Invalid Host header (403 or 421)
- Spec
2026-07-28- Evidence
- E2Reproducedarm64
- TypeScript SDK v2 (Node HTTP)
@modelcontextprotocol/node@2.1.2- Python SDK
mcp@2.3.0- Verified
What it means
Section titled “What it means”A website you visit can make your browser send requests to 127.0.0.1 through a domain it controls. This is DNS rebinding, and the specification asks local servers to defend against it. The official SDKs do so by default for servers bound to localhost: they only accept requests whose Host header is a localhost name. We sent Host: evil.example.com:
| Server | Response |
|---|---|
TypeScript SDK v2 with localhostHostValidation() from @modelcontextprotocol/node (also the default of createMcpExpressApp()) |
403 {"jsonrpc":"2.0","error":{"code":-32000,"message":"Invalid Host: evil.example.com"},"id":null} |
Python SDK 2.3.0, mcp.run("streamable-http", host="127.0.0.1") |
421 Misdirected Request Invalid Host header |
The request never reaches your tools.
A proxy or container changes the Host
Section titled “A proxy or container changes the Host”Behind nginx, Caddy, a tunnel or Docker port mapping, the request arrives with the public name (mcp.example.com) or the container’s address in Host. Two fixes, depending on what you want:
-
Keep the protection and allow your real hostnames. In the TypeScript SDK, use
hostHeaderValidation(['mcp.example.com'])from@modelcontextprotocol/nodeinstead of the localhost variant. In the Python SDK, pass the allowed hosts torun();host:*allows any port. With this setting our server acceptedHost: mcp.example.comand still rejected other names:from mcp.server.transport_security import TransportSecuritySettingsmcp.run("streamable-http",host="127.0.0.1",port=8000,transport_security=TransportSecuritySettings(allowed_hosts=["mcp.example.com", "127.0.0.1:*"],),) -
Make the proxy send
Host: 127.0.0.1:<port>, for exampleproxy_set_header Host $proxy_host;in nginx, if the server only needs to accept the proxy.
You reach a local-only server by IP or domain
Section titled “You reach a local-only server by IP or domain”If you call http://192.168.1.20:8000/mcp from another machine, the Host is that IP and a localhost-only server rejects it. Decide whether the server should be reachable on the network at all. If yes, bind to the right interface, allow that hostname, and add authentication.
Related
Section titled “Related”- Invalid Origin: the browser-side half of the same protection.
- Run a server behind Docker and a reverse proxy
Sources
MCPDev is community documentation. It is not affiliated with the Model Context Protocol project or with the vendors of the clients it covers.