fix(server): settle in-flight JSON-mode requests and release their stream mappings (v1.x) - #2747
Open
lvyanyan wants to merge 1 commit into
Open
Conversation
…ream mappings Two lifecycle bugs in JSON response mode on v1.x, tracked in modelcontextprotocol#2559: - send() resolved the pending HTTP response but never ran the mapping's cleanup, so every completed POST left one _streamMapping entry behind until close() (main got the equivalent of this in modelcontextprotocol#2286). - conversely, cleanup() only deleted the map entry without settling the Promise<Response> returned by handleRequest(), so close() during an in-flight JSON-mode POST left the HTTP request hanging until the client timed out. cleanup() now resolves it with a 503 JSON-RPC error; on the success path send() has already resolved, and re-resolving is a no-op. Fix modelcontextprotocol#2559 (v1.x half; the main-branch close-settle half is drafted in modelcontextprotocol#2584)
🦋 Changeset detectedLatest commit: 24eae34 The changes in this PR will be included in the next version bump. 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 |
commit: |
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.
Fixes #2559 (v1.x half — the main-branch close-settle half is drafted in #2584)
What
On v1.x, JSON response mode has two lifecycle gaps:
send()resolves the pending HTTP response but never runs the stream mapping'scleanup, so every completed POST leaves one_streamMappingentry behind untilclose(). Long-lived sessions accumulate one entry per request. (main got the equivalent fix in Implement MCP 2026-07-28 #2286; it was never carried to v1.x — as noted on the issue, this is what currently ships as 1.30.0.)cleanup()only deleted the map entry without settling thePromise<Response>returned byhandleRequest().close()runs every mapping's cleanup, but for a JSON-mode POST still waiting on its handler that cleanup settled nothing — so the HTTP request hung until the client timed out.Fix
send()now callsstream.cleanup()right after resolving, mirroring main's Implement MCP 2026-07-28 #2286.cleanup()now settles the pending POST with a503JSON-RPC error (-32000), aligned with the approach drafted for main in fix(server): settle in-flight JSON-mode requests on transport close #2584. On the success pathsend()has already resolved beforecleanup()runs, and re-resolving a settled promise is a no-op, so the new resolve only fires when nothing was ever sent.Tests
settles an in-flight JSON-mode request when the transport closes mid-handler— the tool handler signals it has started,close()lands while it is genuinely parked, and the POST must resolve503with the JSON-RPC error payload instead of hanging.releases the JSON-mode stream mapping once the response has been sent—_streamMapping.sizemust be0after a completed JSON-mode POST (on unpatched v1.x this fails with2: the request's mapping plus initialize's).Both tests fail on unpatched v1.x and pass with the fix. Full suite: 1647 passed (the two unhandled stdio
SyntaxErrors reproduce on pristine v1.x and are unrelated).