Skip to main content

Configure an MCP Server

Agent Cores declare MCP servers with YAML files. The host owns transport startup, tool discovery, namespacing, approvals, capability checks, and tool execution.

On a catalog cache miss, the Host first requires mcp.connect:<server_id> and applies the declaration's risk/approval policy. Denied authority stops before client construction, process/network startup, and list_tools(). The later tool invocation separately requires the server call capability and approval. Continue to review a declaration's command, package runner, URL, environment, and headers before enabling it: sanitized secret binding now limits stdio children to an allowlisted environment plus the declaration's approved env entries. Streamable HTTP URLs are checked by the Host before approval/client construction and on every request or redirect; unsafe or unresolvable targets are skipped before a socket is opened.

By default, the loader looks under:

agent/mcp/*.yaml

If agent.yaml sets slots.mcp, that value overrides the default MCP root.

Add a Stdio Server

Create agent/mcp/docs.yaml:

enabled: true
transport: stdio
command: npx
args:
- -y
- "@modelcontextprotocol/server-filesystem"
- /path/to/project
env:
API_TOKEN: "${DOCS_TOKEN}"
tools:
include:
- search*
exclude: []
risk: medium
approval_policy: prompt
capability: mcp.call:docs
connect_timeout_seconds: 30
timeout_seconds: 60
supports_parallel_tool_calls: false

transport: stdio requires command. args, env, and cwd are optional. Relative cwd values are resolved from the runtime workspace.

Environment references such as ${DOCS_TOKEN} are resolved only after connect authority allows the server. If a variable is missing, the Host records a diagnostic and skips that server for the turn. A configured cwd must resolve inside the Host workspace before approval or client construction.

Add a Streamable HTTP Server

Create agent/mcp/remote_docs.yaml:

enabled: true
transport: streamable_http
url: https://example.test/mcp
headers:
Authorization: "Bearer ${REMOTE_DOCS_TOKEN}"
tools:
include: []
exclude: []
risk: medium
approval_policy: prompt
capability: mcp.call:remote_docs
connect_timeout_seconds: 30
timeout_seconds: 60
supports_parallel_tool_calls: false

transport: streamable_http requires an http:// or https:// URL. The Host validates the normalized hostname, literal IPs, and every DNS answer. Private, loopback, link-local, CGNAT, cloud metadata, multicast, reserved, and unspecified targets are blocked by default. Connections use the validated IP while retaining the URL hostname for HTTP Host and TLS SNI, preventing DNS rebinding between validation and connect. URL credentials, paths, queries, and fragments are omitted from approval/audit summaries. Agent Core declarations cannot enable private URLs or ambient HTTP proxy routing.

Grant the MCP Capability

The server manifest's capability names the capability required to call tools from that server. It does not grant the capability by itself.

The Host uses a separate mcp.connect:<server_id> capability for spawn/connect/discovery. The manifest's capability remains the call capability for tools from that server.

Add the capability under the existing capabilities.defaults map in the concrete core manifest:

capabilities:
defaults:
mcp.connect:docs:
scope: core
mcp.call:docs:
scope: core

If capability is omitted, the loader uses mcp.call:<server_id>.

Filter Tools

Use tools.include and tools.exclude to limit the tool catalog:

tools:
include:
- search_docs
- fetch*
exclude:
- fetch_private

Filters match MCP server tool names before the host exposes them. Exposed tool names are host-safe and namespaced, for example docs__search_docs.

Verify

Run:

uv run demiurge init --check
uv run demiurge --provider fake

Inside the TUI:

/tools

list_tools() uses connect_timeout_seconds. Discovery uses one runtime-wide limit of four servers across sessions. A failed server does not block or close a healthy peer; its diagnostic is cached for 30 seconds before only that server is retried. Connect denial is rechecked per server on the next turn. Declaration or authority changes close the older session-bound catalog and require connect reapproval. Removing every declaration closes remaining connections, and starting or resuming another session tracks cleanup of the previous session. Delegated child sessions use their own Host-issued authority and release MCP connections when the child run ends. Evolution review records a secret-safe MCP security diff and prints a content-bound mcp-review:<sha256> token. Promotion requires that exact token; missing or stale tokens leave the live and previous Git refs unchanged.

If a server starts but tool discovery fails, inspect the runtime MCP stderr log:

~/.demiurge/logs/mcp-stderr.log

Boundary

An Agent Core declares MCP servers. The host owns process startup, HTTP transport sessions, environment interpolation, catalog caching, approval prompts, capability enforcement, result conversion, and runtime cleanup. MCP is still not a sandbox: stdio commands and remote URLs remain trusted effects, and stdio processes receive an allowlisted environment plus only declaration-bound values after approval. Streamable HTTP remains subject to the shared fail-closed URL policy and pinned transport on every request, including redirects.