Skip to content

fix: isolate stateless HTTP request exchanges - #264

Open
jstar0 wants to merge 1 commit into
modelcontextprotocol:mainfrom
jstar0:fix/stateless-response-exchange-routing
Open

jstar0 wants to merge 1 commit into
modelcontextprotocol:mainfrom
jstar0:fix/stateless-response-exchange-routing

Conversation

@jstar0

@jstar0 jstar0 commented Jul 26, 2026

Copy link
Copy Markdown

Summary

Fixes #254.

StatelessHTTPServerTransport currently keys response waiters by the client's
raw JSON-RPC id. Because ids are scoped to each client, concurrent POSTs can
legally reuse the same id; the later request then overwrites the earlier
continuation, leaving one HTTP exchange suspended indefinitely. String and
integer ids also collide after stringification.

Changes

This change assigns a private UUID to each in-flight HTTP exchange before the
request is yielded to Server. Responses route by that private id, then restore
the client's original string or integer id before returning over HTTP.

The same exchange identity now scopes HTTP request context, while typed raw-id
aliases preserve existing direct lookups. A package-only mapping keeps
Server.currentHandlerContext.id and cancellation lookup on the original client
id without changing public transport or handler APIs. Cancellation fails closed
when multiple active exchanges make a reused wire id ambiguous.

Verification

  • Added a deterministic regression that waits for two same-id requests to be in
    flight before sending either response.
  • Added string/integer id, HTTP context, handler context, disconnect cleanup, and
    cancellation compatibility coverage.
swift test -v

Result: 555 tests in 40 suites passed.

Scope

Signed-off-by: King Star <mcxin.y@gmail.com>
ianegordon added a commit to ianegordon/swift-sdk that referenced this pull request Sep 10, 2026
…s HTTP request exchanges

Brings modelcontextprotocol#264 onto the modelcontextprotocol#254 branch so its
exchange-scoped id routing can be verified against this branch's
regression tests. Sources are the PR's head e14ef60, unmodified.
@ianegordon

Copy link
Copy Markdown

I have independently verified this PR does resolve the issue I opened, #254 . I have some low priority test improvements that can land after this PR.

I recommend landing the related PRs in the following order.
PR #264 (fixes Issue #254)
PR #260 (fixes Issue #255)

ianegordon added a commit to ianegordon/swift-sdk that referenced this pull request Sep 10, 2026
ianegordon added a commit to ianegordon/swift-sdk that referenced this pull request Sep 10, 2026
…rotocol#264

Manifest entry 1a. Tests-only, stacked on pr/264 at e14ef60; offered
upstream alongside modelcontextprotocol#264.
ianegordon added a commit to ianegordon/swift-sdk that referenced this pull request Sep 10, 2026
ianegordon added a commit to ianegordon/swift-sdk that referenced this pull request Sep 10, 2026
…tream modelcontextprotocol#260, rebased onto modelcontextprotocol#264)

Manifest entry 2. Upstream refs/pull/260/head b5da0ef (branch pr/260),
rebased onto modelcontextprotocol#264 as 12b8c92 with the cancellation routed through the
exchange table. Fixes modelcontextprotocol#255.
ianegordon added a commit to ianegordon/swift-sdk that referenced this pull request Sep 10, 2026
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.

StatelessHTTPServerTransport: concurrent requests sharing a JSON-RPC id overwrite each other's response waiter (hang + continuation leak)

2 participants