Home · Guides

x-mcp-header puts one argument where a load balancer can see it

Streamable HTTP carries a tool call as a JSON body, so anything between the client and the server has to parse that body to know what is being asked. The x-mcp-header extension, introduced in specification revision 2026-07-28, lets a server nominate individual parameters to be copied into HTTP headers, so proxies, load balancers and firewalls can route on them without reading the payload.

The annotation goes inside the JSON Schema of the property being mirrored, and its value is the name portion of the resulting Mcp-Param-{name} header:

{
  "name": "execute_sql",
  "description": "Execute SQL on Google Cloud Spanner",
  "inputSchema": {
    "type": "object",
    "properties": {
      "region": { "type": "string", "description": "The region to execute the query in", "x-mcp-header": "Region" },
      "query":  { "type": "string", "description": "The SQL query to execute" }
    },
    "required": ["region", "query"]
  }
}

Called with "region": "us-west1", the client adds Mcp-Param-Region: us-west1 to the HTTP request.

The constraints, all MUSTs

The failure mode is silent, and it is the tool that disappears

A client on streamable HTTP MUST reject a tool definition that violates any of these, and rejection is defined precisely: the client MUST exclude the invalid tool from the result of tools/list. It SHOULD log a warning naming the tool and the reason. The stated purpose is that one malformed definition does not prevent the other tools from being used.

So the symptom of a mistake here is a tool that simply is not there, on some transports and not others, with the explanation in a log you may not be reading. Clients on stdio MAY ignore the annotation entirely, which means a server tested locally over stdio can lose tools the moment it is deployed behind HTTP.

Do not mirror a secret

The specification says server developers SHOULD NOT mark passwords, API keys, tokens or personal data with x-mcp-header, because header values are visible to network intermediaries. That is the entire point of the feature, and it is the reason to use it sparingly: a value you mirror is a value you have chosen to show to every hop.

When it is worth using

The honest answer is rarely, and only when something in your network path needs to make a decision before the body is available. Region or tenant routing, per-parameter rate limiting at the edge, and firewall rules that depend on an argument are the cases the design is aimed at. If your server reads the value itself and nothing between you and the client cares, the argument in the body is already enough.

Source: the tools section of the MCP specification, revision 2026-07-28, at modelcontextprotocol.io, fetched 2026-09-09. The example is the specification's own. This extension is new in that revision, so a client speaking an earlier version will not implement it and your tool has to work without it.

Questions

Why is number excluded when integer is allowed?

Floating point values do not round-trip through a text header predictably, so the value a proxy reads could differ from the value the server receives. Integers are constrained to the IEEE754 safe range for the same reason.

Does the server still get the parameter in the body?

Yes. The header is a mirror, not a move. Your handler reads arguments exactly as before, and the specification points at its own section on extracting header values from call arguments for the precise rules.

What if two parameters ask for the same header name?

The uniqueness requirement is case-insensitive, so Region and region collide. A client on streamable HTTP must then reject the whole tool definition and leave that tool out of tools/list.

Can I use it on a nested object property?

Only if the property is statically reachable from the schema root. A property behind a oneOf branch or a dynamic reference is not, and marking one is a violation that removes the tool.

How do I know whether a client honoured it?

Log the incoming headers on your server and call the tool through the client you care about. A client on stdio may ignore the annotation entirely, which is allowed, so the absence of the header is not necessarily a bug.

Related

All MCP servers and prices · All guides · Buy the bundle $39