modelcontextprotocol / modelcontextprotocol/typescript-sdk
Streamable HTTP: pre-existing hardening items from the #2547 review
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 13.4k
- Forks
- 2.2k
- Avg merge
- 3d 15h
- Merged PRs (30d)
- 4
Description
Three pre-existing Streamable HTTP transport items surfaced during the #2547 review that are independent of the keep-alive and delivery work there. Collecting them here so they don't get lost; each is small enough to fix individually.
-
Protocol-version gate accepts unvalidated strings on initialize. The priming/resumability gate compares
protocolVersion >= '2025-11-25'lexicographically, and for initialize requests the string comes verbatim from the request body without being checked againstSUPPORTED_PROTOCOL_VERSIONS(non-initialize requests are header-validated). Unsupported strings that sort above the threshold (draft,2026-01-01) enable priming events and the polling callbacks for the initialize stream even though the negotiated version in the response may be lower. Gate on the negotiated version instead. -
Concurrent DELETE requests can fire
onsessionclosedtwice. While the first DELETE is parked on the callback await,_closedis still false, so a second DELETE passes the guards and fires the callback again for the same session. A flag set before invoking the callback closes the window. -
The
EventStorecontract has no session scoping for the standalone stream. Every transport stores standalone server-initiated messages under the fixed id_GET_stream, so a store instance shared across sessions (module-level store inssePollingExample, or any multi-node shared store) mixes sessions on standalone resume: one session's resume can replay another session's notifications. The contract needs a session dimension, or documented single-session store usage.
Applies to both main and v1.x.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the initialize protocol-version gate, the concurrent DELETE session-close path, and the EventStore standalone-stream contract described here, comparing both main and v1.x implementations. Review the related #2547 context and existing transport coverage; done means unsupported versions cannot enable features, concurrent DELETEs invoke onsessionclosed once, and shared stores keep sessions isolated or document single-session usage.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- backend-api-design, networking
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100