Files
AegisGitea-MCP/docs/adr/0002-official-sdk-low-level-server.md
T
Latte 8b7bb7205c docs: phase 0 audit, chunk plan, ADRs and pinned Gitea 28.1.0 swagger
Inventory and gap analysis of the 0.2.0 codebase against the full Gitea API
and the official gitea-mcp toolset, the B1..B11 + security chunk plan, ADRs
0001-0006 for the full-access rebuild, SDK/OAuth research notes, and the
instance swagger pinned for tool generation. The audit-logging doc moves to
docs/audit-logging.md.
2026-10-14 15:34:48 +02:00

1.5 KiB

ADR 0002: official MCP SDK, low-level server

Status: accepted (2026-10-14)

Context

The mission asks for the official MCP Python SDK (FastMCP). In mcp 2.x (current stable 2.3.0) FastMCP was renamed MCPServer. Its add_tool() always derives the input schema from a Python function signature and cannot accept a raw JSON schema. We register 538 tools whose schemas come from the Gitea OpenAPI spec. The SDK's low-level mcp.server.Server takes raw Tool(input_schema=...) objects and offers the same streamable_http_app(auth=..., token_verifier=..., auth_server_provider=..., custom_starlette_routes=...) wiring as MCPServer. Details: docs/research/sdk-oauth-gitea.md section 2.

Decision

  • Depend on mcp>=2.3,<3.
  • Build one low-level Server from the generated catalog with a single on_list_tools and a single on_call_tool dispatcher.
  • Serve it over stdio_server() and over server.streamable_http_app(...) run by uvicorn. The FastAPI app, the hand-rolled JSON-RPC protocol and the [server] extra are removed; mcp already brings Starlette and uvicorn.
  • Validate arguments ourselves with jsonschema (v2 does not).
  • Tool failures are returned as CallToolResult(is_error=True) so the model can read them; only protocol problems raise MCPError.

Consequences

Same package, same transports and auth stack as MCPServer, without private API hacks. The core no longer needs a web-free boundary test: both transports come from the SDK.