Model Context Protocol servers add tools from outside. Each one is started on launch and its tools are registered alongside the built-ins.
They live in ~/.config/raunen/mcp.json rather than the main config, so a server that needs a secret in its env is not shoulder-to- shoulder with the model defaults, and can be shared without dragging the rest of the config along.
stdio runs a local subprocess and speaks JSON-RPC over its stdin and stdout. http posts to a remote Streamable-HTTP endpoint. Empty means stdio.
{
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "."]
},
"example": {
"type": "http",
"url": "https://example.com/mcp/",
"headers": { "Authorization": "Bearer โฆ" }
}
}Headers are forwarded verbatim and nothing expands variables. A token written here sits in the file in plain text โ it is written 0600, but an env-var-based server (env on a stdio server) is the better place for a secret.
A server can be defined and left out of mcp_enabled in the main config, so it stays configured but does not start. An empty list means start every defined server.
"mcp_enabled": ["filesystem"]Connecting to a server is a round trip, and waiting for it before drawing anything is what used to make raunen slow to start. So servers connect alongside the terminal rather than in front of it: the prompt appears immediately, and the tools arrive a moment later. The first turn waits for them, which in practice has already happened by the time anything is typed.
A server is optional this way by default. Set required when a turn is not worth starting without it โ a workflow built around one particular toolset โ and accept that its handshake becomes part of how long raunen takes to start.
"filesystem": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "."], "required": true }
A server that does not start says why in /mcp, in the words the endpoint used, rather than only on the way past.
A tool is charged to the context of every request, whether or not it is ever called: its name, description and full JSON Schema travel with each turn. That is affordable for a handful and ruinous for a server advertising a hundred, which can be more schema than a local model has window.
So past a handful of tools they are held back and reached through two small ones instead โ mcp_search_tools to find a tool by keyword, and mcp_select_tool to load it. Only what a task actually needs is paid for. A hundred-tool server costs about 215 tokens a request rather than 11,000, and the model calls the tool normally once it is loaded.
Nothing is configured. A small server is registered directly, since the two extra tools would cost more than the schemas they save.
A remote server that uses OAuth connects like any other: deferred, so the terminal draws first and the handshake finishes in the background. What was never right was blocking for it โ its login prints a URL and waits for a browser, and once the terminal has taken over the screen that instruction has nowhere to go. So a server that needs a login simply fails to connect and says so in /mcp, in the server's own words.
Log in deliberately, when there is a terminal to read the URL, with /mcp auth. It opens a browser and, if one cannot be, shows the URL in the transcript to finish by hand. The stored token is what makes the next run connect quietly.
/mcp auth github
/mcp logout drops a server's stored token. The server keeps running on the token it already holds, so logout decides the next run, not this one.
/mcp lists what is defined, what is active, and how many tools each one provided.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ mcp filesystem 11 tools example off 1 servers ยท 11 tools
A server that is active but shows not started failed to launch or did not complete the handshake โ /status and RAUNEN_DEBUG=1 say more.