Use agentproto as an MCP server inside coding CLIs
This guide covers one direction: registering the agentproto daemon as an MCP server inside an external coding CLI (Claude Code, Codex, Hermes) so the CLI's agent can call agentproto tools — spawn sessions, prompt them, poll events, and orchestrate multi-agent swarms — from within its own tool loop.
The other direction (host → agentproto) is different: installing
claude-code,codex, orhermesas adapters inside agentproto so the daemon can spawn and drive them. That usesagentproto install <slug>and is documented in concepts/adapters.md.
Prerequisites
| Requirement | Details |
|---|---|
| Node.js | ≥ 20.9.0 |
@agentproto/cli | npm i -g @agentproto/cli |
| Target CLI installed | Claude Code, Codex, or Hermes — see each section |
Step 1 — Start the daemon
The daemon exposes an HTTP MCP endpoint at http://127.0.0.1:18790/mcp (MCP
Streamable HTTP transport, stateless per-request).
agentproto serve
# or pin a workspace:
agentproto serve --workspace ~/code/my-project --port 18790On boot the daemon writes <workspace>/.agentproto/runtime.json (mode 0600)
with the live port and a per-boot bearer token. You do not need to pass a
token for MCP tool calls from localhost — the origin allowlist covers
127.0.0.1:* and localhost:* by default. The bearer token is only required
for mutating HTTP routes (POST /sessions/*, DELETE /sessions/*, WS PTY
upgrade) called from a non-localhost origin.
To run the daemon as a background OS service instead, see
agentproto daemon.
Smoke-test the endpoint
curl -s http://127.0.0.1:18790/health | python3 -m json.tool
# → { "status": "ok", "workspace": "...", "registered": [...], "uptimeMs": ... }Step 2 — Register in the coding CLI
agentproto speaks two MCP transports:
- HTTP (
http://127.0.0.1:18790/mcp) — use directly from clients that support MCP Streamable HTTP (Claude Code). - stdio via the bundled
agentproto mcp-bridgecommand — a stdio MCP server that proxies the daemon/mcpand forwards the real tool schemas. Use it for stdio-only clients (Codex, Cursor, Claude Desktop, standalone Hermes); no third-party bridge needed.
# stdio entrypoint — same daemon, any stdio MCP client:
agentproto mcp-bridge
# honours AGENTPROTO_MCP_URL (default http://127.0.0.1:18790/mcp);
# set it if daemon.port differs from 18790.Claude Code
Claude Code supports the MCP Streamable HTTP transport natively.
Option A — project .mcp.json (checked into the repo, applies to all
contributors):
{
"mcpServers": {
"agentproto": {
"type": "http",
"url": "http://127.0.0.1:18790/mcp"
}
}
}Place this file at the project root. Claude Code picks it up automatically when launched from that directory.
Option B — claude mcp add (global or project scope):
# Project scope (writes to .mcp.json):
claude mcp add --transport http agentproto http://127.0.0.1:18790/mcp
# User scope (writes to ~/.claude.json); flag name may be --scope user:
claude mcp add --transport http --scope user agentproto http://127.0.0.1:18790/mcpAfter registration, restart the Claude Code session. The agentproto server
will appear in the MCP panel and its tools are immediately available to the
agent.
Note: The
claude mcp addflags above match the published Claude Code reference but are not exercised in the agentproto repo — in particular--scope user(not--scope global) is the likely flag for user-level registration; verify against your installed version.
Codex (@openai/codex CLI)
OpenAI's Codex CLI registers stdio MCP servers via ~/.codex/config.toml.
Codex's MCP client speaks stdio, so point it at agentproto's bundled
mcp-bridge — no third-party proxy needed:
# ~/.codex/config.toml
[mcp_servers.agentproto]
command = "agentproto"
args = ["mcp-bridge"]
# non-default daemon port? pass it through:
# env = { AGENTPROTO_MCP_URL = "http://127.0.0.1:18791/mcp" }agentproto mcp-bridge is a stdio MCP server that relays to the daemon /mcp
and forwards each tool's real input schema — so Codex's agent sees the actual
tool parameters, not an opaque blob.
⚠ Verify the
~/.codex/config.tomlkey names against your installed@openai/codexversion. Themcp-bridgecommand ships in@agentproto/cli; ifagentprotoisn't on$PATH, usecommand = "node"withargs = ["/path/to/@agentproto/cli/dist/cli.mjs", "mcp-bridge"].
Hermes (hermes CLI)
Hermes ships its own ACP server (hermes acp) and accepts MCP servers
injected at session spawn time via the ACP session/new.mcpServers parameter.
There is no standalone static config file for Hermes to pre-register MCP
servers before a session starts.
When launched via agentproto (recommended): agentproto automatically
injects its orchestrator MCP gateway into every Hermes session it spawns — no
manual config needed. See agentproto sessions start hermes.
When launched standalone via the ACP client: include the MCP server in the
session/new call:
{
"cwd": "/path/to/workspace",
"mcpServers": [
{
"name": "agentproto",
"type": "http",
"url": "http://127.0.0.1:18790/mcp"
}
]
}Hermes propagates the mcpServers list to its internal tool registry for the
duration of the session.
⚠ Unverified: whether a standalone Hermes CLI config file (e.g.
~/.hermes/config.yaml) pre-registers MCP servers before session start was not confirmed from the agentproto repo. The ACPsession/new.mcpServersinjection is the verified mechanism.
Step 3 — Verify
Once the daemon is running and the CLI is registered, confirm tools are visible.
From Claude Code — type /mcp in the chat input; agentproto should appear
in the server list. Or prompt the agent: List the MCP tools available from agentproto.
Direct MCP tool call (from any client) — list all sessions:
Tool: session_list
Input: {}Expected response: an array (possibly empty) of sessions. Use
agent_sessions_list to filter to agent-only sessions.
Raw curl smoke test:
curl -s -X POST http://127.0.0.1:18790/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' \
| grep -o '"name":"[a-z_]*"' | head -20The endpoint uses the MCP Streamable HTTP transport — both
application/json and text/event-stream must be present in Accept, or
it responds 406 Not Acceptable. It also streams as SSE (event: message
framing), which is why this pipes through grep rather than
python3 -m json.tool.
Expected: tool names including agent_start, session_list,
agent_prompt, and others.
What agentproto exposes over MCP
The full daemon tool surface is available at /mcp. Key tools for
coding-CLI orchestration:
| Tool | Purpose |
|---|---|
agent_start | Spawn a new adapter session (claude-code, hermes, opencode, …) |
agent_prompt | Send a turn to a running session |
agent_output | Read a session's output |
session_list | List all sessions (agent + terminal + browser) |
agent_sessions_list | List active agent sessions only |
agent_kill | Stop a session |
session_tree | Session hierarchy (parent → children) |
session_monitor | Block until one of a set of sessions fires a lifecycle event |
session_events_poll | Drain runtime events |
adapter_list | List installed adapter CLIs |
mcp_discovered_list | MCPs discovered from other CLIs on this machine |
tunnel_create / tunnel_list | Manage reverse tunnels |
file_read / file_write / file_list | Workspace filesystem |
start_browser / stop_browser | Browser session lifecycle |
session_usage | Per-session cost + token usage, live |
list_sandbox_providers | List configured sandbox providers (e.g. e2b) |
setup_sandbox_provider | Configure a sandbox provider's credentials |
agentproto_terminal | MCP App: live PTY over WebSocket for a session |
agentproto_session_story | MCP App: per-session story/timeline panel |
role_list | List role profiles and their spawn/delegation policy |
For the live tool catalog, call tools/list via curl (see verify step above)
or check GET /health → registered[].
Deferred/lazy tool loading (shrink the turn-0 payload)
The full surface above is ~190 tools with full JSON schemas — real tokens
paid on every session's very first turn, whether or not it ever touches
most of them. Deferred mode hides everything except a small always-on set
(the core spawn/drive/observe/report loop, plus the tool_search meta-tool
itself) from tools/list; every tool stays fully callable via tools/call
regardless — tool_search just returns a hidden tool's full schema by
keyword (or select:name1,name2) so the model can look it up on demand
instead of loading all ~190 upfront. Measured on a real daemon boot: 191
tools / ~238 KB / ~60K tokens (chars/4) eager vs. 18 tools / ~58 KB / ~14K
tokens deferred — a ~76% smaller tools/list payload.
Four knobs decide it, checked in this order (first one that has an opinion wins):
- Per-spawn —
agent_start'sdeferredTools: true|false. - Per-mount query — append
?deferred=1(or0to force it off) to any/mcpconnection URL:http://127.0.0.1:18790/mcp?deferred=1. Composes with?denyTools=(used for the executor tool gate — see Roles):denyToolsalways wins for an excluded name, regardless of deferred status. A caller-supplied mount keeps its own query verbatim. - Harness with native tool search — when the adapter's manifest
declares
capabilities.nativeToolSearch(see the verdict table below), the daemon's default self-mount is eager (?deferred=0): the harness already defers MCP tools behind its own search, and a second layer would hide tools from that search (a tool the daemon keeps out oftools/listis invisible to the harness's native search). - Role default — the built-in
executorrole defaults it ON (it can't delegate anyway, so the daemon's full surface is mostly dead weight);supervisorhas no opinion. - Daemon-wide default —
~/.agentproto/config.json'sdefaults.mcp.deferredTools(false|true|{ "alwaysOn": [...] }). Read once at boot; off by default.
Only the loading strategy changes — no tool is removed. To check what a
session actually received, read session_capabilities (mcpServers[].status,
toolCount, tools); an mcp:degraded event on session_events_poll flags a
session whose mount was never listed or listed nothing. Imported MCP servers
stay reachable exactly as before (mounted natively via bundles, or through
mcp_imported_* on the daemon's /mcp).
Native tool search per harness
Verdicts were established against the versions installed on the dev host (2026-10-02). Only a verified, default-on native deferral is declared in the manifest; everything else keeps the role/daemon default.
| Harness | nativeToolSearch | Verdict and source |
|---|---|---|
| claude-code | declared | Defers MCP tool schemas behind its ToolSearch tool (Claude Code docs, "MCP Tool Search", code.claude.com/docs/en/mcp; modes standard/tst/tst-auto read from the pinned 2.1.280 binary, see the lean mode comment in adapters/claude-code/src/index.ts). Default is threshold-based (ENABLE_TOOL_SEARCH=auto); the adapter's tool_search option (true/false/auto) overrides it. Caveat: Claude Code turns it off against a non-first-party ANTHROPIC_BASE_URL unless ENABLE_TOOL_SEARCH is set, so such routes get the eager daemon surface. |
| codex | not declared | Ships a BM25 tool_search tool (core/src/tools/handlers/tool_search.rs, mcp_tool_exposure.rs in codex-cli 0.153.4, strings scan of the binary) with a per-model supports_search_tool flag and a direct/deferred exposure split, but which MCP tools it defers (and under what threshold) is not verified, and it is model-gated. Revisit once confirmed. Not auto-mounted anyway (daemonMount: true needed). |
| opencode | no | Loads every MCP tool into the tool list; the tool_search_tool_* strings in opencode 1.18.33 belong to the bundled @ai-sdk/anthropic provider types, not an opencode feature (strings scan). |
| gemini | no | No tool-search/deferral code in the @google/gemini-cli 0.46.0 bundle (0 matches for tool_search/ToolSearch/defer_loading); MCP tools are filtered only via includeTools/excludeTools. |
| pi | no | Has no MCP client at all: "No MCP" (@earendil-works/pi-coding-agent 0.80.3 README, "No MCP" section); the daemon's tools reach it through its own mcp-bridge extension. |
| hermes | no | hermes-agent 2026.9.14 registers MCP tools eagerly into its tool registry (tools/mcp_tool_registration.py); no tool-search or deferral code in agent/, hermes_cli/, tools/. It has zero built-in tools, so the daemon mount is its toolset. |
{
"defaults": {
"mcp": {
"deferredTools": true
}
}
}Scoped gateway (restrict tool access)
To give the coding CLI a narrower tool surface — session management only, no filesystem or browser tools — use the orchestrator gateway endpoint:
http://127.0.0.1:18790/mcp/orchestrator?scope=<token>The orchestrator gateway exposes only session-management and policy tools.
The scoped <token> is minted per-child session; it appears in the
agent_start response.
Gaps and known issues
| Item | Status |
|---|---|
claude mcp add exact flag syntax | Verify against your claude-code version — not exercised in this repo |
| Codex registration | Native agentproto mcp-bridge stdio entrypoint (no mcp-remote); verify ~/.codex/config.toml keys against your version |
~/.codex/config.toml key schema | Verify against your @openai/codex version |
| Hermes standalone MCP config file | Unknown; ACP session/new.mcpServers is the confirmed path |
@agentproto/adapter-codex npm release | Published (npm 2.0.8) — agentproto install codex works |
| Bearer token for MCP tool calls | Not required from localhost; only for mutating /sessions/* from remote origins |