Connectors
A connector gives an agent the tools of a service: Sentry, GitHub, or anything that speaks MCP.
The agent names a connection by id. The engine holds the URL and the credential, reads the tools the connection offers, and runs every call. Your worker never sees a token.
Declare a connection
MCP servers go under [mcp.<id>].
[mcp.sentry]
url = "https://mcp.sentry.dev/mcp"
[mcp.github]
url = "https://api.githubcopilot.com/mcp/"
auth = { token_env = "GITHUB_TOKEN" }
prefix_tools = falseThe file holds names and references. A token written in the file is a parse
error.
Authorize it
A server that takes a static credential needs nothing more. The engine reads
$token_env when it makes the call.
Every other server uses OAuth. A person must consent in a browser.
subs mcp login sentry
subs mcp listThere is no logout. Delete the [mcp.<id>] section to disconnect. The
credential goes with it.
The credential belongs to the id. Declare one server twice to connect two accounts. Authorize each id on its own.
[mcp.sentry]
url = "https://mcp.sentry.dev/mcp" # subs mcp login sentry
[mcp.sentry2]
url = "https://mcp.sentry.dev/mcp" # subs mcp login sentry2An agent with both sees sentry__ and sentry2__ tools.
Where the credential lives
The file decides.
| The file has | The credential goes |
|---|---|
No [remote] | Into that environment's db, with the sessions that use it. |
A [remote] | Into the deployment. It never reaches your machine. |
A local database holds credentials. Add *.db* to .gitignore.
With a [remote], authorizing takes two steps.
- Declaring records the id and the URL.
subs applydeclares every[mcp.<id>]in the file. - Authorizing is the consent.
subs mcp login does both. A declared connection reaches nothing until someone
consents.
auth belongs to a local engine. It names a variable on this machine. subs apply and subs mcp login refuse a connection that carries one. Remove auth
and authorize on the deployment instead.
Some deployments allow only the URLs in their own catalog. The error lists them.
Give it to an agent
An agent names a connection by id. An id on its own takes every tool the connection offers. Use the table form to take fewer.
[agent.support]
mcp = ["sentry"]
[agent.triage]
mcp = [{ id = "sentry", tools = { read_only = true } }]The filter belongs to the agent. These two agents share one connection and one credential, and see different tools.
A worker declares the same thing in the config it returns.
if (trigger.type === "session.start") {
return {
agent: {
model: "claude-haiku-4-5",
mcp: [{ id: "sentry", tools: { read_only: true } }]
}
};
}The model now sees sentry__search_issues beside your own tools. When it calls
one, the engine runs it. Your worker still sees the call: tool.finished
arrives with the result.
Filtering
A connection can offer a hundred tools. Above about forty, a model chooses badly. Take fewer.
type McpTools = {
include?: string[] // globs over the tool's name on the connection
exclude?: string[]
read_only?: boolean
non_destructive?: boolean
idempotent?: boolean
}The engine applies the capability keys, then include, then exclude. Each one
can only remove tools.
The globs match the tool's name on the connection, not the prefixed name the model sees.
The capability keys read the connection's MCP annotations. A tool with no annotation fails them. Annotations are hints from the server. Use them to take fewer tools, not as a security boundary.
Names
The engine prefixes a connection's tools with its id, such as sentry__search.
Set prefix_tools = false to use their own names.
The engine resolves each name against everything else the model can call. If two names match, it drops one.
- A tool you declared, or a sub-agent id, keeps its name.
- If two connectors have the same name, both lose it.
The engine reports every name it drops.
When tools are fetched
The engine fetches a connection's tool list once per session, the first time a config names it. It never refreshes the list during a session, so the model never calls a tool that has disappeared.
The turn waits while a fetch runs. If the fetch fails, the turn runs without those tools.
Next
- Tool calls: tools your worker runs.
- Agents: the section that names a connection.
- Sub-agents: put a large connector behind a child agent.