fix(deployment): disable fastmcp host-origin guard behind the runtime proxy#4205
Open
AnayGarodia wants to merge 1 commit into
Open
fix(deployment): disable fastmcp host-origin guard behind the runtime proxy#4205AnayGarodia wants to merge 1 commit into
AnayGarodia wants to merge 1 commit into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #4199.
Summary
FastMCP >= 3.4.3 turns on DNS-rebinding (Host header) protection by default. The MCP launcher runs behind the runtime reverse proxy (modal / tower / local runner), which rewrites the
Hostheader, so with the allowlist defaulting to localhost the guard rejects every request with421 Misdirected Request. The server starts but never serves a usable request.Fix
run_mcp_instancenow passeshost_origin_protectiontoinstance.run(), driven by a newMcpConfiguration.host_origin_protectionfield that defaults toFalse(these servers only receive traffic from the authenticated runtime proxy, so the guard is redundant). It stays overridable for anyone who wants it on.Because dlt pins
fastmcp>=3.0.0but the option only exists in>=3.4.3, the argument is passed only when the installed FastMCP supports it (version-gated) — passing it to an older FastMCP would raiseTypeError. Older versions never had the guard, so they need no change.This replaces the interim
fastmcp<3.4.3pin in the test workspace: real deployments on the runtime were still broken until the launcher itself was fixed.Tests
Two unit tests in
tests/workspace/deployment/test_launchers.py: the arg is passed asFalsewhen supported, and omitted when not.black/ruff/mypypass on the changed files.Note
I went with option 1 from the issue (disable the guard for these proxied deployments) rather than a static allowlist, since the forwarded
Hostdiffers per backend (modal*.modal.host, tower, local*.dltrun.*) so no single allowlist works. Happy to switch to a config-driven per-backend allowlist if you prefer.