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:
- Direct
tools/list with a 2026 version header and no _meta.
- Direct
tools/call with valid routing headers and no _meta.
_meta missing only io.modelcontextprotocol/protocolVersion (must be rejected).
_meta missing only io.modelcontextprotocol/clientInfo (must be accepted; this field is optional).
_meta missing only io.modelcontextprotocol/clientCapabilities (must be rejected).
The first two cases would also be useful additions to the upstream conformance suite.
Summary
rmcp 3.0.1's Streamable HTTP server accepts direct MCP
2026-07-28requests whose HTTP headers select the modern protocol version but whose JSON-RPC body omits the required per-request_meta.Both
tools/listandtools/callreturn HTTP 200, and the tool call executes. There was no precedinginitializeorserver/discoverexchange.This is distinct from #1083: that PR rejects
_meta.protocolVersionwhen the corresponding HTTP header is absent. This issue is the inverse—theMCP-Protocol-Versionheader is present, but the required body_metais absent.Environment
rmcp-v3.0.13bb3c8dbce8ff4c1f8c9e91ebe03ca5cd42f3e81mcp-conformanceserver withSTATELESS=12026-07-28Reproduction
Build and start the reference server:
Send
tools/listwithoutparams._meta:Send
tools/callwithoutparams._meta:Actual behavior
Both requests return HTTP 200 with a successful
resultType: "complete"response.test_simple_textexecutes and returns its normal text result.The server log also shows synthetic peer information with
meta: None, while treating the request as protocol version2026-07-28.Expected behavior
For the final
2026-07-28stateless lifecycle, each request is self-contained and MUST carry the required request metadata:io.modelcontextprotocol/protocolVersionandio.modelcontextprotocol/clientCapabilities. The HTTP protocol-version header mirrors the body field and does not make an otherwise incomplete request valid.io.modelcontextprotocol/clientInfois optional. Clients SHOULD include it on every request unless specifically configured not to do so, but servers must not reject a request solely becauseclientInfois 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_metafields.Specification references: 2026-07-28 per-request protocol fields and transport request metadata.
Likely validation gap
validate_request_protocol_version_metarejects an absent metadata protocol version only forserver/discover; other methods returnOk(()).The later
requires_request_metadatacheck activates for discovery, previously marked peers, or requests whose_metaalready 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/discoverand 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:
tools/listwith a 2026 version header and no_meta.tools/callwith valid routing headers and no_meta._metamissing onlyio.modelcontextprotocol/protocolVersion(must be rejected)._metamissing onlyio.modelcontextprotocol/clientInfo(must be accepted; this field is optional)._metamissing onlyio.modelcontextprotocol/clientCapabilities(must be rejected).The first two cases would also be useful additions to the upstream conformance suite.