Repository navigation
Migrate MCP transport from SSE to Streamable HTTP (spec 2026-07-28) #1750
Copy link
Copy link
Open
Description
Summary
Current MCP transport implementation uses the deprecated HTTP+SSE transport (2024-11-05 era) via mcp SDK 1.x, pinned <2 because of the decorator API (@mcp_server.list_tools()/@mcp_server.call_tool()) removed in SDK 2.x. Migrate to Streamable HTTP per the latest spec (2026-07-28).
Current state
src/codegraphcontext/api/mcp_sse.py:ServerfrommcpSDK 1.x,SseServerTransport("/api/v1/mcp/messages"), two endpoints (GET /api/v1/mcp/sse,POST /api/v1/mcp/messages), custom_SendTracker/_AlreadySentResponseshims to bridge SDK's raw ASGI writes with FastAPI.src/codegraphcontext/api/app.py: wires both routes behindrequire_api_key.src/codegraphcontext/server.py: separate hand-rolled stdio JSON-RPC loop (MCPServer._run_loop), duplicating tool-list/tool-call dispatch logic independently of the SSE path, advertisingprotocolVersion: 2025-03-26manually.pyproject.toml:mcp>=1.0.0,<2pin with a comment explaining the 2.x decorator API removal blocks the upgrade.
Target state
- Bump to
mcp>=2,<3(latest 2.2.0 already ships a_streamable_http_modern.pymodule purpose-built for spec 2026-07-28). - Replace
mcp_sse.py'sSseServerTransport/shims withmcp.server.lowlevel.Server(on_list_tools=..., on_call_tool=...)and itsstreamable_http_app(streamable_http_path="/api/v1/mcp", host="127.0.0.1", ...), mounted once. The SDK'sStreamableHTTPSessionManagerauto-classifies each request byMCP-Protocol-Versionheader and routes legacy Streamable HTTP clients (2025-03-26 through 2025-11-25, session-based) and modern 2026-07-28 clients (per-request, no session) to the correct internal handler — no manual dual-endpoint hosting needed for anything from 2025-03-26 onward. - Collapse the two existing routes (
/api/v1/mcp/sseGET,/api/v1/mcp/messagesPOST) into the single mounted endpoint. Auth (require_api_key) needs rewiring onto the new mount (SDK'stoken_verifier/auth_server_providerparams, or a wrapping FastAPI dependency/middleware). - Add
Originheader validation (spec MUST, DNS-rebinding protection) — SDK'sstreamable_http_appauto-enables this for localhost, needs confirming/extending for the app's actual host config. - The oldest 2024-11-05 HTTP+SSE transport (standalone GET SSE stream + separate POST endpoint, pre-dating any session model) is NOT covered by the new SDK transport manager. Only keep the current literal
/sse+/messagesroutes alive if a real client still needs that exact wire format; otherwise drop them. - Unify stdio (
server.py) and HTTP tool dispatch where practical — both converge on the same request shape under 2026-07-28 (no session, per-request metadata), removing today's duplicated tool-list/tool-call logic. - Update/rewrite
tests/unit/api/for the new single-endpoint POST flow.
Non-goals
- No changes required to
mcp.server.stdio-based transport semantics beyond what naturally falls out of shared dispatch cleanup (stdio isn't touched by the 2026-07-28 transport revision itself).
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Type
Projects
- StatusShow more project fieldsBacklog tasks
- StatusShow more project fieldsNo status
Activity
github-actions commentedon Sep 30, 2026
Hi! 👋 Join our CodeGraphContext Discord channel to collaborate: https://discord.gg/dR4QY32uYQ
Shashankss1205 commentedon Oct 9, 2026
#1751 plus #1747 were combined locally with preserved awaited get_server calls in both MCP 2 handlers. All 43 API tests passed under MCP 2.3. The PR review records the integration adjustment. This issue remains open for stdio dispatch consolidation and transport acceptance beyond the HTTP migration.
Shashankss1205 commentedon Oct 15, 2026
Maintenance review — 15 October 2026
#1772 integrates #1751 with #1747's awaited gateway binding. All 43 API tests pass under MCP 2.3, including auth/origin and legacy/modern transport checks. Stdio dispatch consolidation remains outside this transport PR.
Shashankss1205 commentedon Oct 15, 2026
The transport portion is now merged through #1772 (including #1751's original commits and the #1747 async integration). All CI checks pass, including Python builds, platform E2E and strict parity; all 43 dedicated API tests passed locally under MCP 2.3. New integrations can use /api/v1/mcp; legacy SSE remains supported with auth/Origin checks. Keeping this issue open for the explicitly separate stdio-dispatch consolidation.
Shashankss1205 commentedon Oct 15, 2026
Correction to the previous status: GitHub rejected #1772's merge with a stale/conflicting merge state after the batching integration landed. The source merges cleanly with current main locally; I am publishing that explicit merge and will wait for checks on the updated head. The transport work is reviewed, but is not yet merged.
Shashankss1205 commentedon Oct 15, 2026
Final verified status: #1772 merged successfully at 2908a70 after every updated-head check passed; original #1751 is now also marked merged. This supersedes the temporary merge-conflict status above. Streamable HTTP and the retained legacy SSE routes are on main, with serving-loop binding and auth/Origin checks covered. The final combined source passes 1,695 unit tests (8 skipped). Keeping #1750 open for the separate stdio-dispatch consolidation.
feat(mcp): migrate transport from SSE to Streamable HTTP (spec 2026-0…