MCP servers
An MCP server is a tool provider the agent can call. The set of MCP servers on a session is the session’s blast radius — the complete list of things the agent can do outside its own clone.
The entry format
Section titled “The entry format”MCP is the one artifact type with no separate body — the index entry is the connection config.
From mcp.json:
"playwright-custom": { "title": "Playwright Custom", "description": "Playwright MCP server for browser automation and screenshots.", "type": "stdio", "command": "npx", "args": ["-y", "playwright-stealth-mcp-server@latest"], "env": { "STEALTH_MODE": "false", "HEADLESS": "true" }, "default_in_roots": ["zimmer"]}| Field | Notes |
|---|---|
type | stdio | sse | streamable-http (http) |
command / args / env | stdio servers |
url / headers | remote servers |
oauth | remote servers that need an OAuth flow |
default_in_roots | which roots get it by default |
env and headers values may contain ${VAR} placeholders.
The formal schema is published by AIR at
pulsemcp.github.io/air/schemas/mcp.schema.json
— which is what mcp.json’s own $schema key points at. A snapshot is also served from this site at
/mcp.schema.json.
Secrets never touch the catalog
Section titled “Secrets never touch the catalog”The catalog carries the placeholder. The environment carries the value. The transform joins
them at prepare time, and AIR then validates that no ${VAR} survived and fails if any did.
That validation is the good part: a typo’d secret name fails loudly at prepare, before the agent ever gets a server that 401s on every call.
Zimmer’s SecretsLoader resolves values in this order: XOauthTokenVendor (for X/Twitter tokens)
→ Rails encrypted credentials (mcp_secrets) → ENV.
Selection is per session
Section titled “Selection is per session”A session’s server list is seeded from the agent root’s defaults and then owned by the session.
The UI and the API (PATCH /api/v1/sessions/:id/mcp_servers, max 50) mutate it directly, and air prepare runs with --without-defaults so AIR won’t re-add what you removed.
Beyond the ones you pick, a session also gets auto-injected servers — most notably the
self-session server (SelfSessionInjector), which is how an agent can archive itself, set its own
title, or schedule its own wake-up. session_json exposes three fields for this:
mcp_servers (what you chose), injected_mcp_servers, and all_mcp_servers.
Remote servers and OAuth
Section titled “Remote servers and OAuth”A remote server (http / streamable-http / sse) with no static Authorization header is assumed
to possibly need OAuth. Before spawn, McpOauthCredentialInjector checks each one; if any lacks a
valid credential, the session is parked in failed with failure_reason: oauth_required, and
the UI renders Authorize buttons.
→ MCP server OAuth for the full flow.
MCP connection status is inferred from logs
Section titled “MCP connection status is inferred from logs”There is no protocol-level “did this server connect” signal that Zimmer consumes. Instead:
- Claude:
McpLogPollerServicescrapes the CLI’s MCP log files. - Codex:
CodexMcpStatusDetectorstring-matches tool names againstcodex-rs’sMCP_TOOL_NAME_DELIMITER = "__", and reimplements Codex’s internalsanitize_responses_api_tool_namecharacter rules in Ruby.
Timeouts and caching
Section titled “Timeouts and caching”MCP_TIMEOUT = 180000(3 minutes) — a flat startup timeout for every MCP server.NPM_CONFIG_CACHEis set to a clone-local.npm-cache, sonpx-based servers don’t fight over a shared cache.NpxCacheHealServiceexists to detect and delete a corrupted_npxcache — by matching npm’s error text (ENOTEMPTY,ERR_UNSUPPORTED_DIR_IMPORT). An entire service that self-heals a filesystem bug by regexing stderr.MCP_PACKAGE_REINSTALLandDockerfile.base’sbin/preinstall-mcp-packagespre-warm the npm and python packages listed inmcp.json, so a cold session doesn’t pay the download.
The fourteen that ship
Section titled “The fourteen that ship”playwright-custom (the only one default-on, for the zimmer root), context7, linear, and
eleven others. Read mcp.json for the current list — it changes more often than this page will.