Skip to content

Invalid Origin header (403)

Spec
2026-07-28
Evidence
E2Reproducedarm64
TypeScript SDK v2 (Node HTTP)
@modelcontextprotocol/node@2.1.2
Python SDK
mcp@2.3.0
Verified

The specification says servers must validate the Origin header and answer 403 Forbidden when it is present and invalid. Browsers add Origin to cross-site requests; desktop and command-line clients normally do not. With Origin: https://evil.example.com we got:

Server Response
TypeScript SDK v2 with localhostOriginValidation() 403 {"jsonrpc":"2.0","error":{"code":-32000,"message":"Invalid Origin: evil.example.com"},"id":null}
Python SDK 2.3.0, streamable-http on 127.0.0.1 403 Invalid Origin header

A request with Origin: http://localhost:8504 passed both servers’ checks: the defaults trust localhost origins only.

If you are building a web client, an MCP App host, or a browser extension, its origin must be on the server’s allow list:

  • TypeScript SDK: replace localhostOriginValidation() with originValidation(['app.example.com']).
  • Python SDK: pass transport_security=TransportSecuritySettings(allowed_origins=["https://app.example.com"], allowed_hosts=[...]) to mcp.run("streamable-http", ...). We tested this; requests from that origin returned 200.

Passing the Origin check is not enough for a browser to read the response. The server must also send CORS headers, or the browser blocks it: see Blocked by CORS policy.

Send the same request with and without the Origin your web app uses:

Terminal window
curl -i -X POST http://127.0.0.1:8000/mcp \
-H 'content-type: application/json' \
-H 'accept: application/json, text/event-stream' \
-H 'MCP-Protocol-Version: 2026-07-28' \
-H 'Mcp-Method: tools/list' \
-H 'Origin: https://app.example.com' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28","io.modelcontextprotocol/clientCapabilities":{}}}}'

403 with Invalid Origin means the allow list does not include that origin. 200 without the header but 403 with it confirms the check is the only problem. Both servers we tested gave 200 once the origin was allowed, and still 403 for any other.

Sources

MCPDev is community documentation. It is not affiliated with the Model Context Protocol project or with the vendors of the clients it covers.