modelcontextprotocol / modelcontextprotocol/kotlin-sdk

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

Open
#766 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement needs confirmation P3
Dominant language
Kotlin
Stars
1.5k
Forks
248
Avg merge
1d 20h
Merged PRs (30d)
23

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 release 0.12.0 (c339d8cb)
    • Also reproduced with a main snapshot from 2026-05-16 (44e012e4)
    • Transport: Streamable HTTP server (stateful profile)

To reproduce

  1. Start a Kotlin 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 with the Kotlin SDK Streamable HTTP server's initialize handling path and reproduce both mismatch directions using the provided curl request. Check how the HTTP header and JSON-RPC body are read and how the negotiated version is returned. Done requires an agreed mismatch behavior, documentation or specification guidance, and a regression test covering both directions.

Written by the indexing model from the issue text.

Assessment

Tech stack
kotlin
Domain
api, backend
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.