Correction after investigation: this is not a C# SDK client bug. The client already emits Mcp-Param-* headers correctly and per spec (see StreamableHttpClientConformanceTests, which asserts Mcp-Param-Region is auto-sent after ListToolsAsync/AddKnownTools).
What actually fails
The cross-SDK conformance harness @modelcontextprotocol/conformance@0.2.0-alpha.2 scenario http-custom-headers is non-conformant. Its test_custom_headers tool declares:
float_val: { type: "number", description: "Floating point numeric value", "x-mcp-header": "FloatVal" }
i.e. it puts x-mcp-header on a JSON Schema type: "number" (float) parameter and expects the client to mirror Mcp-Param-FloatVal.
SEP-2243 explicitly forbids this:
"MUST only be applied to parameters with primitive types (integer, string, boolean). Parameters with type number are not permitted."
— seps/2243-http-standardization.md / docs/specification/draft/server/tools.mdx
Our client correctly treats the number annotation as invalid and excludes the entire tool from the listing (the same behavior verified by the passing http-invalid-tool-headers scenario). The excluded tool is therefore a cache miss on CallToolAsync, so no Mcp-Param-* headers are sent — which makes every positive "Client sends correct Mcp-Param-X" check fail while the negatives ("omit null", "no header for unannotated param") pass. That exact failure signature is what we observed.
Action
- No SDK code change — emitting float headers would make us violate SEP-2243.
- File/track an upstream bug against the conformance package to remove or relabel
float_val (use integer, or drop the x-mcp-header annotation) so http-custom-headers is spec-conformant.
- Re-enable the
RunConformanceTest_Sep2243("http-custom-headers") xunit case (currently skipped behind HasSep2243Scenarios/HasMatchingDraftWireVersion) once a conformant package version ships.
cc #1610
Correction after investigation: this is not a C# SDK client bug. The client already emits
Mcp-Param-*headers correctly and per spec (seeStreamableHttpClientConformanceTests, which assertsMcp-Param-Regionis auto-sent afterListToolsAsync/AddKnownTools).What actually fails
The cross-SDK conformance harness
@modelcontextprotocol/conformance@0.2.0-alpha.2scenariohttp-custom-headersis non-conformant. Itstest_custom_headerstool declares:i.e. it puts
x-mcp-headeron a JSON Schematype: "number"(float) parameter and expects the client to mirrorMcp-Param-FloatVal.SEP-2243 explicitly forbids this:
Our client correctly treats the
numberannotation as invalid and excludes the entire tool from the listing (the same behavior verified by the passinghttp-invalid-tool-headersscenario). The excluded tool is therefore a cache miss onCallToolAsync, so noMcp-Param-*headers are sent — which makes every positive "Client sends correct Mcp-Param-X" check fail while the negatives ("omit null", "no header for unannotated param") pass. That exact failure signature is what we observed.Action
float_val(useinteger, or drop thex-mcp-headerannotation) sohttp-custom-headersis spec-conformant.RunConformanceTest_Sep2243("http-custom-headers")xunit case (currently skipped behindHasSep2243Scenarios/HasMatchingDraftWireVersion) once a conformant package version ships.cc #1610