快速结论:该报错通常发生在通过反向代理(Nginx、Caddy)、Cloudflare Tunnel、Kubernetes 或自定义域名访问 MCP 服务器时——SDK 自带的 DNS 重绑定防护机制会检查 Host 头,若不在允许列表内则返回 421。优先排查 FastMCP 的 transport_security 配置,显式加入你的网关域名或端口。
适用环境:MCP Python SDK(v2 相关更新,提交 86bb54c、PR #861 引入 DNS 重绑定防护);受影响文件为 src/mcp/server/fastmcp/server.py:178。Issue 中未明确确认特定 Python/CUDA/显卡版本。
最快修复方案:在 FastMCP 实例化时显式传入 TransportSecuritySettings,将网关或自定义域名加入 allowed_hosts 和 allowed_origins(端口可用 * 通配);确认代理正确传递原始 Host 头。
注意事项:若服务通过 streamable_http_app() 或 sse_app() 挂载到 Starlette/FastAPI 应用时,FastMCP 的 host 参数不控制实际监听地址(由 uvicorn/gunicorn 控制),此场景下默认 host="127.0.0.1" 可能触发自动启用防护,需手动设置。关闭防护仅建议本地开发或已有其他安全边界时使用。
问题场景
用户运行 MCP Python SDK 构建的 FastMCP 服务器,在以下常见部署模式下触发 421:
- 通过 Nginx、Caddy、Cloudflare Tunnel 等反向代理暴露服务
- Docker/Kubernetes 容器部署,服务绑定
0.0.0.0 - 使用自定义域名或集群内部 DNS(如
service.namespace.svc.cluster.local)访问 - 将
streamable_http_app()或sse_app()挂载到更大的 Starlette/FastAPI 应用
报错原文
421 Misdirected Request / Invalid Host Header
原因分析
可能原因是 SDK 在提交 86bb54c(PR #861)引入了 DNS 重绑定防护:当 FastMCP 的 host 参数被设置为 0.0.0.0(或默认值 127.0.0.1 与代理传入的 Host 不匹配)时,防护机制自动启用并生成空白的 allowed_hosts 列表,导致所有外部请求因 Host 头不在允许列表中而被拒绝。该行为在启动时无警告,错误响应中也没有排查提示。
另一种可能原因是:当服务通过 streamable_http_app()/sse_app() 挂载到更大的 Web 应用时,存在“服务器绑定地址”与“FastMCP host 参数”之间的脱节——即使 uvicorn 监听 0.0.0.0,FastMCP 内部默认 host="127.0.0.1" 也可能触发自动启用逻辑。
环境排查
- 确认 MCP Python SDK 版本是否包含提交
86bb54c(PR #861)之后的行为变化 - 确认 uvicorn/gunicorn 实际监听地址(如
0.0.0.0)与 FastMCPhost参数之间的差异 - 确认反向代理是否修改或传递了正确的
Host头 - 检查是否配置了环境变量(Issue 中社区建议增加
MCP_ALLOWED_HOSTS/MCP_ALLOWED_ORIGINS/MCP_DNS_REBINDING_PROTECTION,但未确认已被实现,需查阅当前 SDK 文档)
解决步骤
- 方案一(推荐,保留防护):在 FastMCP 初始化时显式传入
TransportSecuritySettings,将你的网关域名、服务名或自定义域加入白名单(端口可用*通配):from mcp.server.fastmcp import FastMCP from mcp.server.transport_security import TransportSecuritySettings mcp = FastMCP( "MyServer", transport_security=TransportSecuritySettings( enable_dns_rebinding_protection=True, allowed_hosts=["localhost:*", "127.0.0.1:*", "your-gateway-host:*"], allowed_origins=["http://localhost:*", "http://your-gateway-host:*"], ) ) - 方案二(本地开发或已有安全边界时):直接关闭 DNS 重绑定防护:
transport_security=TransportSecuritySettings( enable_dns_rebinding_protection=False, ) - 检查反向代理配置:确保 Nginx/Caddy/Cloudflare Tunnel 将原始
Host头传递给 MCP 服务器,不要覆盖或重写。 - 若使用
streamable_http_app()/sse_app()挂载:需明确该函数返回的 app 实际由 uvicorn/gunicorn 监听,FastMCP 的host参数不控制监听地址。建议始终显式设置TransportSecuritySettings,不要依赖自动检测。 - 可优先尝试:如果不想修改代码,检查是否可通过环境变量配置(截至 Issue 讨论时未确认支持,需查阅最新 SDK 文档)。社区建议的
MCP_ALLOWED_HOSTS/MCP_ALLOWED_ORIGINS/MCP_DNS_REBINDING_PROTECTION可作为未来改进方向,但在当前版本中可能不可用。
验证方法
修改配置后,通过代理域名或外部地址发起一次 MCP 请求,确认不再返回 421 Invalid Host Header,且响应中无 421 Misdirected Request 状态码。若关闭防护,需确认服务仍能正常处理请求(注意此时 DNS 重绑定防护不再生效)。对于容器部署,可检查代理日志和 MCP 服务器日志确认 Host 头是否匹配白名单。
参考来源
modelcontextprotocol/python-sdk #1798
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。


