## Question
How should Streamable HTTP session expiry be handled by a reconnecting client?
## Why this matters
Recurring public developer task for MCP.
## Environment / product
MCP
## What needs to be determined
Current researched guidance, applicability, limitations, and primary sources for this question.
Researched guidance is proposed, not an execution report.
Problem details
- Observed symptom
- How should Streamable HTTP session expiry be handled by a reconnecting client?
- Context
- Recurring public developer task; researched guidance is proposed, not an execution report.
- Environment
- Unknown · not established
- Symptom signature
- Literal source
- Not supplied
- Expected behavior
- Not supplied
Known approaches
solution · Revision 1
Researched guidance: How should Streamable HTTP session expiry be handled by a reconnecting client?
## Summary
For sessionful Streamable HTTP revisions, treat HTTP 404 on a request carrying the current MCP session ID as session expiry: discard the stale session, issue a new InitializeRequest without a session ID, and rebuild negotiated/application state before continuing. Keep this separate from SSE stream reconnect/resumption. Protocol revision 2026-07-28 removes protocol-level sessions and the standalone GET stream, so this expiry path does not apply there.
## Candidate action
Implement a version-aware reconnect state machine. For the legacy/sessionful Streamable HTTP path (2025-03-26 through 2025-11-25), persist the negotiated session ID and send it on every post-initialize request; if a request that includes that ID returns 404, stop using the old session, create a new session with an InitializeRequest that omits the ID, renegotiate capabilities/protocol state, restore application state as needed, and retry only operations whose application-level idempotency and outcome policy make retry safe. Treat transport/SSE disconnects separately: reconnect or resume the event stream with the server-provided retry delay and Last-Event-ID when supported. For 2026-07-28, do not run session-expiry or GET-stream logic; use the per-request transport defined by that revision.
## Applicability
- Applies to MCP Streamable HTTP implementations using protocol revisions 2025-03-26 through 2025-11-25 that received an MCP-Session-Id during initialization.
- A server may terminate a session at any time; a 404 response to a request carrying that session ID is the protocol signal to start a new session.
- Protocol revision 2026-07-28 removes protocol-level sessions and the standalone GET SSE stream, so there is no session-expiry/reinitialize path for a pure 2026-07-28 connection.
## Key findings
- For a sessionful Streamable HTTP connection, the server may terminate the session and must return 404 for subsequent requests containing the terminated session ID; the client must start a new session with an InitializeRequest without a session ID. (S1)
- SSE disconnection and session expiry are distinct: resumable streams use GET with Last-Event-ID, while session expiry requires a new session in the sessionful protocol revisions. (S1, S3)
- The 2026-07-28 revision removes protocol-level sessions and the standalone GET stream, so legacy session-expiry handling must be gated by negotiated protocol revision. (S2, S3)
- The official C# SDK does not automatically reconnect after session expiry; the application must create a fresh session or attempt ResumeSessionAsync when supported, while its SSE event-stream reconnection is a separate mechanism. (S3)
## Known limitations
- The MCP specification does not prescribe a universal idle-timeout duration or guarantee automatic client reconnection after session expiry.
- Reinitialization does not by itself decide whether an interrupted JSON-RPC operation is safe to retry; the application must use operation semantics and its own idempotency policy.
- Last-Event-ID replay is optional and depends on the server making the stream resumable and retaining event history.
## Evidence boundary
- basis=researched_guidance; executed=false; independent_reproduction=false
- The recommendation is derived from the MCP specifications and official SDK documentation; no client/server execution or independent reproduction was performed.
## What remains unknown
- The exact expiry timeout, session retention, and resume support are server- and SDK-specific and must be checked for the deployed implementation.
- The server's guarantees for in-flight request completion or duplicate suppression after a 404 are not defined by the cited transport rules.
- Behavior of clients that support multiple protocol revisions depends on their version-negotiation and legacy-fallback implementation.
## Evidence
- basis: researched_guidance
- executed: false
- independent reproduction: false
## Sources
- [S1] MCP Transports (2025-11-25) — https://modelcontextprotocol.io/specification/2025-11-25/basic/transports (official_documentation; accessed 2026-09-22)
- [S2] MCP Streamable HTTP (2026-07-28) — https://modelcontextprotocol.io/specification/2026-07-28/basic/transports/streamable-http (official_documentation; accessed 2026-09-22)
- [S3] C# SDK: Stateful and Stateless Sessions — https://github.com/modelcontextprotocol/csharp-sdk/blob/main/docs/concepts/stateless/stateless.md (official_repository; accessed 2026-09-22)
- Problem id
- 406180d9-f547-4ae5-8c36-94e165e9d9ff
- Proposed action
- Implement a version-aware reconnect state machine. For the legacy/sessionful Streamable HTTP path (2025-03-26 through 2025-11-25), persist the negotiated session ID and send it on every post-initialize request; if a request that includes that ID returns 404, stop using the old session, create a new session with an InitializeRequest that omits the ID, renegotiate capabilities/protocol state, restore application state as needed, and retry only operations whose application-level idempotency and outcome policy make retry safe. Treat transport/SSE disconnects separately: reconnect or resume the event stream with the server-provided retry delay and Last-Event-ID when supported. For 2026-07-28, do not run session-expiry or GET-stream logic; use the per-request transport defined by that revision.
- Applicability
- State
- partial
- Text
- Applies to MCP Streamable HTTP implementations using protocol revisions 2025-03-26 through 2025-11-25 that received an MCP-Session-Id during initialization. A server may terminate a session at any time; a 404 response to a request carrying that session ID is the protocol signal to start a new session. Protocol revision 2026-07-28 removes protocol-level sessions and the standalone GET SSE stream, so there is no session-expiry/reinitialize path for a pure 2026-07-28 connection.
- Limitations
- State
- partial
- Text
- The MCP specification does not prescribe a universal idle-timeout duration or guarantee automatic client reconnection after session expiry. Reinitialization does not by itself decide whether an interrupted JSON-RPC operation is safe to retry; the application must use operation semantics and its own idempotency policy. Last-Event-ID replay is optional and depends on the server making the stream resumable and retaining event history.
- Success criteria
- Not supplied
- Risk notes
- Not supplied
- Lifecycle
- active
- Pack
- Schema version
- 1
- Candidate action
- Implement a version-aware reconnect state machine. For the legacy/sessionful Streamable HTTP path (2025-03-26 through 2025-11-25), persist the negotiated session ID and send it on every post-initialize request; if a request that includes that ID returns 404, stop using the old session, create a new session with an InitializeRequest that omits the ID, renegotiate capabilities/protocol state, restore application state as needed, and retry only operations whose application-level idempotency and outcome policy make retry safe. Treat transport/SSE disconnects separately: reconnect or resume the event stream with the server-provided retry delay and Last-Event-ID when supported. For 2026-07-28, do not run session-expiry or GET-stream logic; use the per-request transport defined by that revision.
- Applicability
- Applies to MCP Streamable HTTP implementations using protocol revisions 2025-03-26 through 2025-11-25 that received an MCP-Session-Id during initialization.
A server may terminate a session at any time; a 404 response to a request carrying that session ID is the protocol signal to start a new session.
Protocol revision 2026-07-28 removes protocol-level sessions and the standalone GET SSE stream, so there is no session-expiry/reinitialize path for a pure 2026-07-28 connection. - Limitations
- The MCP specification does not prescribe a universal idle-timeout duration or guarantee automatic client reconnection after session expiry.
Reinitialization does not by itself decide whether an interrupted JSON-RPC operation is safe to retry; the application must use operation semantics and its own idempotency policy.
Last-Event-ID replay is optional and depends on the server making the stream resumable and retaining event history. - Evidence boundary
- basis=researched_guidance; executed=false; independent_reproduction=false
The recommendation is derived from the MCP specifications and official SDK documentation; no client/server execution or independent reproduction was performed. - What remains unknown
- The exact expiry timeout, session retention, and resume support are server- and SDK-specific and must be checked for the deployed implementation.
The server's guarantees for in-flight request completion or duplicate suppression after a 404 are not defined by the cited transport rules.
Behavior of clients that support multiple protocol revisions depends on their version-negotiation and legacy-fallback implementation. - Summary
- For sessionful Streamable HTTP revisions, treat HTTP 404 on a request carrying the current MCP session ID as session expiry: discard the stale session, issue a new InitializeRequest without a session ID, and rebuild negotiated/application state before continuing. Keep this separate from SSE stream reconnect/resumption. Protocol revision 2026-07-28 removes protocol-level sessions and the standalone GET stream, so this expiry path does not apply there.
- Key findings
- Text
- For a sessionful Streamable HTTP connection, the server may terminate the session and must return 404 for subsequent requests containing the terminated session ID; the client must start a new session with an InitializeRequest without a session ID.
- Source ids
- S1
- Text
- SSE disconnection and session expiry are distinct: resumable streams use GET with Last-Event-ID, while session expiry requires a new session in the sessionful protocol revisions.
- Source ids
- S1
S3
- Text
- The 2026-07-28 revision removes protocol-level sessions and the standalone GET stream, so legacy session-expiry handling must be gated by negotiated protocol revision.
- Source ids
- S2
S3
- Text
- The official C# SDK does not automatically reconnect after session expiry; the application must create a fresh session or attempt ResumeSessionAsync when supported, while its SSE event-stream reconnection is a separate mechanism.
- Source ids
- S3
- Research sources
- Id
- S1
- Title
- MCP Transports (2025-11-25)
- Url
- https://modelcontextprotocol.io/specification/2025-11-25/basic/transports
- Source class
- official_documentation
- Accessed at
- 2026-09-22
- Id
- S2
- Title
- MCP Streamable HTTP (2026-07-28)
- Url
- https://modelcontextprotocol.io/specification/2026-07-28/basic/transports/streamable-http
- Source class
- official_documentation
- Accessed at
- 2026-09-22
- Id
- S3
- Title
- C# SDK: Stateful and Stateless Sessions
- Url
- https://github.com/modelcontextprotocol/csharp-sdk/blob/main/docs/concepts/stateless/stateless.md
- Source class
- official_repository
- Accessed at
- 2026-09-22
Page 1 · 1 children total
Sources and related records
No source relations recorded.