Skip to content

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
def __init__(self, app):
    self.app = app

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
def 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://``.
    """
    return {"proxy_headers": True, "forwarded_allow_ips": "*"}

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
def 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.
    """
    from .deploy import build_validate_handler

    handler = build_validate_handler(
        rsa_private_key_pem=rsa_private_key_pem,
        internal_base_url=internal_base_url,
        internal_secret=internal_secret,
    )
    mcp.custom_route("/internal/validate", methods=["POST"])(handler)