fix: prevent infinite reconnection loop when SSE stream drops without response#2512
Open
dragogargo wants to merge 2 commits intomodelcontextprotocol:mainfrom
Open
fix: prevent infinite reconnection loop when SSE stream drops without response#2512dragogargo wants to merge 2 commits intomodelcontextprotocol:mainfrom
dragogargo wants to merge 2 commits intomodelcontextprotocol:mainfrom
Conversation
added 2 commits
April 27, 2026 19:17
… response When the server accepts SSE connections but closes the stream without delivering a complete JSON-RPC response, the client retried forever because _handle_reconnection reset the attempt counter to 0 on each reconnection. Now the attempt counter only resets when real data (not just priming events) was received, indicating the server made progress. When the server only sends empty priming events and drops, the counter increments and the client gives up after MAX_RECONNECTION_ATTEMPTS. Also report a JSONRPCError back to the caller when max attempts are exceeded, so call_tool returns an error instead of hanging forever. Fixes modelcontextprotocol#2393
The isinstance check for JSONRPCRequest always evaluates to True because _handle_reconnection is only called for request messages. Mark the branch with pragma: no branch to satisfy 100% branch coverage.
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.
Motivation and Context
Fixes #2393.
_handle_reconnection()resets theattemptcounter to0when a reconnection succeeds at the HTTP level but the stream ends without delivering a complete JSON-RPC response. This makesMAX_RECONNECTION_ATTEMPTSineffective — the counter only applies to consecutive exceptions, not total reconnection attempts. If the server accepts the connection but the stream drops repeatedly (sending only priming events), the client retries forever.In production this causes MCP client coroutines to hang indefinitely when a server experiences transient stream drops.
How Has This Been Tested?
test_handle_reconnection_stops_after_max_attempts) that mocksaconnect_sseto simulate a server sending only priming events then dropping. Verifies the client gives up afterMAX_RECONNECTION_ATTEMPTSand sends aJSONRPCErrorback to the caller.test_streamable_http.pytests pass, includingtest_streamable_http_multiple_reconnections(3 legitimate reconnections with real data).Changes
JSONRPCErrorback throughread_stream_writersocall_toolreturns an error instead of hanging forever.Breaking Changes
No.
Types of changes
Checklist