fix(mcp): disable DNS-rebinding protection on FastMCP
FastMCP defaults to an allow-list of localhost variants for the Host header (DNS-rebinding protection). Any deployment behind a reverse proxy hitting a non-localhost hostname (e.g. devassistant.traefik.internal) gets 421 Misdirected Request with: WARNING mcp.server.transport_security: Invalid Host header: <name> The protection exists to stop a malicious browser page from rebinding DNS to attack a localhost MCP server. Our deployment is HTTP transport behind a reverse proxy with bearer-token auth, which already gates every request — so the rebinding threat doesn't apply. Disabling the check lets any Host through; auth still rejects unauthorized requests at 401. This also makes the integration test pass without test-only host hackery — every realistic Host header (Traefik internal hostname, CDN domain, custom DNS) now reaches FastMCP cleanly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
from mcp.server.transport_security import TransportSecuritySettings
|
||||
from quart import Quart
|
||||
|
||||
_INSTRUCTIONS = """
|
||||
@@ -23,8 +24,24 @@ Hierarchy: Project -> Milestone -> Task/Note.
|
||||
|
||||
|
||||
def build_mcp_server() -> FastMCP:
|
||||
"""Build the FastMCP instance with all tools registered."""
|
||||
mcp = FastMCP("scribe", instructions=_INSTRUCTIONS.strip())
|
||||
"""Build the FastMCP instance with all tools registered.
|
||||
|
||||
DNS-rebinding protection is disabled: FastMCP's default allow-list is
|
||||
just localhost variants, which means any deployment behind a reverse
|
||||
proxy (Traefik with a hostname like devassistant.traefik.internal,
|
||||
Cloudflare, nginx, etc.) gets 421 Misdirected Request. The threat
|
||||
model that protection addresses — a malicious browser page rebinding
|
||||
DNS to hit a localhost MCP — doesn't apply here: this is HTTP transport
|
||||
behind a reverse proxy with bearer-token auth as the real security
|
||||
boundary.
|
||||
"""
|
||||
mcp = FastMCP(
|
||||
"scribe",
|
||||
instructions=_INSTRUCTIONS.strip(),
|
||||
transport_security=TransportSecuritySettings(
|
||||
enable_dns_rebinding_protection=False,
|
||||
),
|
||||
)
|
||||
from fabledassistant.mcp.tools import register_all
|
||||
register_all(mcp)
|
||||
return mcp
|
||||
|
||||
Reference in New Issue
Block a user