modelcontextprotocol / modelcontextprotocol/typescript-sdk

Stateless StreamableHTTPServerTransport: per-request requirement is invisible through the Node wrapper (500 with empty body)

Open
#2,704 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

v1 v2
Dominant language
TypeScript
Stars
13.4k
Forks
2.2k
Avg merge
3d 15h
Merged PRs (30d)
4

Description

Problem

The WebStandard core throws a clear assertion when a stateless transport is reused:

Stateless transport cannot be reused across requests. Create a new transport per request.

The Node wrapper (StreamableHTTPServerTransport via @hono/node-server) converts that assertion into a bare 500 with an empty body — no onerror, no rejection. Combined with Client.connect() unconditionally sending notifications/initialized, a stock official-client <-> official-stateless-server pair fails with an opaque 500, giving no signal that the per-request assembly pattern is required.

Suggestion

  1. Surface the assertion through onerror (or reject from handleRequest) so the failure is observable and debuggable.
  2. Document the per-request pattern ("create a new transport per request") prominently in the stateless guide — it is currently invisible through the Node wrapper.

Context

Observed while integrating the 2026-07-28 stateless core (@modelcontextprotocol/sdk 1.30.0) as an official protocol face. Our workaround (per-request assembly + a notification-dropping client transport) is documented in our project's known-issues log.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the Node wrapper's StreamableHTTPServerTransport and its handleRequest path, then compare the WebStandard assertion with the Node behavior. Check Client.connect() and the stateless guide for the per-request pattern. Done means the reuse failure is observable through onerror or a rejected request, and the guide clearly documents creating a new transport per request.

Written by the indexing model from the issue text.

Assessment

Tech stack
node.js, typescript
Domain
api, backend, documentation
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.