Skip to content

MCP: accept missing MCP-Protocol-Version as the session's negotiated version - #1694

Merged
kriszyp merged 1 commit into
mainfrom
fix/mcp-protocol-header-relax-1611
Jul 8, 2026
Merged

kriszyp merged 1 commit into
mainfrom
fix/mcp-protocol-header-relax-1611

Conversation

@kylebernhardy

Copy link
Copy Markdown
Member

Fixes #1611 (as repurposed after investigation — both originally-filed items were verified unreproducible/stale on 5.1.17; see the issue comment with runtime evidence).

Summary

Requests on an established session that omit MCP-Protocol-Version were treated as 2025-03-26 (the spec's backcompat assumption) and then failed the negotiated-version check — so any client that negotiated 2025-06-18 but doesn't send the header on every request got 400 MCP-Protocol-Version mismatch. The session record already knows the negotiated version, so a missing header now validates as that version. A header that IS present must still name a supported version and match the negotiated one (both still 400).

One conditional in validateProtocolHeader (covers both call sites: POST dispatch and GET SSE open); initialize never validated the header and is unchanged.

Spec posture (flagging for review): the assume-2025-03-26 rule is a SHOULD aimed at clients predating the header; such clients negotiate 2025-03-26 anyway, so deferring to the session version is equivalent for them and stops penalizing modern clients that violate the MUST-send-header rule on non-critical requests. No downgrade risk — the authority is the server-side session record, not anything an attacker can strip in transit.

Testing

Flipped the unit test that asserted the 400, added a headerless GET SSE case; verified at runtime on a live instance (headerless tools/list on a 2025-06-18 session → 200; 2025-03-26 header on the same session → 400; garbage version → 400). No docs companion: the docs don't document the header behavior.

Generated by an LLM (Claude Fable 5); cross-reviewed by Codex (no findings) and Gemini (no findings; confirmed both call sites, the empty-string-header edge, and the no-downgrade posture).

@kylebernhardy
kylebernhardy requested a review from kriszyp July 7, 2026 21:47

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the MCP transport protocol validation to accept requests with a missing MCP-Protocol-Version header on established sessions, treating them as using the session's negotiated version. This resolves issues where headerless requests on newer session versions were incorrectly rejected. Corresponding unit tests have been updated and added to verify this behavior. There are no review comments, and I have no additional feedback to provide.

@claude

claude Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Reviewed; no blockers found.

@kriszyp
kriszyp changed the base branch from v5.1 to main July 8, 2026 11:59
@kriszyp

kriszyp commented Jul 8, 2026

Copy link
Copy Markdown
Member

Hey @kylebernhardy — retargeted this from v5.1 to main. New PRs should always target main; v5.1 is patch-only and gets populated automatically by the cherry-pick bot when a merged main PR carries the patch label. If this needs to ship in a patch release, add the patch label once it's merged to main instead of targeting v5.1 directly.

…sion (#1611)

Assuming 2025-03-26 for an absent header (the spec's backcompat rule for
pre-header clients) made every headerless request on a 2025-06-18
session fail the mismatch check with a 400. The established session is
the version authority: a missing header now validates as the session's
own version, while a present header must still be supported and match.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kylebernhardy
kylebernhardy force-pushed the fix/mcp-protocol-header-relax-1611 branch from 8252640 to 5671427 Compare July 8, 2026 14:36
@kylebernhardy
kylebernhardy marked this pull request as ready for review July 8, 2026 15:06
@kylebernhardy

Copy link
Copy Markdown
Member Author

Understood — thanks for the workflow correction (main-first, patch label → cherry-pick bot; will target main going forward). Added the patch label since the strict-mismatch 400 bites 5.1.x clients too. Comment generated by an LLM (Claude Fable 5).

@github-actions

github-actions Bot commented Jul 8, 2026 •

Copy link
Copy Markdown
Contributor

Patch cherry-pick: merged

Cherry-picked onto v5.1.

@kriszyp
kriszyp merged commit 4c9aab1 into main Jul 8, 2026
53 checks passed
@kriszyp
kriszyp deleted the fix/mcp-protocol-header-relax-1611 branch July 8, 2026 17:29
github-actions Bot pushed a commit that referenced this pull request Jul 8, 2026
…x-1611

MCP: accept missing MCP-Protocol-Version as the session's negotiated version
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MCP: relax MCP-Protocol-Version mismatch — treat missing header on an established session as the session's negotiated version

3 participants