When a bridge is restarted and resumes a stateful Streamable HTTP session with the persisted MCP-Session-Id (e.g. crash recovery), the SDK v2 client intentionally skips the initialize handshake, so getNegotiatedProtocolVersion() returns undefined. mcpc never seeds the reconstructed transport with the previously negotiated version, so:
- session details show
Protocol: unknown (stateful) and lose the Server: line,
- all requests on the resumed connection are sent without the required
MCP-Protocol-Version header (spec violation; strict servers may reject them).
Repro (against the legacy e2e test server):
mcpc connect http://localhost:13456/mcp @web # Protocol: 2025-11-25 (stateful)
kill -9 <bridge pid> # crash, no graceful DELETE
mcpc @web ping # auto-restart resumes the session
mcpc @web # Protocol: unknown (stateful), no Server line
The SDK provides StreamableHTTPClientTransportOptions.protocolVersion for exactly this case: "When reconnecting with a preserved sessionId, set this to the version negotiated during the original handshake so the reconnected transport continues sending the required header." mcpc persists protocolVersion in sessions.json but never passes it back on resumption.
Related: this is the SDK v2 successor of the stdio symptom in modelcontextprotocol/typescript-sdk#1468 (stdio detection itself is fixed by the v2 getNegotiatedProtocolVersion(); only the resume path remains affected).
When a bridge is restarted and resumes a stateful Streamable HTTP session with the persisted
MCP-Session-Id(e.g. crash recovery), the SDK v2 client intentionally skips the initialize handshake, sogetNegotiatedProtocolVersion()returnsundefined. mcpc never seeds the reconstructed transport with the previously negotiated version, so:Protocol: unknown (stateful)and lose theServer:line,MCP-Protocol-Versionheader (spec violation; strict servers may reject them).Repro (against the legacy e2e test server):
The SDK provides
StreamableHTTPClientTransportOptions.protocolVersionfor exactly this case: "When reconnecting with a preserved sessionId, set this to the version negotiated during the original handshake so the reconnected transport continues sending the required header." mcpc persistsprotocolVersionin sessions.json but never passes it back on resumption.Related: this is the SDK v2 successor of the stdio symptom in modelcontextprotocol/typescript-sdk#1468 (stdio detection itself is fixed by the v2
getNegotiatedProtocolVersion(); only the resume path remains affected).