Skip to main content

Single-Connection Servers

For single-connection servers, name is optional and dispatch auto-resolves:
gmail = Connection(secrets=SecretKeys(token="GMAIL_TOKEN"))  # No name needed

async def _req(method, path, body=None):
    ctx = get_context()
    return await ctx.dispatch(HttpRequest(method=method, path=path, body=body))

Connection Naming

Connection names are derived from your server’s slug: windsor/gmail-mcp -> gmail-mcp. If you hardcode a different name in dispatch("gmail", ...), it will fail. Use auto-dispatch for single-connection servers.

Multi-Connection Servers

When you have multiple connections, specify the target explicitly:
await ctx.dispatch("gmail", HttpRequest(...))
await ctx.dispatch("calendar", HttpRequest(...))
Each connection requires a separate OAuth flow. Pass connection_name when creating the session:
# API creates session with explicit connection name
session = await admin_api.create_oauth_session(
    server_id=deployment_id,
    scopes=["gmail.readonly"],
    connection_name="gmail",  # Stored with this name
)

Debugging

Connection not found? Check what’s in the JWT:
@tool(description="Debug")
async def debug() -> dict:
    ctx = get_context()
    return {"connections": list(ctx.runtime.get("connections", {}).keys())}