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.