MCP servers
Subspace speaks the Model Context Protocol (MCP): each MCP server is a page in the
mcp/ directory, an agent binds the servers it needs, and their tools appear to the model
as mcp.<server>.<tool> with the server’s real JSON Schema. Binding is opt-in and per
agent, the toolset is snapshotted and journaled at run start, and a trust note lets you
review a server’s tools before you ever bind it, because server-provided tool descriptions
are a prompt-injection surface.
Server pages
Section titled “Server pages”A mcp/ page carries a metadata.mcp block. There is one page per server:
---mcp: transport: { http: https://mcp.example.com/v1 } headers: { Authorization: EXAMPLE_MCP_TOKEN } trust: { search: always, delete_record: never }---
# example-tools| Field | Meaning |
|---|---|
transport |
{ http: url } for a remote server, or { stdio: 'command args…' } to spawn a local process. |
headers |
HTTP header name to ops.secrets name. Resolved at connect time, never stored in the page. |
env |
Stdio child env var to ops.secrets name. The child sees only these plus PATH. |
trust |
Per-tool gate override, { tool: 'always' | 'never' }. Default is always (gated). |
enabled |
Set false to suspend the server. The toggle is authoritative. |
Secrets resolve through the capability broker
from ops.secrets at connect time, so rotating a token is a row update.
Binding to an agent
Section titled “Binding to an agent”Binding is opt-in. A definition lists servers in mcp: string[]; absent means none.
This is deliberately stricter than skills (which default to all): an agent reaches an
external server only when its definition names it.
---agent: mcp: [example-tools] tools: [kb.search, "mcp.example-tools.search"] # allowlist applies over the union---At run start the bound servers’ toolsets are snapshotted into the journaled definition
message (failure-tolerant per server, so one dead server does not sink the run) and
registered for that run as mcp.<server>.<tool>, passing the server’s real JSON Schema to
the model. The definition’s tools allowlist, if present, applies over the union of
built-in and MCP tools.
Connections and idempotency
Section titled “Connections and idempotency”Connections are process state, not run state. Clients reconnect lazily per call with
secrets resolved at connect time, and connections are cached. A dead server yields a
tool-result error string, never a run failure, so a flaky server degrades gracefully. Every
MCP call takes an effect claim keyed on the call id (mcp.<server>.<tool>:<callId>) because
third-party tools cannot be assumed idempotent: a crash mid-call refuses the silent re-run.
The trust note
Section titled “The trust note”Server-provided tool names and descriptions are prompt-injection surface: they reach
the model, so you should read them before binding. Every mcp/ page renders an MCP server
· trust note panel above its outline.
-
List served tools
Click list served tools. This connects to the server on that explicit click only, never on page open, and shows each
mcp.<server>.<tool>with its description. -
Review the gate state
Each tool shows whether it is approval-gated or ungated (from
trust), so you see exactly what a bound agent could do without further approval. -
Then bind
Only after review do you add the server to a definition’s
mcp:list. Review before first bind is the whole point of the panel.
The MCP settings surface
Section titled “The MCP settings surface”/settings/mcp lists every readable mcp/ page plus any SUBSPACE_MCP_SERVERS env entries
that no page shadows, each with a source badge (repo-managed, invalid, disabled).
- New server creates an
mcp/page from a stdio command or an http url. - The per-server checkbox toggles
metadata.mcp.enabled. - Both go through
agents.mcpServerSaveand are admin-only: a stdio entry is a command the host executes, so it shares the trust posture ofos.exec. Changes ride the ordinary audited command path, so GitOps-managed pages reject as read-only and env entries cannot be edited here. - Per-server list served tools reuses the trust-note flow (
agents.mcpTools, connecting only on the click); a disabled server still lists for review-before-enable. - Clicking a page-sourced server name opens its
mcp/page for headers, env, and trust edits.