colibri/docs/COLIBRI-EXTERNAL-MCP-PROTOTYPE.md
Sam & Claude 9891d06144 feat(rc): rename test agent and load provider env (Sam & Codex)
Rename the local deterministic launch helper from colibri-smoke-agent to colibri-test-agent, update CLI/TUI/tests/docs, and teach the FreeBSD rc.d service to source /usr/local/etc/colibri/provider.env plus set a service PATH for local spawns.\n\nChecks: cargo fmt --check; ./scripts/check-format.sh; git diff --check; cargo check -p colibri-daemon -p colibri-client -p colibri-glasspane-tui; cargo check -p colibri-client --bins; cargo test -p colibri-client --test live_socket_check -- --nocapture.
2026-06-15 07:35:44 +02:00

3.2 KiB

Colibri external MCP host prototype

Status: prototype. colibri-mcp is still primarily an MCP server that exposes Colibri to editors/assistants. This prototype also lets that server act as a small MCP client/host for other stdio MCP servers.

What it does now

colibri-mcp always exposes three prototype tools:

  • colibri_external_mcp_servers — read the configured external server registry
  • colibri_external_mcp_list_tools — spawn configured servers and call tools/list
  • colibri_external_mcp_call_tool — call an external server tool; gated by COLIBRI_MCP_EXTERNAL_CALL=1

The default is read-only/discovery: listing configured servers and their tools is allowed, but calling external tools requires an explicit trusted profile.

Registry file

By default, colibri-mcp looks for:

/usr/local/etc/colibri/external-mcp.json

Override with:

COLIBRI_MCP_EXTERNAL_CONFIG=/path/to/external-mcp.json colibri-mcp
# or
colibri-mcp --external-config /path/to/external-mcp.json

Schema:

{
  "servers": {
    "demo": {
      "command": "/usr/local/bin/demo-mcp-server",
      "args": ["--stdio"],
      "env": {
        "DEMO_MODE": "1"
      },
      "jail": { "name": "mcp0", "root_path": "/usr/local/bastille/jails/mcp0/root" }
    }
  }
}

The optional jail field confines the server in a FreeBSD jail (see below).

Confinement (jail)

External MCP servers are arbitrary third-party binaries — at least as untrusted as the agents Colibri already jails — so the host reuses the agent spawner's confinement primitive rather than growing a parallel one: colibri_daemon::spawner::{jail_wrap, JailConfig, PrivMode}.

Per-server jail accepts the same shape as the agent spawner (docs/COLIBRI-JAILED-AGENT-SPAWN-DESIGN.md):

  • { "name": "<jail>" } — enter an existing persistent jail via jexec.
  • { "path": "/var/jails/mcp" } — ephemeral jail -c command=… for the call.
  • optional ip4, user.

The root-only jail step uses the shared COLIBRI_JAIL_PRIV_MODE policy (mdo on the live USB, helper on deployed hosts). Omit jail to run the server on the host, as before. stdio still flows through jexec/jail/mdo, so the stdin/stdout JSON-RPC transport is unaffected.

Trusted call mode

External tool calls are disabled unless explicitly enabled:

COLIBRI_MCP_EXTERNAL_CALL=1 colibri-mcp
# or
colibri-mcp --external-call

This is intentionally separate from COLIBRI_MCP_WRITE=1. A Colibri write tool and an external MCP tool are different trust surfaces.

Quick check shape

From an MCP client:

{ "name": "colibri_external_mcp_servers", "arguments": {} }
{ "name": "colibri_external_mcp_list_tools", "arguments": { "server": "demo" } }
{ "name": "colibri_external_mcp_call_tool", "arguments": { "server": "demo", "name": "tool_name", "arguments": {} } }

Limits

This prototype is intentionally simple:

  • stdio transport only
  • one external process per request
  • no long-lived connection pool
  • no server/tool allowlist beyond the registry file
  • no streaming tool results
  • no production-grade secret manager integration

That is enough for experimental ISO/operator work. A production host should add policy, lifecycle management, audit logs, and per-tool permission controls.