Skip to content

fix(server): reject duplicate in-flight request ids, v1.x backport of #2434#2474

Draft
Sammy-Dabbas wants to merge 1 commit into
modelcontextprotocol:v1.xfrom
Sammy-Dabbas:issue-2433-v1x-backport
Draft

fix(server): reject duplicate in-flight request ids, v1.x backport of #2434#2474
Sammy-Dabbas wants to merge 1 commit into
modelcontextprotocol:v1.xfrom
Sammy-Dabbas:issue-2433-v1x-backport

Conversation

@Sammy-Dabbas

Copy link
Copy Markdown

Backport of #2434 to the v1.x web-standard Streamable HTTP transport, fixing #2433 on the 1.x line.

Motivation and Context

WebStandardStreamableHTTPServerTransport registered every request id in _requestToStreamMapping with no duplicate check, so a second POST reusing an in flight id overwrote the entry, cross-wired the first request's response onto the second POST's stream, and left the first POST hanging. Deployed clients that send a constant id per request hit this under concurrency.

How Has This Been Tested?

Added regression tests for concurrent id collision, duplicate ids within one batch, sequential reuse after completion, cancel-then-reuse, and JSON response mode. The unfixed transport returns 200 with the cross-wired body while the first POST hangs; with the guard the duplicate is rejected with 400 and the first POST completes with its own result. The full transport test file and typecheck passes.

Breaking Changes

None. A duplicate in flight id now returns 400 with JSON-RPC -32600 instead of silently mis-delivering a response. Sequential reuse after completion and all valid traffic are unchanged.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

Same approach as #2434, adapted to the v1.x layout in src/server/webStandardStreamableHttp.ts, with an isCancelledNotification guard added to src/types.ts so cancelled ids stay reusable.

Backport of modelcontextprotocol#2434 to the v1.x web-standard transport. The transport
registered every request via _requestToStreamMapping.set(message.id,
streamId) with no duplicate check, so a concurrent POST reusing an
in-flight id overwrote the entry, cross-wired the first request's
response onto the second POST's stream, and left the first POST hanging.

Reject a POST containing a request whose id is already in flight, or
duplicated within the same batch, with HTTP 400 and JSON-RPC -32600.
Sequential reuse after completion stays allowed since deployed clients
send a constant id for every request. Cancelled requests never produce a
response, so notifications/cancelled now retires the transport
bookkeeping for its target id; without that, a cancelled id would stay
in flight forever and lock out cancel-then-reuse clients. Adds the
missing isCancelledNotification guard to types.

Fixes modelcontextprotocol#2433.
@changeset-bot

changeset-bot Bot commented Jul 9, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 21cd552

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

@pkg-pr-new

pkg-pr-new Bot commented Jul 9, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@modelcontextprotocol/sdk@2474

commit: 21cd552

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