modelcontextprotocol / modelcontextprotocol/typescript-sdk

Streamable HTTP server accepts mismatched `MCP-Protocol-Version` header and body `protocolVersion` on `initialize`

Open
#2,108 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug fix proposed P2 ready for work
Dominant language
TypeScript
Stars
13.4k
Forks
2.2k
Avg merge
3d 15h
Merged PRs (30d)
4

Description

Describe the bug

When the initial initialize request carries an MCP-Protocol-Version HTTP header that disagrees with initialize.params.protocolVersion in the JSON-RPC body, the server accepts the request without error. The negotiated protocol version follows the JSON-RPC body rather than the MCP-Protocol-Version request header.

The current MCP 2025-11-25 specification does not explicitly require the server to check body/header consistency on initialize, so this is filed as an implementation observation rather than a strict spec-violation claim.

  • Environment
    • Reproduced with stable releasev1.29.0 (e12cbd70)
    • Also reproduced with a main snapshot from 2026-05-16: 22595b96
    • Transport: Streamable HTTP server (stateful and stateless profiles)

To reproduce

  1. Start a TypeScript SDK Streamable HTTP server.
  2. Send an initialize request where the body protocolVersion is 2025-11-25 but the MCP-Protocol-Version header is 2025-03-26 (or vice versa).
  3. Observe that the server returns HTTP 200 with a normal initialize result.
  4. Check the negotiated protocol version in the response.

Expected behavior

Option A: the server rejects the mismatch before negotiation, for example with HTTP 400 or a JSON-RPC Invalid Request error.

Option B: the spec clarifies which field is authoritative, and the SDK documents that behavior and covers it with a regression test.

Logs

Both mismatch directions were accepted:

body=2025-11-25 header=2025-03-26 -> HTTP 200, negotiated version follows body (2025-11-25)
body=2025-03-26 header=2025-11-25 -> HTTP 200, negotiated version follows body (2025-03-26)

After initialization, subsequent responses used the body-negotiated version in the MCP-Protocol-Version header, not the original mismatched header value.

With a Streamable HTTP server running, set ENDPOINT to the server endpoint and send an initial initialize request whose HTTP header and JSON-RPC body disagree:

ENDPOINT=http://127.0.0.1:8080/mcp

curl -i -sS --http1.1 -X POST "$ENDPOINT" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H 'MCP-Protocol-Version: 2025-03-26' \
  --data '{"jsonrpc":"2.0","id":"init-conflict-1","method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"version-conflict-repro","version":"0.1.0"}}}'

Repeat with the values reversed: body 2025-03-26, header 2025-11-25.

Additional context

  • Related: SEP-2575 introduces a related future-state requirement that, for HTTP requests, the MCP-Protocol-Version header match _meta["io.modelcontextprotocol/protocolVersion"].

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 by reproducing the mismatch with the provided curl command against a Streamable HTTP server, using both header/body version directions. Trace the initialize request handling and version negotiation, then check existing regression coverage. Done means an explicit mismatch behavior is chosen, implemented or documented, and covered by a regression test.

Written by the indexing model from the issue text.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.