Repository navigation
Description
Problem
WebStandardStreamableHTTPServerTransport sets Connection: keep-alive on each SSE Response, but it cannot know the lifetime of the underlying HTTP connection and does not provide a matching Keep-Alive lifetime.
Connection is a hop-by-hop header. The HTTP adapter or server owns that policy. On Node HTTP/1.1, the explicit SDK header suppresses Node automatic output such as:
Connection: keep-alive
Keep-Alive: timeout=5Without the lifetime hint, a pooling client cannot retire an idle socket before the server does and can race a server FIN on a later MCP request. On HTTP/2, Connection is forbidden and must be removed by the adapter.
The header is currently present at three response sites on both main and v1.x.
Expected behavior
The web-standard transport should omit hop-by-hop connection policy. The concrete adapter can then describe the real transport:
- Node HTTP/1.1 emits
Connection: keep-aliveand its configuredKeep-Alive: timeout=...automatically. - HTTP/2 emits neither forbidden hop-by-hop header.
- Other Fetch runtimes remain free to apply their own connection policy.
This does not disable persistent connections and does not require Connection: close. Nearby MCP requests can still reuse a socket, while clients that honor the advertised lifetime can retire it safely and continue the same Mcp-Session-Id on another socket.
Scope
This is separate from SSE comment heartbeats such as #2541. Heartbeats protect an open, temporarily silent SSE body. This issue concerns the idle lifetime of an HTTP connection after a finite response has completed.
Activity
colinaaa commentedon Jul 27, 2026
I have a focused patch for
mainthat removes the three Web Standard SSEConnectionheaders and adds coverage for POST, standalone GET, and Last-Event-ID replay responses. I will send it as a small PR; the stablev1.xfile needs a separate backport.colinaaa commentedon Jul 27, 2026
The verified
v1.xbackport is available ate84b2adb(compare view). It removes the same three headers, adds POST/GET/replay assertions, and passes the full v1 non-E2E suite (1612/1612), typecheck, ESLint, and Prettier. It also applies cleanly with #2547; the combined focused suite passes 176/176.GitHub rejected PR creation against
v1.xfor this read-only external contributor (GraphQL permission denied / REST 404), although #2554 againstmainwas accepted. A maintainer can cherry-pick the commit or open the backport from the compare branch.