colibri/docs/COLIBRI-EXTERNAL-MCP-PROTOTYPE.md

109 lines
3.2 KiB
Markdown
Raw Normal View History

# 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:
```text
/usr/local/etc/colibri/external-mcp.json
```
Override with:
```sh
COLIBRI_MCP_EXTERNAL_CONFIG=/path/to/external-mcp.json colibri-mcp
# or
colibri-mcp --external-config /path/to/external-mcp.json
```
Schema:
```json
{
"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:
```sh
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 smoke shape
From an MCP client:
```json
{ "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.