Mirror x-mcp-header tool arguments into Mcp-Param-* request headers (SEP-2243)
What
Implements client-side Mcp-Param-* header emission (SEP-2243 "Custom Headers from Tool Parameters"). The client already validated and dropped tools with malformed x-mcp-header annotations but never emitted the headers - the gap the conformance expected-failures file named as the unimplemented S8 design.
On a modern (2026-07-28) Streamable HTTP connection, a tools/call now mirrors each argument annotated with x-mcp-header into an Mcp-Param-<name> header: string verbatim, integer as decimal, boolean as true/false, base64-sentinel-wrapped when not header-safe. Null or absent arguments are omitted, unannotated parameters are never mirrored, and the argument stays in the request body (additive, per spec).
The tool schema comes from the tool's last list_tools entry (annotations are cached); a tool the client never listed emits no Mcp-Param-* headers (spec-permitted).
Changes
mcp.shared.inbound:x_mcp_header_map()(schema -> path->token) andmcp_param_headers()(args -> headers), reusing the existing schema walk andencode_header_valuecodec.ClientSession: modern stamp injects param headers fortools/call;list_toolscaches each kept tool's annotations and evicts the entry when a re-list drops the tool.- Conformance
client.py: adds thehttp-custom-headershandler (replays the harnesstoolCalls). docs/migration.mdupdated.
Conformance
http-custom-headers now passes 18/18 on both the default and 2026-07-28 client legs and is removed from both expected-failures baselines.
The harness fixture annotated number-typed properties with x-mcp-header, which the spec forbids ("Parameters with type number are not permitted"); a conformant client drops those tools, so the scenario was previously unpassable. That is fixed upstream in modelcontextprotocol/conformance#371. CI is temporarily pinned to the pkg.pr.new preview of #371, with a CONFORMANCE_PKG_SHA256 digest + fetch-and-verify step (the repo's established pattern for URL pins) so the mutable URL is verified, not trusted. Repin to the published release once #371 ships.
All tests pass, 100% coverage, strict-no-cover/pyright/ruff clean.
AI Disclaimer
This PR was developed with the assistance of either Claude or Codex. I've reviewed and verified the changes.