Skip to content

Conversation

@joseairosa
Copy link

Summary

This PR adds proper handling for HTTP 410 Gone responses in StreamableHTTPClientTransport, enabling seamless reconnection when MCP sessions expire or servers restart.

Problem

When an MCP server restarts or a session times out, the server returns HTTP 410 Gone to indicate the session ID is no longer valid. Currently, the client:

  1. Throws an error on 410
  2. Retains the stale session ID in _sessionId
  3. Sends the same invalid session ID on all subsequent requests
  4. Gets 410 repeatedly, breaking the connection permanently

This creates a poor user experience where MCP connections become permanently broken after server restarts, requiring users to manually restart their client applications.

Real-world scenario

Client                          Server
  |                               |
  |-- POST (session: abc-123) --->|
  |                               | (server restarts, session gone)
  |<-------- 410 Gone ------------|
  |                               |
  |-- POST (session: abc-123) --->|  <- Still sending stale ID!
  |<-------- 410 Gone ------------|
  |                               |
  |-- POST (session: abc-123) --->|  <- Stuck in loop
  |<-------- 410 Gone ------------|
  ...forever...

Solution

Handle 410 responses by:

  1. Clearing the stale _sessionId
  2. Automatically retrying the request
  3. Server assigns a new session ID on the retry

This follows the same pattern already used for 401 (auth) and 403 (scope) responses.

After this fix

Client                          Server
  |                               |
  |-- POST (session: abc-123) --->|
  |                               | (server restarts, session gone)
  |<-------- 410 Gone ------------|
  |                               |
  |-- POST (no session ID) ------>|  <- Retry without stale ID
  |<-- 200 OK (session: xyz-789) -|  <- New session assigned
  |                               |
  |-- POST (session: xyz-789) --->|  <- Working again!
  |<-------- 200 OK --------------|

Changes

  • send() method: Added 410 handling that clears session ID and retries POST requests
  • _startOrAuthSse() method: Added 410 handling that clears session ID and retries SSE GET connections
  • Tests: Added comprehensive tests for both POST and GET 410 scenarios

Testing

All existing tests pass, plus 2 new tests:

  • should clear session ID and retry on 410 during POST request
  • should clear session ID and retry on 410 during SSE GET request
cd packages/client && pnpm test
# ✓ 42 tests passed

Related

This complements the server-side behavior where servers should return 410 Gone for expired sessions, as documented in the MCP Streamable HTTP transport specification.

When a server returns HTTP 410 Gone (indicating the session no longer exists),
the client now automatically clears the stale session ID and retries the request.
This enables seamless reconnection after server restarts or session timeouts.

Previously, receiving a 410 would throw an error but the client would retain
the invalid session ID, causing all subsequent requests to fail with the same
410 error - breaking the connection permanently until the client was restarted.

Changes:
- Add 410 handling in send() method for POST requests
- Add 410 handling in _startOrAuthSse() for SSE GET requests
- Clear _sessionId before retrying to allow server to assign a new session
- Add comprehensive tests for both POST and GET 410 scenarios

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@joseairosa joseairosa requested a review from a team as a code owner January 19, 2026 03:40
@changeset-bot
Copy link

changeset-bot bot commented Jan 19, 2026

🦋 Changeset detected

Latest commit: b4124d1

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@modelcontextprotocol/client Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new
Copy link

pkg-pr-new bot commented Jan 19, 2026

Open in StackBlitz

@modelcontextprotocol/client

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/client@1402

@modelcontextprotocol/server

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/server@1402

@modelcontextprotocol/express

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/express@1402

@modelcontextprotocol/hono

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/hono@1402

@modelcontextprotocol/node

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/node@1402

commit: b4124d1

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.

1 participant