modelcontextprotocol / modelcontextprotocol/typescript-sdk

Bug/Feature Request: Node 26 fetch HTTP/2 SSE stream buffering hangs MCP connections

Open
#2,525 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

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

Description

Title

Bug/Feature Request: Node 26 fetch HTTP/2 SSE stream buffering hangs MCP connections

Body

(Note: This issue was investigated and drafted with the help of Google Antigravity / Gemini 3.1 Pro during a debugging session).

The Issue

When running MCP SDK clients (such as mcporter) on Node.js 26.4.0, all Server-Sent Events (SSE) connections fail to initialize and eventually time out with errors like Invalid response body, expected a web ReadableStream.

Root Cause Analysis

Node 26 upgraded its native fetch implementation (backed by undici) to enable HTTP/2 by default. There appears to be a stream buffering regression in undici when handling SSE over HTTP/2. As a result, the initial connection chunks (specifically the endpoint URI required by the MCP client) are buffered and never flushed to the client's ReadableStream, causing the connection handshake to stall indefinitely.

Evidence & Workaround
  • Failure: On Node 26.4.0, standard MCP SSE connections hang completely.
  • Success: By overriding the global fetch dispatcher to force HTTP/1.1, the streams flow instantly and 100% of the MCP server connections succeed.

Here is the exact shim that resolves the issue locally:

import { setGlobalDispatcher, Agent } from "undici";

// Force HTTP/1.1 to bypass the Node 26 HTTP/2 SSE streaming bug
const agent = new Agent({
  allowH2: false
});
setGlobalDispatcher(agent);
Proposed Solution

While the root cause lies upstream in Node.js / undici, the MCP SDK could protect its users from this breaking change:

  1. Enforce HTTP/1.1 for SSE: Explicitly configure the fetch transport layer to use HTTP/1.1 (allowH2: false) when running in a Node.js environment, as SSE over HTTP/2 in Node is currently unstable.
  2. Expose Transport Config: Alternatively, expose the underlying fetch request initialization/dispatcher options in the SDK so users can inject custom undici agents when needed.

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

Locate the SDK's SSE fetch transport entry point and reproduce the hang on Node.js 26.4.0 with an HTTP/2 connection. Compare behavior using the supplied undici dispatcher shim that forces HTTP/1.1. Done means MCP SSE connections initialize reliably, with focused coverage for the affected stream-handshake behavior.

Written by the indexing model from the issue text.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.