MCP servers
The MCP Servers module (admin-only) connects agent runs to tools offered by an external Model Context Protocol server — a translation service, a ticket system, any MCP-speaking backend.
How it works
- Configure a server — endpoint, authentication, the class of data its tools may see, and whether its tools need human approval. A server that declares no data class supplies nothing: there is no default anybody silently inherits (fail-closed, ADR-113).
- Import its catalogue — an explicit action that fetches the tools the server advertises. Import is the only network call that happens outside an agent run; nothing talks to the server just because a page rendered. Tool input schemas are normalised into the supported subset on import; a tool whose schema cannot be expressed is skipped rather than silently weakened.
- Enable individual tools — imported tools start disabled and are switched on one by one, exactly like the builtin tools in the Tools module.
Is the server alive?
Test connection performs the MCP handshake and reports what came back: how long it took, which protocol revision the server chose and what the server calls itself. The report appears on the server's card and stays there until you leave the page — only the latency is stored, so the rest would be lost to a page reload, and this is the one action in the module that therefore does not reload. It writes no catalogue — no tool is added, removed or orphaned, and the import status and the last import error stay exactly as they were. Use it to check a server before enabling it, and to tell "the server is down" from "the server is fine and this tool is gone".
Each server card also shows Last successful contact. That is the last time this installation completed any round trip against the server — a tool call, an import or a connection test — together with how long that round trip took. It is deliberately not the same as Last import: a server that has been answering tool calls all month can still show an import from six weeks ago, and previously there was no way to see the difference.
A failed connection test replaces the report on the card with its reason, and is stored nowhere. Only a success moves the contact date.
Guard rails
- Remote tools always require an administrator, and count as non-idempotent writes — unconditionally, whatever the server's catalogue says about them: they are never replayed on a retry, and never waved through the trust-zone gate in observe mode. That the classification cannot be argued down from the far side is what makes the setting below the only place the question is answered.
- Requires approval decides whether an agent run stops and waits for a person before it calls any tool of this server. It is on for a newly configured server: what a remote tool actually does cannot be inspected from here, and the server's own annotations do not get to answer the question about themselves (ADR-134). Switch it off per server once you know what its tools do. This holds for every server, including one configured before the setting existed: an update leaves it requiring approval, and nothing switches that off on your behalf.
- The number of remote calls one run may make is bounded (default: 20) — a remote call crosses the network while a backend user waits, and nothing else limits how many a model asks for at once.
What a remote answer can contain
An MCP server may answer a tool call with several typed blocks: text, images, embedded resources. This client reads text only. When a server sends anything else, the blocks are dropped and the answer opens with a line saying how many were dropped and of which type — so a model reading a partial answer is told it is partial, and a run whose tool returned only an image is not told the tool returned nothing. The line comes first because a long answer is shortened before the model sees it, and a note at the end would be the part that is cut. If you need the image itself, the tool is not usable from here yet.
A call that fails does not fail the run. It comes back as a failed tool result naming the server, the model is told, and the run carries on. This covers both ways a call fails: the server not answering usefully — it is down, it refuses the credential, it sends something that is not JSON-RPC — and the server answering that the tool itself failed, which is the ordinary case of a missing page or a rejected argument. Both are recorded as failures in the run's event stream, so a server that is flaky is visible without reading transcripts.
See ADR-116 for the design rationale, ADR-154 for what liveness is measured on and why the connection test writes nothing, and ADR-161 for the conformance suite every supported connection is held to — including the one thing it does not do: cancelling a call that is already in flight. Cancelling a run stops it at the next step, but an outstanding remote call still runs to its 15-second timeout.