Plug in any Model Context Protocol server (stdio, HTTP, or SSE) by declaring it in config.yaml. Its tools register as mcp_<server>_<tool> and join the agent behind the same approval gate as the built-ins. /mcp shows connection status and the tools each server added, and /mcp reload applies a config edit without restarting.
mcp:
connect_timeout: 20
call_timeout: 60
servers:
github:
command: npx
args: ["-y", "@modelcontextprotocol/server-github"]
env:
GITHUB_PERSONAL_ACCESS_TOKEN: ${GITHUB_TOKEN}
internal-docs:
url: https://mcp.example.com/mcp
headers:
Authorization: Bearer ${EXAMPLE_TOKEN}
risk: read_onlytransport
stdio | http | sse. Optional: inferred from command (stdio) or url (http).
command / args / env
stdio: the server process to spawn
url / headers
http/sse: the remote endpoint
risk
the default tier for the server's tools. Omitted or invalid means destructive (always asks). This is your trust declaration: the server's own annotations never drive the gate. To set one tool: /policy risk <tool> <tier> --save.
enabled: false
keep the entry but skip the connection
::trust rules
- –Remote tools always ask until you lower their tier. A server's own "read-only" claim is never trusted;
/mcpshows it as a hint only. - –Their results, error text included, are untrusted input and pass through the injection quarantine.
- –Every remote (HTTP/SSE) call is a recorded egress event. A stdio server is a local process Saturn can't see inside, so each call to one is recorded as
untracked. - –Under
/policy airgap on, remote calls refuse, and every MCP call asks you first, even with its tier lowered or the gate open. A headless run refuses them. - –At the gate, an MCP tool's arguments render full-width, and a secret in them warns inline.
- –
${VAR}inurl,args,env, andheadersexpands from your environment or.env, so secrets never sit in the config file.
note
A server that misses connect_timeout at startup is reported and skipped. A call that runs past call_timeout fails cleanly, and the answer reports it like any other failed call.