claude-code - 💡(How to fix) Fix MCP Streamable HTTP client: surface session_terminated to model instead of auto-reinitializing per spec [2 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#56264Fetched 2026-05-06 06:32:47
View on GitHub
Comments
2
Participants
2
Timeline
5
Reactions
0
Author
Timeline (top)
labeled ×3commented ×2

Error Message

Streamable HTTP error: Error POSTing to endpoint: {"type":"error","error":{"type":"not_found_error","message":"MCP session has been terminated or no longer exists on the server.","details":{"error_code":"mcp_session_terminated"}},"request_id":"req_011Caj9XocsEiGmk1EK83q7T"}

Fix Action

Fix / Workaround

The 2026 MCP roadmap calls this out explicitly as a top problem ("stateful sessions fight with load balancers") and the canonical persistence pattern is still unresolved upstream (modelcontextprotocol/python-sdk#880). Servers can mitigate (we have — see "Workaround" below), but every server doing it independently doesn't scale; the spec puts the responsibility on the client and the client is the right layer to fix this in once for everyone.

This is the spec-prescribed behaviour and the only way I'm aware of to deliver consistent UX across surfaces (Code, Desktop, mobile, web) without each MCP server independently implementing server-side workarounds.

Workaround we shipped (alfred-shell)

Code Example

Streamable HTTP error: Error POSTing to endpoint: {"type":"error","error":{"type":"not_found_error","message":"MCP session has been terminated or no longer exists on the server.","details":{"error_code":"mcp_session_terminated"}},"request_id":"req_011Caj9XocsEiGmk1EK83q7T"}
RAW_BUFFERClick to expand / collapse

Symptom

When the user's MCP server sleeps, redeploys, or returns 404 mcp_session_terminated for any other reason, claude-code surfaces the error to the model as a tool result instead of auto-reinitialising the session and replaying the call. The model sees something like:

Streamable HTTP error: Error POSTing to endpoint: {"type":"error","error":{"type":"not_found_error","message":"MCP session has been terminated or no longer exists on the server.","details":{"error_code":"mcp_session_terminated"}},"request_id":"req_011Caj9XocsEiGmk1EK83q7T"}

…in the middle of an otherwise-successful conversation. The next tool call usually succeeds (the client does re-init implicitly on the next request — it just leaks the failure of the one that triggered it).

Why it's a bug, not a feature

Per the MCP Streamable HTTP spec, §Session Management point 4:

When a client receives HTTP 404 in response to a request containing an MCP-Session-Id, it MUST start a new session by sending a new InitializeRequest without a session ID attached.

The spec is explicit that 404 mcp_session_terminated is a normal lifecycle event the client must transparently handle — not an error to surface to the model. claude-code's current behaviour is non-spec-compliant.

Repro

Any production MCP server that drops in-memory sessions across process boundaries reproduces this. Common shapes:

  • Fly.io / GCP Cloud Run / AWS ECS auto-stop: the server's machine sleeps after idle, wakes on the next request as a fresh process with empty session state.
  • Server redeploy: same effect.
  • Horizontal scaling without sticky sessions: a different replica gets the request than handled the initialize.
  • Network blip that the upstream proxy translates to a session-loss.

The 2026 MCP roadmap calls this out explicitly as a top problem ("stateful sessions fight with load balancers") and the canonical persistence pattern is still unresolved upstream (modelcontextprotocol/python-sdk#880). Servers can mitigate (we have — see "Workaround" below), but every server doing it independently doesn't scale; the spec puts the responsibility on the client and the client is the right layer to fix this in once for everyone.

Desired behaviour

When the Streamable HTTP transport gets back a 404 with the structured mcp_session_terminated shape (or any 404 to a request bearing an mcp-session-id):

  1. Discard the local mcp-session-id cookie.
  2. POST a fresh InitializeRequest to the same endpoint without a session-id, capture the new id from the response header.
  3. Re-issue the original tool call against the new session.
  4. Return the tool's actual result to the model. Surface the error only if step 2 or 3 also fails (a real outage rather than a stale session).

This is the spec-prescribed behaviour and the only way I'm aware of to deliver consistent UX across surfaces (Code, Desktop, mobile, web) without each MCP server independently implementing server-side workarounds.

Workaround we shipped (alfred-shell)

Until claude-code lands the spec-compliant client behaviour, our MCP server now lazy-recreates sessions: on a request with an unknown mcp-session-id and a valid auth token, it transparently creates a fresh transport bound to that exact id rather than 404'ing. Source if useful as a reference: zulven/alfred@3e16e1e — alfred-shell/src/http.ts.

This works around the symptom for our users but doesn't fix it for the broader MCP ecosystem — most third-party MCP servers will still 404, and end-users on Code / Desktop / mobile will still see the error mid-conversation.

Severity

Medium. Not a hard failure — the next tool call usually succeeds, so it's recoverable. But it leaks an internal protocol detail to the model (which then often "narrates" the failure to the user, training in a "retry" pattern), and reduces trust in the MCP layer. Easy fix at exactly one layer.

Happy to provide more detail or test fixes against alfred-shell if useful.

extent analysis

TL;DR

The client should be modified to handle 404 mcp_session_terminated errors by reinitializing the session and replaying the call, rather than surfacing the error to the model.

Guidance

  • When the client receives a 404 mcp_session_terminated error, it should discard the local mcp-session-id cookie and POST a fresh InitializeRequest to the same endpoint without a session-id.
  • The client should capture the new session id from the response header and re-issue the original tool call against the new session.
  • The client should only surface the error to the model if the reinitialization or replay of the call fails.
  • The MCP server's workaround of lazy-recreating sessions can be used as a temporary solution, but it does not fix the underlying issue and may not work for all third-party MCP servers.

Example

No code example is provided as the issue does not contain sufficient information about the client's implementation.

Notes

The fix requires modifying the client to handle 404 mcp_session_terminated errors in a spec-compliant manner. The MCP server's workaround can be used as a temporary solution, but it is not a substitute for fixing the client.

Recommendation

Apply the workaround of modifying the client to handle 404 mcp_session_terminated errors, as it is the most straightforward way to fix the issue and ensure spec-compliant behavior.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING