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.
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 registrycolibri_external_mcp_list_tools— spawn configured servers and calltools/listcolibri_external_mcp_call_tool— call an external server tool; gated byCOLIBRI_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 viajexec.{ "path": "/var/jails/mcp" }— ephemeraljail -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.