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.
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.
---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 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 (mcp.<server>.<tool>:<runId>:<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.
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. Stdio servers must also pin the reviewed tool names and schemas inmetadata.mcp.toolsbefore an agent can bind them. Run startup reads that declaration and never launches a stdio process merely to discover its capabilities. - Clicking a page-sourced server name opens its
mcp/page for headers, env, and trust edits.