Skip to content

Fail gracefully instead of resuming a session across a protocol change (#374) - #375

Merged
jancurn merged 2 commits into
mainfrom
claude/mcp-protocol-version-error-thd5fj
Aug 20, 2026
Merged

Fail gracefully instead of resuming a session across a protocol change (#374)#375
jancurn merged 2 commits into
mainfrom
claude/mcp-protocol-version-error-thd5fj

Conversation

@jancurn

@jancurn jancurn commented Aug 20, 2026

Copy link
Copy Markdown
Member

A session could get stuck reconnecting forever after its server upgraded to MCP 2026-07-28: each reconnect replayed the stored MCP-Session-Id, which makes the SDK skip protocol negotiation, so every request went out without the required _meta envelope and was rejected — same id, same rejection, forever.

Session resumption is a 2025-era mechanism, so the fix is to not carry it across protocol versions:

  • A stored session id recorded with a modern (2026-07-28) protocol version is ignored and dropped from sessions.json — the reconnect negotiates afresh and self-heals
  • A resumed legacy session whose server no longer speaks that protocol version is marked expired with a hint to run restart (which reconnects without the id), instead of retry-looping
  • New isProtocolMismatchError() classifier for the wire signatures of an era mismatch
  • E2E regression guard (sessions/stale-session-id, modern matrix column) covering both scenarios, plus unit tests for the classifier

Fixes #374

https://claude.ai/code/session_013JRn5VpCR4jVsXqupVNhzD

claude added 2 commits August 20, 2026 10:45
Reconnecting a session replays the stored MCP-Session-Id, and the SDK skips
version negotiation whenever the transport carries one. The client therefore
never learns the protocol era and emits no per-request `_meta` envelope, while
the transport still stamps the MCP-Protocol-Version header restored from
sessions.json — a combination every 2026-07-28 server rejects. Each reconnect
replayed the same id, so the session could never recover.

- New bridge-side resumption planner: it rebuilds the persisted `server/discover`
  result and hands it to the SDK's `connect({ prior })`, so a resumed modern
  connection knows its era; it refuses to resume when the stored state cannot
  support one (an id left behind by a server that has since gone stateless, no
  persisted discover result, or no overlapping protocol version)
- sessions.json now drops a stored session id when a connection ends up without
  one, instead of keeping it forever
- A resumed connection rejected for a protocol mismatch is retried once from
  scratch with a fresh negotiation, rather than failing every reconnect
- A resumed modern connection opens its own `subscriptions/listen` stream, which
  the SDK only opens on a probed connect, so list-change notifications keep
  arriving
- Added unit tests and an e2e regression guard (sessions/stale-session-id, modern
  matrix column) that reproduces the exact server rejection without the fix

Fixes #374

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013JRn5VpCR4jVsXqupVNhzD
…ol change

Session resumption is a 2025-era mechanism, so don't carry it across protocol
versions: a stored session id recorded with a modern (2026-07-28) protocol
version is ignored and dropped, and a resumed legacy session whose server no
longer speaks that version is marked expired with a hint to run `restart`.
This removes the resumption planner, the SDK connect({ prior }) plumbing, and
the client-side listen-stream reopening from the previous commit.

Refs #374

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013JRn5VpCR4jVsXqupVNhzD
@jancurn jancurn changed the title Fix stale session IDs wedging 2026-07-28 connections (#374) Fail gracefully instead of resuming a session across a protocol change (#374) Aug 20, 2026
@jancurn
jancurn merged commit 0427494 into main Aug 20, 2026
7 checks passed
@jancurn
jancurn deleted the claude/mcp-protocol-version-error-thd5fj branch August 20, 2026 12:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Session to a 2026-07-28 server gets stuck reconnecting: resumed connection sends no _meta envelope

3 participants