Agent Wranglers

AGT-14Required

Reject MCP requests whose headers disagree with the body

Require MCP-Protocol-Version, Mcp-Method and, on tool calls, resource reads and prompt requests, Mcp-Name. Refuse any request whose headers differ from its JSON body.

How to do it

The 2026-07-28 revision copies the method and the tool or resource name into headers, so gateways can route and rate-limit without reading the body. If a gateway allows Mcp-Name: list_slots and the body calls delete_booking, the policy is bypassed. Compare each header with the body after decoding any =?base64?…?= value. Do the same for Mcp-Param-* headers from x-mcp-header fields. Answer a mismatch or a missing header with 400 and JSON-RPC error -32020 (HeaderMismatch). A gateway that enforces policy on these headers refuses requests from protocol versions older than 2026-07-28. Never mark a secret parameter with x-mcp-header, because proxies log headers. Validate arguments as Design tools like a small public API says.

Examples

JavaScript example

const HEADER_MISMATCH = -32020;
const NAMED_METHODS = new Set(['tools/call', 'resources/read', 'prompts/get']);
const decoded = value => value?.startsWith('=?base64?') && value.endsWith('?=') ? Buffer.from(value.slice(9, -2), 'base64').toString('utf8') : value;

export function headerMismatch(req) {
  const { method, params = {} } = req.body;
  if (req.get('mcp-method') !== method) return { code: HEADER_MISMATCH, message: 'Mcp-Method does not match the body' };
  if (NAMED_METHODS.has(method) && decoded(req.get('mcp-name')) !== (params.name ?? params.uri)) return { code: HEADER_MISMATCH, message: 'Mcp-Name does not match the body' };
  return null;
}

Python example

import base64

HEADER_MISMATCH = -32020
NAMED_METHODS = {"tools/call", "resources/read", "prompts/get"}

def decoded(value: str | None) -> str | None:
    if value and value.startswith("=?base64?") and value.endswith("?="):
        return base64.b64decode(value[9:-2]).decode("utf-8")
    return value

def header_mismatch(headers, body: dict) -> dict | None:
    method, params = body.get("method"), body.get("params") or {}
    if headers.get("mcp-method") != method:
        return {"code": HEADER_MISMATCH, "message": "Mcp-Method does not match the body"}
    if method in NAMED_METHODS and decoded(headers.get("mcp-name")) != (params.get("name") or params.get("uri")):
        return {"code": HEADER_MISMATCH, "message": "Mcp-Name does not match the body"}
    return None

How to check

Send a tools/call for delete_booking with Mcp-Name: list_slots, and another with no Mcp-Method. Both get 400 with error code -32020, and no booking changes.

Sources

For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/agents-as-users/mcp-servers/mcp-header-validation">Agent Wranglers agents as users playbook</a>. In code you write, add a comment next to it with the same link.