Skip to content

Streamable HTTP accepts direct 2026 requests without required request _meta #1086

Description

@DaleSeo

Summary

rmcp 3.0.1's Streamable HTTP server accepts direct MCP 2026-07-28 requests whose HTTP headers select the modern protocol version but whose JSON-RPC body omits the required per-request _meta.

Both tools/list and tools/call return HTTP 200, and the tool call executes. There was no preceding initialize or server/discover exchange.

This is distinct from #1083: that PR rejects _meta.protocolVersion when the corresponding HTTP header is absent. This issue is the inverse—the MCP-Protocol-Version header is present, but the required body _meta is absent.

Environment

  • Tag: rmcp-v3.0.1
  • Commit: 3bb3c8dbce8ff4c1f8c9e91ebe03ca5cd42f3e81
  • Server: repository mcp-conformance server with STATELESS=1
  • Protocol version: 2026-07-28

Reproduction

Build and start the reference server:

cargo build -p mcp-conformance
STATELESS=1 PORT=8002 ./target/debug/conformance-server

Send tools/list without params._meta:

curl --include --http1.1 http://127.0.0.1:8002/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H 'MCP-Protocol-Version: 2026-07-28' \
  -H 'Mcp-Method: tools/list' \
  --data '{"jsonrpc":"2.0","id":31,"method":"tools/list","params":{}}'

Send tools/call without params._meta:

curl --include --http1.1 http://127.0.0.1:8002/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H 'MCP-Protocol-Version: 2026-07-28' \
  -H 'Mcp-Method: tools/call' \
  -H 'Mcp-Name: test_simple_text' \
  --data '{"jsonrpc":"2.0","id":32,"method":"tools/call","params":{"name":"test_simple_text","arguments":{}}}'

Actual behavior

Both requests return HTTP 200 with a successful resultType: "complete" response. test_simple_text executes and returns its normal text result.

The server log also shows synthetic peer information with meta: None, while treating the request as protocol version 2026-07-28.

Expected behavior

For the final 2026-07-28 stateless lifecycle, each request is self-contained and MUST carry the required request metadata: io.modelcontextprotocol/protocolVersion and io.modelcontextprotocol/clientCapabilities. The HTTP protocol-version header mirrors the body field and does not make an otherwise incomplete request valid.

io.modelcontextprotocol/clientInfo is optional. Clients SHOULD include it on every request unless specifically configured not to do so, but servers must not reject a request solely because clientInfo is absent.

Because the requests above omit both required fields, they MUST return HTTP 400 with JSON-RPC -32602 Invalid params, identifying the missing or malformed required _meta fields.

Specification references: 2026-07-28 per-request protocol fields and transport request metadata.

Likely validation gap

validate_request_protocol_version_meta rejects an absent metadata protocol version only for server/discover; other methods return Ok(()).

The later requires_request_metadata check activates for discovery, previously marked peers, or requests whose _meta already declares a modern version. A direct request whose modern version appears only in the HTTP header therefore does not activate required-field validation.

Conformance coverage gap

The current 2026 server suite passes against the reference server because it checks missing metadata on server/discover and sends later requests after a valid discovery exchange. It does not send a direct non-discover request with a 2026 HTTP version header and missing _meta.

Suggested regression coverage

Add Streamable HTTP tests for:

  1. Direct tools/list with a 2026 version header and no _meta.
  2. Direct tools/call with valid routing headers and no _meta.
  3. _meta missing only io.modelcontextprotocol/protocolVersion (must be rejected).
  4. _meta missing only io.modelcontextprotocol/clientInfo (must be accepted; this field is optional).
  5. _meta missing only io.modelcontextprotocol/clientCapabilities (must be rejected).

The first two cases would also be useful additions to the upstream conformance suite.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

P1High: significant functionality gap or spec violationT-bugBug fixes and error correctionsT-coreCore library changesT-transportTransport layer changes

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions