mcp: CORS on the streamable-http app (answer OPTIONS preflight without auth)
build-image / test (push) Failing after 3h13m8s
build-image / build (push) Has been skipped

OPTIONS /mcp returned 401 (auth layer rejecting the preflight) with no CORS
headers, which blocks browser-based MCP clients / connector setup. Build the app
explicitly and add CORSMiddleware (wildcard origin — bearer-token auth, no cookies)
so preflight is answered 200 and Mcp-Session-Id/WWW-Authenticate are exposed.
This commit is contained in:
2026-07-06 22:13:36 -04:00
parent 41b9c7a99a
commit 5f2c55c865
+16 -1
View File
@@ -69,10 +69,25 @@ def start_server(mcp_instance: FastMCP, transport: TransportAliases) -> None:
)
mcp_instance.run(transport="sse", mount_path=mount_path)
else: # STREAMABLE_HTTP
import uvicorn # noqa: PLC0415
from starlette.middleware.cors import CORSMiddleware # noqa: PLC0415
logger.info(
"Starting MCP server with Streamable HTTP transport at http://%s:%s%s.",
host,
port,
mcp_instance.settings.streamable_http_path,
)
mcp_instance.run(transport="streamable-http")
app = mcp_instance.streamable_http_app()
# CORS so browser-based MCP clients / connector setup can reach /mcp — the
# preflight is what matters: CORSMiddleware answers OPTIONS directly (200)
# instead of the auth layer rejecting it (401). Bearer-token auth, no
# cookies, so a wildcard origin is safe; expose the headers clients read.
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
expose_headers=["Mcp-Session-Id", "WWW-Authenticate"],
)
uvicorn.run(app, host=host, port=port, log_level=os.getenv("FASTMCP_LOG_LEVEL", "info").lower())