Guides

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, or hermes as adapters inside agentproto so the daemon can spawn and drive them. That uses agentproto install <slug> and is documented in concepts/adapters.md.


Prerequisites

RequirementDetails
Node.js≥ 20.9.0
@agentproto/clinpm i -g @agentproto/cli
Target CLI installedClaude 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 18790

On 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-bridge command — a stdio MCP server that proxies the daemon /mcp and 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/mcp

After 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 add flags 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.toml key names against your installed @openai/codex version. The mcp-bridge command ships in @agentproto/cli; if agentproto isn't on $PATH, use command = "node" with args = ["/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 ACP session/new.mcpServers injection 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 -20

The 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:

ToolPurpose
agent_startSpawn a new adapter session (claude-code, hermes, opencode, …)
agent_promptSend a turn to a running session
agent_outputRead a session's output
session_listList all sessions (agent + terminal + browser)
agent_sessions_listList active agent sessions only
agent_killStop a session
session_treeSession hierarchy (parent → children)
session_monitorBlock until one of a set of sessions fires a lifecycle event
session_events_pollDrain runtime events
adapter_listList installed adapter CLIs
mcp_discovered_listMCPs discovered from other CLIs on this machine
tunnel_create / tunnel_listManage reverse tunnels
file_read / file_write / file_listWorkspace filesystem
start_browser / stop_browserBrowser session lifecycle
session_usagePer-session cost + token usage, live
list_sandbox_providersList configured sandbox providers (e.g. e2b)
setup_sandbox_providerConfigure a sandbox provider's credentials
agentproto_terminalMCP App: live PTY over WebSocket for a session
agentproto_session_storyMCP App: per-session story/timeline panel
role_listList 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):

  1. Per-spawn — agent_start's deferredTools: true|false.
  2. Per-mount query — append ?deferred=1 (or 0 to force it off) to any /mcp connection URL: http://127.0.0.1:18790/mcp?deferred=1. Composes with ?denyTools= (used for the executor tool gate — see Roles): denyTools always wins for an excluded name, regardless of deferred status. A caller-supplied mount keeps its own query verbatim.
  3. 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 of tools/list is invisible to the harness's native search).
  4. Role default — the built-in executor role defaults it ON (it can't delegate anyway, so the daemon's full surface is mostly dead weight); supervisor has no opinion.
  5. Daemon-wide default — ~/.agentproto/config.json's defaults.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.

HarnessnativeToolSearchVerdict and source
claude-codedeclaredDefers 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.
codexnot declaredShips 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).
opencodenoLoads 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).
gemininoNo 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.
pinoHas 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.
hermesnohermes-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

ItemStatus
claude mcp add exact flag syntaxVerify against your claude-code version — not exercised in this repo
Codex registrationNative agentproto mcp-bridge stdio entrypoint (no mcp-remote); verify ~/.codex/config.toml keys against your version
~/.codex/config.toml key schemaVerify against your @openai/codex version
Hermes standalone MCP config fileUnknown; ACP session/new.mcpServers is the confirmed path
@agentproto/adapter-codex npm releasePublished (npm 2.0.8) — agentproto install codex works
Bearer token for MCP tool callsNot required from localhost; only for mutating /sessions/* from remote origins