Skip to content

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

Description

@kylebernhardy

Two small conformance / consistency observations from testing a live application-profile instance (harper@5.1.15), MCP spec rev 2025-06-18.

1. initialize returns HTTP 400 when the MCP-Protocol-Version header is absent

An initialize POST without an MCP-Protocol-Version header returns 400 Bad Request; adding MCP-Protocol-Version: 2025-06-18 makes it 200. The transport spec says: "if the server does not receive an MCP-Protocol-Version header … the server SHOULD assume protocol version 2025-03-26." A hard 400 on the initialization request is stricter than that SHOULD — and many clients don't send the header on the first initialize (the version isn't negotiated yet; it's carried in the body's params.protocolVersion).

Repro:

curl -sD- -H 'content-type: application/json' -H 'accept: application/json, text/event-stream' \
  -X POST http://<host>/mcp \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"c","version":"0"}}}'
# → HTTP/1.1 400 Bad Request     (add MCP-Protocol-Version header → 200)

2. initialize advertises resources.subscribe: true, but subscriptions aren't implemented

The initialize result advertises capabilities.resources.subscribe: true, while the docs (reference/v5/mcp/tools-and-resources) state "resources are static (no resources/subscribe in v1)" and #1349 lists subscriptions as planned. Advertising subscribe: true invites clients to call resources/subscribe against a server that won't honour it. Either land subscriptions (tracked in #1349) or stop advertising the capability until then.

Activity

  1. added
    area:mcpModel Context Protocol (MCP) server: protocol, profiles, stdio CLI
    on Jul 6, 2026
  2. kylebernhardy commented on Jul 7, 2026

    @kylebernhardy
    MemberAuthor

    Investigated both items against current v5.1 (5.1.17, commit 194f1ba) with a live instance. Neither reproduces as filed:

    1. initialize without MCP-Protocol-Version → could not reproduce. Your exact curl (no header, protocolVersion in the body) returns 200 with a session id:

    HTTP/1.1 200 OK
    {"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2025-06-18","serverInfo":{"name":"harper-mcp","version":"5.1.17"},...}}
    

    Code archaeology agrees: handlePost has dispatched initialize before any protocol-header validation since the transport landed in v5.1.0 — the only pre-initialize 400s are JSON-RPC parse failures and an invalid body params.protocolVersion. Could you retest against 5.1.17 and, if it still 400s for you, capture the response body (the JSON-RPC error.message pinpoints which check fired)? A fronting proxy is another candidate.

    What you may have actually hit: requests after initialize that omit the header do get a 400 on a 2025-06-18 session — the missing header is assumed to be 2025-03-26 per the spec's compatibility rule, which then fails the negotiated-version match:

    {"error":{"code":-32600,"message":"MCP-Protocol-Version mismatch: session negotiated 2025-06-18, request sent 2025-03-26"}}
    

    Per spec, clients MUST send the header on post-negotiation requests, so rejecting is defensible — but if common clients omit it, we could relax the mismatch case (treat missing-header on an established session as the session's own version). That's a maintainer call; leaving this issue open for that question if wanted.

    2. resources.subscribe: true is accurate — subscriptions are implemented. They shipped in v5.1.10 (#1404, completing #1349). The live endpoint enforces its documented precondition rather than being a stub:

    → resources/subscribe (no SSE stream open)
    ← {"error":{"code":-32602,"message":"open the GET SSE stream before subscribing to resources"}}
    

    The docs page you quoted was outdated at the time; the current docs have a dedicated MCP Resource Subscriptions page and the tools-and-resources page now points to it.

    Suggested disposition: close as stale, or retitle to the narrower "relax MCP-Protocol-Version mismatch for missing header on established sessions" question above.

    Comment generated by an LLM (Claude Fable 5); runtime evidence from a clean 5.1.17 instance.

  3. self-assigned this
    on Jul 7, 2026
  4. changed the title [-]MCP 2025-06-18: initialize 400s without MCP-Protocol-Version header; resources.subscribe:true advertised though subscriptions unimplemented[/-] [+]MCP: relax MCP-Protocol-Version mismatch — treat missing header on an established session as the session's negotiated version[/+] on Jul 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:mcpModel Context Protocol (MCP) server: protocol, profiles, stdio CLI

Type

No type

Fields

Priority

None yet

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions