{"record":{"id":"05b5c7df2e279d50","repo":"googleapis/mcp-toolbox","slug":"mcp-method-header-value-s-does-not-match-body-v","errorCode":null,"errorMessage":"Mcp-Method header value '%s' does not match body value '%s'","messagePattern":"Mcp-Method header value '(.+?)' does not match body value '(.+?)'","errorType":"error_code","errorClass":"NewHeaderMismatchedError","httpStatus":null,"severity":"error","filePath":"internal/server/mcp/v20260728/method.go","lineNumber":112,"sourceCode":"\t\tmetaErr := fmt.Errorf(\"_meta error: missing required fields in request metadata\")\n\t\treturn jsonrpc.NewError(id, jsonrpc.INVALID_PARAMS, metaErr.Error(), nil), metaErr\n\t}\n\treturn nil, nil\n}\n\n// validateHeader checks the header of every requests\n// Toolbox do not check for `Mcp-Param-{Name}` header since we are not\n// implementing custom headers from parameters\n// Do not need to check for Base64-encoding or invalid characters since we are\n// only checking `mcp-method` and `mcp-name`\nfunc validateHeader(id jsonrpc.RequestId, header http.Header, method, name string) (any, error) {\n\t// stdio transport will not have header\n\tif header == nil {\n\t\treturn nil, nil\n\t}\n\theaderMethod := header.Get(\"mcp-method\")\n\tif headerMethod != method {\n\t\terr := fmt.Errorf(\"Mcp-Method header value '%s' does not match body value '%s'\", headerMethod, method)\n\t\treturn jsonrpc.NewHeaderMismatchedError(id, err), err\n\t}\n\theaderName := header.Get(\"mcp-name\")\n\tif headerName != name {\n\t\terr := fmt.Errorf(\"Mcp-Name header value '%s' does not match body value '%s'\", headerName, name)\n\t\treturn jsonrpc.NewHeaderMismatchedError(id, err), err\n\t}\n\treturn nil, nil\n}\n\n// getResultMetadata append the resultMetaObject on existing metadata\nfunc getResultMetadata(ctx context.Context, curMeta map[string]any) (map[string]any, error) {\n\tv, err := util.ToolboxVersionFromContext(ctx)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tresMetaObj := ResultMetaObject{","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/server/mcp/v20260728/method.go#L94-L130","documentation":"The MCP server validates that the `Mcp-Method` HTTP header exactly matches the JSON-RPC `method` field of the request body. A mismatch indicates the request may be tampered with or routed incorrectly, so the server rejects it with a jsonrpc HeaderMismatchedError before processing. This is part of a header-integrity check in validateHeader (internal/server/mcp/v20260728/method.go:112).","triggerScenarios":"Sending a streamable-HTTP request to tools/list, tools/call, prompts/list, prompts/get, server/discover, or groups/list endpoints where the `Mcp-Method` header value differs from the body's `method` field (e.g. header `tools/call` with body method `tools/list`). A nil header (stdio) skips validation.","commonSituations":"Reverse proxies or middleware rewriting/stripping headers; client SDKs generating the header from a stale or hardcoded value; manually constructed curl requests where header and body disagree; HTTP/2 or proxy layer lowercasing or mangling header names.","solutions":["Set the Mcp-Method header to exactly the JSON-RPC method string sent in the body (e.g. Mcp-Method: tools/list with \"method\":\"tools/list\").","If behind a proxy/load balancer, configure it to pass through the Mcp-Method and Mcp-Name headers unmodified.","Regenerate the request with an up-to-date MCP client SDK so header and body are produced together.","For local stdio usage, omit headers entirely; validation is skipped when header is nil."],"exampleFix":"// before\ncurl -X POST http://127.0.0.1:5000/mcp -H 'Mcp-Method: tools/call' \\\n  -d '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/list\"}'\n// after\ncurl -X POST http://127.0.0.1:5000/mcp -H 'Mcp-Method: tools/list' \\\n  -d '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/list\"}'","handlingStrategy":"validation","validationCode":"function validateMcpMethodHeader(headers, body) {\n  const parsed = JSON.parse(body);\n  if (headers.get('Mcp-Method') !== parsed.method) {\n    throw new Error(`Mcp-Method header '${headers.get('Mcp-Method')}' != body method '${parsed.method}'`);\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  const res = await fetch(mcpUrl, { headers: { 'Mcp-Method': method, 'Mcp-Name': name }, body });\n  const payload = await res.json();\n  if (payload.error && payload.error.code === -32000) { // HeaderMismatchedError class\n    console.error('Header/body mismatch:', payload.error.message);\n  }\n} catch (e) { console.error('request failed', e); }","preventionTips":["Always generate the Mcp-Method header from the same variable used for the body's method field.","Configure proxies to pass Mcp-* headers through unmodified.","Prefer official MCP client SDKs over hand-built HTTP requests.","Add a pre-send assertion in tests comparing header and body method."],"tags":["mcp","http-header","request-validation","go"],"backgroundTag":"http-header-body-mismatch","analyzedSha":"8cc6e09de2ad7b8bffc77751799585a1401a48eb","analyzedAt":"2026-09-05T01:10:36.887Z","contentChangedAt":"2026-09-05T01:10:36.887Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}