feat: transparent session migration on server restart#2584
Open
emiapwil wants to merge 1 commit into
Open
Conversation
When a StreamableHTTP server restarts, client sessions are lost and the server returns 404 'Session not found' for any request using an old session ID. Clients (OpenCode, etc.) do not automatically reinitialize, leaving the connection permanently broken. This change: 1. Detects unknown/expired session IDs and creates a new transport using the client's original session ID, so session ID header validation passes. 2. Starts the new transport in stateless mode (pre-initialized) so the client's first non-initialize request is accepted immediately without requiring the full MCP initialization handshake. Closes modelcontextprotocol#1121
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When a StreamableHTTP MCP server restarts (e.g., the MCP bridge process crashes or is restarted), all client sessions are lost. The server returns "Session not found" (404) for any subsequent request using the old session ID. Most clients do not automatically reinitialize, leaving the connection permanently broken until the client is manually restarted.
Solution
Transparent session migration. When a request arrives with a session ID that is not found in the server's active session table (indicating a server restart), the server now:
_validate_session()passes naturally.stateless=Truemode (pre-initialized) so the client's first non-initialize request is accepted immediately, without requiring the full MCP initialization handshake (initialize→notifications/initialized).After these changes, the server handles three session states:
session_idexists in_server_instancessession_idisNonesession_idis set but not in_server_instancesstateless=TrueTesting
Using the Python test client below to verify session migration:
Server log shows:
Related issue
Closes #1821