feat: harden local stdio MCP, CI package smoke, CLAUDE.md conventions #64

Merged
Latte merged 4 commits from feat/local-mcp-hardening-and-ci into dev 2026-06-27 13:29:11 +00:00
Owner

Summary

Hardens the local stdio MCP transport, proves it end-to-end, records project conventions in CLAUDE.md, and makes the Gitea workflows complete by testing the package build in CI.

Local MCP (stdio) — made solid

  • stdout is now strictly reserved for the JSON-RPC stream. _configure_stderr_logging() pins all logging to stderr and rewrites any stray stdout handler, so a log line can never corrupt the protocol (the classic stdio-MCP failure).
  • Extracted a pure, testable build_server() from _serve().
  • End-to-end tests over the mcp in-memory transport: initialize + tools/list + tools/call, covering a successful round trip and a policy denial surfaced as an MCP error (not a crash).

CLAUDE.md

  • No AI attribution anywhere in the project (commits, PRs, releases, comments, docs).
  • Documented the stdio transport invariants (stdout reserved, build_server vs _serve).

Workflows — complete & tested

  • New package job in test.yml: uv build, then smoke-test both install profiles —
    • core install excludes the web stack and the aegis-gitea-mcp stdio entry exits 2 with an actionable message;
    • the [server] extra pulls in fastapi/uvicorn and imports the server entry.
  • Catches packaging / console-script regressions on every push and PR.

Verification

  • ruff + ruff-format + black + mypy (strict) clean.
  • pytest: 350 passed, 1 skipped; coverage 83.99% (threshold 80%).
  • Locally mirrored the CI package smoke: core wheel installs without FastAPI; stdio entry exits 2.
## Summary Hardens the local stdio MCP transport, proves it end-to-end, records project conventions in `CLAUDE.md`, and makes the Gitea workflows complete by testing the package build in CI. ### Local MCP (stdio) — made solid - **stdout is now strictly reserved for the JSON-RPC stream.** `_configure_stderr_logging()` pins all logging to stderr and rewrites any stray stdout handler, so a log line can never corrupt the protocol (the classic stdio-MCP failure). - Extracted a pure, testable `build_server()` from `_serve()`. - **End-to-end tests over the `mcp` in-memory transport**: `initialize` + `tools/list` + `tools/call`, covering a successful round trip and a policy denial surfaced as an MCP error (not a crash). ### CLAUDE.md - **No AI attribution** anywhere in the project (commits, PRs, releases, comments, docs). - Documented the stdio transport invariants (stdout reserved, `build_server` vs `_serve`). ### Workflows — complete & tested - New `package` job in `test.yml`: `uv build`, then smoke-test **both** install profiles — - core install excludes the web stack and the `aegis-gitea-mcp` stdio entry exits 2 with an actionable message; - the `[server]` extra pulls in fastapi/uvicorn and imports the server entry. - Catches packaging / console-script regressions on every push and PR. ### Verification - ruff + ruff-format + black + mypy (strict) clean. - pytest: 350 passed, 1 skipped; coverage 83.99% (threshold 80%). - Locally mirrored the CI package smoke: core wheel installs without FastAPI; stdio entry exits 2.
Latte added the Kind/DocumentationKind/EnhancementKind/Chore labels 2026-06-27 13:20:14 +00:00
Latte added 3 commits 2026-06-27 13:20:15 +00:00
Reserve stdout for the JSON-RPC stream: _configure_stderr_logging() pins all
logging to stderr (and rewrites any stray stdout handler) so a log line can
never corrupt the stdio protocol. Extract a pure, testable build_server() from
_serve(). Add end-to-end tests over the mcp in-memory transport (initialize +
tools/list + tools/call), covering a successful round trip and a policy denial
surfaced as an MCP error.
Record that no 'Generated with Claude Code' / Co-Authored-By / 'made by Claude'
attribution may appear in commits, PRs, releases, comments or docs. Add stdio
transport notes (stdout reserved for JSON-RPC, build_server vs _serve).
ci: build the package and smoke-test both install profiles
docker / test (pull_request) Successful in 34s
docker / test (push) Successful in 36s
docker / lint (pull_request) Successful in 39s
docker / lint (push) Successful in 40s
test / test (push) Successful in 42s
test / package (pull_request) Failing after 2m27s
lint / lint (pull_request) Successful in 43s
lint / lint (push) Successful in 43s
test / test (pull_request) Successful in 44s
docker / docker (pull_request) Successful in 1m10s
docker / docker (push) Successful in 34s
test / package (push) Failing after 2m5s
3d527f8690
Add a package job to the test workflow: uv build, then verify a clean core
install excludes the web stack and the aegis-gitea-mcp stdio entry exits 2 with
an actionable message, and that the [server] extra pulls in fastapi/uvicorn and
imports the server entry. Catches packaging/console-script regressions in CI.
Latte added 1 commit 2026-06-27 13:27:02 +00:00
ci: stop artifact upload from failing the build on Gitea runners
docker / test (push) Successful in 34s
docker / lint (push) Successful in 40s
lint / lint (push) Successful in 43s
docker / lint (pull_request) Successful in 43s
docker / test (pull_request) Successful in 34s
test / test (push) Successful in 44s
lint / lint (pull_request) Successful in 44s
test / package (push) Successful in 1m8s
test / test (pull_request) Successful in 44s
test / package (pull_request) Successful in 53s
docker / docker (push) Successful in 1m5s
docker / docker (pull_request) Successful in 43s
4db37d200e
Gitea's act_runner does not reliably support the actions/upload-artifact@v4
backend. Drop the artifact upload from the test workflow (the package job's
purpose is to build and smoke-test, not to store wheels) and make the publish
workflow's upload best-effort (continue-on-error) so a flaky artifact backend
cannot block a release — the package is still published to the registry.
Latte merged commit 2bb74807bc into dev 2026-06-27 13:29:11 +00:00
Latte deleted branch feat/local-mcp-hardening-and-ci 2026-06-27 13:29:11 +00:00
Sign in to join this conversation.