run
run ¶
Deployment entrypoint for the multi-tenant Domo MCP server (HTTP transport).
Run with: python -m crew_dcs.mcp_server
Wires the datacrew resolver (dc_ token -> per-instance Domo credential) and a JWTVerifier for token validation, then serves the crew-dcs tool surface with the primary-tier disclosure posture.
Required env (set via Infisical at deploy): DOMO_VPS_RSA_PRIVATE_KEY PEM (PKCS8) — VPS envelope private key (sole decryptor) WEBUI_INTERNAL_SECRET shared secret for datacrew.space internal endpoints Optional env: DOMO_MCP_JWKS_URL (default https://datacrew.space/.well-known/jwks.json) DOMO_MCP_ISSUER (default https://datacrew.space) DOMO_MCP_AUDIENCE (default https://domo.datacrew.space) DOMO_MCP_INTERNAL_BASE (default https://datacrew.space) DOMO_MCP_HOST / DOMO_MCP_PORT (default 0.0.0.0 / 3000)
Proxy correctness (deployed behind Caddy + Cloudflare Tunnel, TLS terminates at
the proxy):
- proxy_uvicorn_config makes uvicorn trust X-Forwarded-Proto so any
redirect Location is built with https:// instead of http://. A
cross-scheme redirect makes HTTP clients drop the Authorization bearer,
which previously turned a /mcp/ request into an unauthenticated 401 and
broke Letta tool discovery.
- StripTrailingSlash rewrites /mcp/ to /mcp in the ASGI scope
before routing, so the trailing-slash form is served by the canonical route
with no redirect at all (belt-and-suspenders with the scheme fix above).
These are wired through the supported FastMCP 3.3.1 mcp.run knobs:
uvicorn_config (forwarded verbatim to uvicorn.Config) and middleware
(a list of Starlette Middleware applied to the streamable-HTTP app).
NOTE (HITL / deploy-time verification): confirm the FastMCP HTTP transport string and the JWTVerifier import path against the installed FastMCP version.
StripTrailingSlash ¶
StripTrailingSlash(app)
ASGI middleware that strips a single trailing slash from the request path.
Starlette's router redirects /mcp/ to /mcp (307) by default. Behind a
TLS-terminating proxy that redirect can switch scheme and make clients drop
the Authorization header. Rewriting the path in the scope makes /mcp/
resolve to the canonical route directly, so no redirect is emitted.
Source code in src/crew_dcs/mcp_server/run.py
53 54 | |
proxy_uvicorn_config ¶
proxy_uvicorn_config() -> dict[str, Any]
uvicorn.Config kwargs that trust the reverse proxy's forwarded headers.
With proxy_headers on and forwarded_allow_ips open, uvicorn honors
X-Forwarded-Proto: https (set by Caddy) so request URLs — and any
redirect Location built from them — use https://.
Source code in src/crew_dcs/mcp_server/run.py
68 69 70 71 72 73 74 75 | |
register_validate_route ¶
register_validate_route(
mcp,
*,
rsa_private_key_pem: str,
internal_base_url: str,
internal_secret: str
) -> None
Register POST /internal/validate as a FastMCP custom HTTP route.
Custom routes are appended to the streamable-HTTP app outside the
RequireAuthMiddleware that wraps the /mcp transport (FastMCP 3.3.1
only guards the MCP path), so this endpoint bypasses the dc_ JWTVerifier and
is gated solely by the X-Webui-Secret shared secret checked in-handler.
Source code in src/crew_dcs/mcp_server/run.py
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | |