MCP Integration
Connecting MCP servers to Orchid agents: none, passthrough, and OAuth auth modes.
Orchid agents can call any MCP server over Streamable HTTP or SSE transport. The connection is configured per-server in agents.yaml; the framework handles capability discovery, caching, and per-user authentication transparently.
The MCP client interface
OrchidMCPClient in orchid_ai/core/mcp.py combines two narrower ABCs:
OrchidMCPToolCaller— code that only invokes tools depends on thisOrchidMCPDiscoverable— code that discovers capabilities depends on this
StreamableHttpMCPClient in orchid_ai/mcp/client.py is the concrete implementation. It keeps an in-memory capability cache that is populated once (proactively at startup or session-start) and flushed only via explicit invalidate_cache() calls.
Three auth modes
Each MCP server declaration carries exactly one field under auth: — the mode. No credentials, no endpoints, no client IDs live in config.
mcp_servers:
- name: public-weather
url: https://weather.example.com/mcp
# auth defaults to: mode: none
- name: tenant-catalog
url: https://catalog.example.com/mcp
auth:
mode: passthrough
- name: external-crm
url: https://crm.example.com/mcp
auth:
mode: oauth| Mode | Behaviour |
|---|---|
none (default) | No auth headers. For local or public servers. |
passthrough | Forwards the graph's OrchidAuthContext bearer token on every call. The MCP server and Orchid share the same identity provider. |
oauth | Full MCP 2025-03-26 flow. On the first 401 the framework discovers everything — protected resource metadata, authorization server metadata, and dynamic client registration — and stores per-user tokens in OrchidMCPTokenStore. See OAuth & Authentication. |
cache_ttl is rejected
OrchidMCPServerConfig is declared with extra="forbid". Adding cache_ttl: to a server block raises a Pydantic validation error at startup. Capability caches have no TTL; they live for the process lifetime and are flushed via invalidate_cache() or OrchidSessionWarmer.invalidate_user().
Proactive capability warming
The framework warms MCP capability caches at well-defined boundaries so the per-request hot path never pays discovery cost:
| Boundary | What gets warmed |
|---|---|
| Process startup | Every auth.mode: none server |
User session start (POST /session/warm) | Every passthrough and oauth server |
| Post-OAuth callback | The freshly-authorised server |
OrchidSessionWarmer drives all three boundaries. It is idempotent per (tenant_key, user_id) pair.