fix: configure MCP transport security with env-driven allowed hosts
All checks were successful
ci/woodpecker/push/build Pipeline was successful
All checks were successful
ci/woodpecker/push/build Pipeline was successful
FastMCP auto-enables DNS rebinding protection when host=127.0.0.1 (the default). Production requests from brain.woltje.com were rejected with 421 Invalid Host header because the allowed_hosts list was empty. Added MCP_ALLOWED_HOSTS config field (comma-separated). When set, DNS rebinding protection is enabled with those hosts; when empty, protection is disabled. Set MCP_ALLOWED_HOSTS=brain.woltje.com in Portainer stack env. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -19,5 +19,10 @@ class Settings(BaseSettings):
|
||||
port: int = 8000
|
||||
log_level: str = "info"
|
||||
|
||||
# MCP transport security — comma-separated allowed Host header values.
|
||||
# Set to the public hostname (e.g. "brain.woltje.com") in production.
|
||||
# Empty disables DNS rebinding protection.
|
||||
mcp_allowed_hosts: str = ""
|
||||
|
||||
|
||||
settings = Settings()
|
||||
|
||||
@@ -6,6 +6,7 @@ import logging
|
||||
from fastapi import Depends, FastAPI, HTTPException, Security
|
||||
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
from mcp.server.transport_security import TransportSecuritySettings
|
||||
|
||||
from src import brain, db
|
||||
from src.config import settings
|
||||
@@ -29,7 +30,12 @@ def require_api_key(credentials: HTTPAuthorizationCredentials = Security(bearer)
|
||||
# ---------------------------------------------------------------------------
|
||||
# MCP server
|
||||
# ---------------------------------------------------------------------------
|
||||
mcp = FastMCP("openbrain", stateless_http=True)
|
||||
_allowed_hosts = [h.strip() for h in settings.mcp_allowed_hosts.split(",") if h.strip()]
|
||||
_transport_security = TransportSecuritySettings(
|
||||
enable_dns_rebinding_protection=bool(_allowed_hosts),
|
||||
allowed_hosts=_allowed_hosts,
|
||||
)
|
||||
mcp = FastMCP("openbrain", stateless_http=True, transport_security=_transport_security)
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
|
||||
Reference in New Issue
Block a user