fix(mcp): disable deprecated SSE transport — GHB-189#97
Merged
Gastonfoncea merged 1 commit intoMay 17, 2026
Merged
Conversation
`/api/mcp/sse` was timing out in prod with 0 bytes received (no HTTP headers). Root cause: mcp-handler 1.1.0's SSE handler hard- requires a TCP Redis URL via REDIS_URL/KV_URL env vars. Our Vercel project has Upstash via Marketplace but only the REST-API env vars (KV_REST_API_URL/_TOKEN) are auto-injected — the TCP URL is not. Without it, initializeRedis() throws synchronously before flushing any response, so the Vercel runtime kills the function and the client sees a 0-byte hang. The README "Redis (optional, for SSE)" is misleading; in the code Redis is mandatory for SSE. Fix: set `disableSse: true` in createMcpHandler config. Per mcp- handler's own type docs, SSE was removed from the MCP spec on 2025-03-26, so `/sse` now returns a clean 404 instead of hanging. Streamable HTTP (`/api/mcp/mcp`) remains the canonical transport and continues to work for all current MCP clients (Claude Code, Cursor, Codex, custom SDKs aligned with the latest spec). Verified locally: - /api/mcp/sse → 404 "Not found" - /api/mcp/mcp → 200 with valid MCP initialize handshake Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes GHB-189.
Root cause (found via systematic debugging)
mcp-handler@1.1.0line 381 — the/sseGET handler unconditionally callsinitializeRedis(redisUrl)before flushing any HTTP headers.redisUrldefaults toprocess.env.REDIS_URL || process.env.KV_URL. If neither is set,initializeRedisthrows synchronously with"redisUrl is required", the Vercel function crashes, and the client sees a 0-byte hang until it times out (the symptom reported).Our Vercel project has Upstash provisioned via Marketplace, but the Marketplace integration only auto-injects the REST-API env vars (
KV_REST_API_URL,KV_REST_API_TOKEN) used by our rate-limiter atlib/rate-limit/upstash.ts. The classic TCP Redis URL (KV_URL/REDIS_URL) required bymcp-handleris not injected, and was never added manually.The
mcp-handlerREADME says "Redis (optional, for SSE)" but the source has Redis as mandatory for SSE. ThedisableSseconfig flag exists precisely for this case.Fix
disableSse: truein thecreateMcpHandlerconfig. Per the library's own type docs, SSE was removed from the MCP spec on 2025-03-26:Streamable HTTP (
/api/mcp/mcp) remains the canonical transport. Claude Code, Cursor, Codex CLI, and modern MCP SDKs already speak Streamable HTTP.Verified locally
Test plan
pnpm typecheck(workspace-wide) passespnpm test(workspace-wide) passes/ssereturns clean 404/mcpstill returns valid MCP initialize handshakecurl -i https://mcp.ghbounty.com/api/mcp/ssereturns 404 in <1s (not timeout)mcp.ghbounty.comURL configured) still connects via Streamable HTTPOut of scope
KV_URL(TCP Redis) to actually wire SSE — explicitly rejected because SSE is deprecated upstream and we have no clients that depend on it.🤖 Generated with Claude Code