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())}
Last modified on February 6, 2026