The 2026-07-28 MCP spec did something small that changes where you put your infrastructure. Every Streamable HTTP request now has to carry the JSON-RPC method in an Mcp-Method header and, when it calls a tool, the tool name in Mcp-Name (SEP-2243). That means your gateway — nginx, Envoy, HAProxy, a CDN — can route, throttle, and block per-tool by reading two headers, without ever deserializing a JSON-RPC body. This is the copy-paste version. (For why the protocol went stateless in the first place, see MCP goes stateless.)
The whole idea: the method and tool name now live in headers on purpose — duplicated from the body so that edge infrastructure, which is good at headers and bad at nested JSON, can act on them. Route on Mcp-Method, rate-limit on Mcp-Name, and keep the body sealed.
1. Route by method in nginx#
nginx exposes any request header as $http_<lowercased_name_with_underscores>, so Mcp-Method arrives as $http_mcp_method and Mcp-Name as $http_mcp_name. Use a map to pick an upstream from the method:
# expensive tool calls go to the GPU-backed pool; everything else stays cheap
map $http_mcp_method $mcp_pool {
default "mcp_cheap";
"tools/call" "mcp_tools";
}
upstream mcp_cheap { server 10.0.0.10:8080; server 10.0.0.11:8080; }
upstream mcp_tools { server 10.0.1.10:8080; server 10.0.1.11:8080; }
server {
listen 443 ssl;
location /mcp {
# reject requests that don't speak the 2026-07-28 header contract
if ($http_mcp_method = "") { return 400; }
proxy_pass http://$mcp_pool;
}
}
Because the spec went stateless, any instance can serve any request — so nginx is free to round-robin within each pool. No sticky sessions, no Mcp-Session-Id to pin.
2. Rate-limit one tool without touching the others#
The old problem: one embed-heavy tool would eat the whole server's request budget, and you couldn't throttle it at the edge because you couldn't see which tool a request called. Now you can — key a limit_req_zone on $http_mcp_name:
# a separate throttle bucket per tool name
limit_req_zone $http_mcp_name zone=per_tool:10m rate=5r/s;
location /mcp {
limit_req zone=per_tool burst=10 nodelay;
limit_req_status 429;
proxy_pass http://$mcp_pool;
}
Now search and deep_research get independent 5-requests-per-second buckets. A hot tool can't starve the rest, and you tune each one from its real cost.
3. The same thing in Envoy#
Envoy matches on request headers declaratively — route tools/call to a dedicated cluster and attach a per-route rate limit:
routes:
- match:
prefix: "/mcp"
headers:
- name: "Mcp-Method"
string_match: { exact: "tools/call" }
route:
cluster: mcp_tools
rate_limits:
- actions:
- request_headers:
header_name: "Mcp-Name"
descriptor_key: "tool"
- match:
prefix: "/mcp"
route: { cluster: mcp_cheap }
The Mcp-Name value becomes a rate-limit descriptor, so your rate-limit service can enforce a different quota for each tool from one rule.
Headers are a routing and metering convenience. They are not an authorization boundary — the client writes them.
4. The one header you must never trust#
Here's the trap. A client controls its own headers, so nothing stops it from sending Mcp-Name: search on a request whose body actually calls admin_delete. If you gate access on the header, you've built a bypass.
So the rule is: route and rate-limit on the headers; authorize on the body. Your server must still parse the real method and tool and check permissions against that. Add one cheap defense at the origin — reject any request where the Mcp-Name header disagrees with the tool in the body, returning a hard 400:
if request.headers.get("Mcp-Name") != rpc_body["params"]["name"]:
raise HTTPException(400, "Mcp-Name header does not match request body")
That turns a header/body mismatch into a loud error instead of a silent authorization hole, and it costs you one comparison.
Ship it in three moves: put an Mcp-Method route map in front of your stateless pool, add a $http_mcp_name rate-limit bucket for your most expensive tool, and add the header-versus-body equality check in the server. The first two are pure edge config; the third is the line that keeps the convenience from becoming a liability. For the caching half of the same spec, see how to add response caching to your MCP server.



