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.

@changeset-bot

changeset-bot Bot commented Jul 9, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 52358e0

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: 52358e0

@markhagler

Copy link
Copy Markdown

+1 on this backport specifically — the 1.x line is where this bites production users of the claude.ai custom-connector path today.

Data in #2433 (comment above): #2433 still reproduces on 1.29.0 and 1.30.0, so no released 1.x version is currently clean. In our deployment it strands ~1 % of MCP requests as an empty 200 that hangs until the client's 240 s deadline, with nothing logged server-side.

Glad to test this branch against real connector traffic if that is useful before merge.

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.
@Sammy-Dabbas
Sammy-Dabbas force-pushed the issue-2433-v1x-backport branch from 21cd552 to 52358e0 Compare August 9, 2026 03:30
@claude claude Bot added the v1 Issues / PRs related to v1.x label Aug 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

v1 Issues / PRs related to v1.x

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants