You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A recent update (Commit: 86bb54c, PR: #861) introduced DNS rebinding protection to the MCP Python SDK. While this improves security, it may cause existing setups to fail with a 421 Misdirected Request / Invalid Host Header error if the host header doesn't match the allowed list (common when using proxies, gateways, or custom domains).
Affected Components
File:src/mcp/server/fastmcp/server.py:178
Solutions
Depending on your security requirements, you can resolve this in two ways:
Option 1: Explicitly Allow Specific Hosts (Recommended)
Use this approach if you are running in production or through a gateway. You can wildcard the ports using *.
frommcp.server.fastmcpimportFastMCPfrommcp.server.transport_securityimportTransportSecuritySettingsmcp=FastMCP(
"MyServer",
transport_security=TransportSecuritySettings(
enable_dns_rebinding_protection=True,
# Add your specific gateway or domain hereallowed_hosts=["localhost:*", "127.0.0.1:*", "your-gateway-host:*"],
allowed_origins=["http://localhost:*", "http://your-gateway-host:*"],
)
)
Option 2: Disable DNS Rebinding Protection
Use this approach for local development or if you are managing security at a different layer of your infrastructure.
@cbcoutinho@jerome3o-anthropic@maxisbey I suggest adding some documents for Invalid Host Header. Because this kind of problem often occurs in the cluster deployment.
Reacted by andr0s, Ryan Voots, Mykhailo Borodianskyi and H4dr1en
+1 to above: it'll be nice if there is a set centralised env vars defined specifically for these configs:
As seen there are more linked issues to this one, with the solution that adding configs / envvars that are mcp servers specific. Having centralised set of env vars can prevent mcp servers implementing customised configs / envvars, saving efforts.
@ddworken@jerome3o-anthropic There really needs to be a better mechanism to set this globally/environmentally beyond passing transport_security to every server instance.
Looking at the growing list of linked issues and commits referencing this problem, it's clear this is causing significant friction for users deploying MCP servers in production environments (Kubernetes clusters, reverse proxies, gateways, etc.).
As other users mentioned above, having standardized environment variables like MCP_ALLOWED_HOSTS, MCP_ALLOWED_ORIGINS, and MCP_DNS_REBINDING_PROTECTION would be extremely valuable.
We ran into this same issue in our MCP server (nextcloud-mcp-server) where we mount FastMCP to a Starlette application for Docker/Kubernetes deployments.
The key issue for this deployment pattern:
When you use mcp.streamable_http_app() or mcp.sse_app() and mount it to a larger Starlette/FastAPI application, there's a disconnect between the web server's bind address and FastMCP's host parameter:
Uvicorn bind address (--host 0.0.0.0): Where the HTTP server listens (set via CLI/Dockerfile)
FastMCP host parameter (defaults to 127.0.0.1): Used for auto-enable logic
Since FastMCP defaults host="127.0.0.1" regardless of how uvicorn is configured, the auto-enable triggers even for servers explicitly bound to 0.0.0.0 for container deployments.
Environment variable support (as others mentioned): MCP_ALLOWED_HOSTS, MCP_ALLOWED_ORIGINS, MCP_DNS_REBINDING_PROTECTION would help containerized deployments configure this without code changes.
Documentation for mounted apps: When using streamable_http_app() or sse_app(), the host parameter doesn't control where the app listens - that's controlled by uvicorn/gunicorn. Consider documenting this distinction.
Consider detection logic: Could the middleware inspect the actual request origin rather than relying on the host parameter? Or perhaps only auto-enable when the app is run via mcp.run() rather than mounted?
Security note: For containerized deployments, DNS rebinding protection may be inappropriate anyway - requests come via Kubernetes service DNS (service.namespace.svc.cluster.local), ingress controllers, or load balancers with varying Host headers. Network-level isolation and OAuth authentication are typically the security boundaries instead.
This kind of annoying behavior is expected when enforcing security on the wrong layer. I'm still against the TransportSecurity object, as I was in the PR that introduced it.
@maxisbey@pcarleton this issue has a lot of thumbs up, can you please take a look?
Reacted by Chris Coutinho, Madlad, Junyi Hou, Stephen Eckels, FOTempel and tekHedd
This kind of annoying behavior is expected when enforcing security on the wrong layer. I'm still against the TransportSecurity object, as I was in the PR that introduced it.
@maxisbey@pcarleton this issue has a lot of thumbs up, can you please take a look?
At the very least allow us to configure it with our own allowed_hosts and allowed_origins (or gasp disable it with a simple switch in a trusted environment) without reverse engineering and rebuilding every MCP container out there that uses this stuff. My LLM and agents run in separate containers, and as it is now I cannot use any MCP server container that's built on this library.
Activity
Junyi-99 commentedon Dec 17, 2025
@cbcoutinho @jerome3o-anthropic @maxisbey I suggest adding some documents for
Invalid Host Header. Because this kind of problem often occurs in the cluster deployment.maxisbey commentedon Dec 18, 2025
Yep I agree, adding documentation around this would be a really good idea!
fix: configure TransportSecuritySettings for production Host validation
fix modelcontextprotocol/python-sdk#1798
Fix DNS rebinding protection for reverse proxy
fix: disable DNS rebinding protection for reverse proxy deployment
princerb commentedon Jan 10, 2026
Can any env vars currently configure for this, like
MCP_ALLOWED_HOSTSandMCP_ALLOWED_ORIGINS?zemin-piao commentedon Jan 20, 2026
+1 to above: it'll be nice if there is a set centralised env vars defined specifically for these configs:
As seen there are more linked issues to this one, with the solution that adding configs / envvars that are mcp servers specific. Having centralised set of env vars can prevent mcp servers implementing customised configs / envvars, saving efforts.
fix: Disable DNS rebinding protection for reverse proxy deployments
Maddest-Lad commentedon Jan 28, 2026
@ddworken @jerome3o-anthropic There really needs to be a better mechanism to set this globally/environmentally beyond passing transport_security to every server instance.
Looking at the growing list of linked issues and commits referencing this problem, it's clear this is causing significant friction for users deploying MCP servers in production environments (Kubernetes clusters, reverse proxies, gateways, etc.).
As other users mentioned above, having standardized environment variables like MCP_ALLOWED_HOSTS, MCP_ALLOWED_ORIGINS, and MCP_DNS_REBINDING_PROTECTION would be extremely valuable.
cbcoutinho commentedon Jan 29, 2026
We ran into this same issue in our MCP server (nextcloud-mcp-server) where we mount FastMCP to a Starlette application for Docker/Kubernetes deployments.
The key issue for this deployment pattern:
When you use
mcp.streamable_http_app()ormcp.sse_app()and mount it to a larger Starlette/FastAPI application, there's a disconnect between the web server's bind address and FastMCP'shostparameter:--host 0.0.0.0): Where the HTTP server listens (set via CLI/Dockerfile)hostparameter (defaults to127.0.0.1): Used for auto-enable logicSince FastMCP defaults
host="127.0.0.1"regardless of how uvicorn is configured, the auto-enable triggers even for servers explicitly bound to0.0.0.0for container deployments.Our workaround:
Suggestions for the SDK:
Environment variable support (as others mentioned):
MCP_ALLOWED_HOSTS,MCP_ALLOWED_ORIGINS,MCP_DNS_REBINDING_PROTECTIONwould help containerized deployments configure this without code changes.Documentation for mounted apps: When using
streamable_http_app()orsse_app(), thehostparameter doesn't control where the app listens - that's controlled by uvicorn/gunicorn. Consider documenting this distinction.Consider detection logic: Could the middleware inspect the actual request origin rather than relying on the
hostparameter? Or perhaps only auto-enable when the app is run viamcp.run()rather than mounted?Security note: For containerized deployments, DNS rebinding protection may be inappropriate anyway - requests come via Kubernetes service DNS (
service.namespace.svc.cluster.local), ingress controllers, or load balancers with varying Host headers. Network-level isolation and OAuth authentication are typically the security boundaries instead.See our fix: https://github.com/cbcoutinho/nextcloud-mcp-server/blob/master/docs/MCP-1.23-DNS-REBINDING-FIX.md
8 remaining items
docs: Add troubleshooting guide for 421 Invalid Host Header error
Fix 421 Invalid Host header: disable DNS rebinding protection for clo…
Add workaround for default allowed hosts
Kludex commentedon Apr 5, 2026
This kind of annoying behavior is expected when enforcing security on the wrong layer. I'm still against the TransportSecurity object, as I was in the PR that introduced it.
@maxisbey @pcarleton this issue has a lot of thumbs up, can you please take a look?
mcp: disable DNS rebinding protection (handled at OAuth + CF layer)
FOTempel commentedon May 10, 2026
At the very least allow us to configure it with our own allowed_hosts and allowed_origins (or gasp disable it with a simple switch in a trusted environment) without reverse engineering and rebuilding every MCP container out there that uses this stuff. My LLM and agents run in separate containers, and as it is now I cannot use any MCP server container that's built on this library.
fix: disable MCP DNS rebinding protection to resolve 421 Invalid Host…
TransportSecuritySettings.allowed_hosts=[](default) silently rejects external Host headers with HTTP 421 #2688 as a duplicate of this issuelaozhangzzz commentedon Jun 25, 2026
docs: retitle hand-offs and link text to match the new nav
maxisbey commentedon Jul 29, 2026
Thanks for the report. Closing this as it's been fixed in v2, which is now released (see #3044). Feel free to reopen if you still hit it on v2.
AI Disclaimer
feat: add FASTMCP_ALLOWED_HOSTS, FASTMCP_ALLOWED_ORIGINS, FASTMCP_TRA…
fix: no Host allowlist needed for HTTP; decide the policy explicitly