fix: scope MCP replay to the requested stream - #1529
Open
jadch wants to merge 1 commit into
Open
Conversation
Contributor
Author
|
CI note: the only red check is the 16-minute self-host E2E suite, and it is the same deterministic pre-existing failure on this PR's exact base (
Both fail |
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.
Summary
Keep a cursor-bearing MCP recovery GET scoped to the stream identified by its
Last-Event-ID, while preserving the existing cursorless fresh-GET fallback for completed POST responses that otherwise have no recovery cursor.Problem
The Streamable HTTP spec says a server MUST NOT replay messages that would have been delivered on a different stream. The current patched transport first replays the cursor's stream, then appends responses from every other undelivered POST stream to the same recovery GET.
That can lose the response the client actually needs: the TypeScript SDK stops reconnecting after the first JSON-RPC result/error, so an unrelated completed response can make it close before the cursor's own result arrives.
Change
Last-Event-IDbranchreplayUndeliveredResponsesOnFreshGetand call it only when GET has no cursorRegression proof
With the old cross-stream call deliberately restored, the new test fails immediately:
With this fix restored, the full replay E2E file passes all three scenarios.
Validation
bun run check:patchesbun run --cwd packages/hosts/cloudflare test— 61 passedbun run --cwd packages/hosts/cloudflare typecheckbun run --cwd e2e typecheckbunx vitest run --project cloud cloud/mcp-sse-replay.test.ts— 3 passedRelated context: #1345 and #1489.