Review pass on the mother MCP infra: - Rename usb_nodes → hive_nodes: a node is any host that joined the hive (live-usb/disk/vps/mother), not just a USB boot. Add a first-class node_type column (live-usb|disk|vps|mother|unknown). The schema migrates an existing osa DB in place (ALTER TABLE + ALTER SEQUENCE, guarded by to_regclass) and ADD COLUMN IF NOT EXISTS for already-renamed tables — data preserved, idempotent. FKs/trigger/indexes follow. - node-register-mcp: accepts + validates node_type, UPSERTs into hive_nodes. Add ON_ERROR_STOP=1 (psql otherwise exits 0 on SQL error → false success) and fold stderr into the captured result so failures are reported. - setup-mother.sh: apply schema BEFORE granting on its tables (fresh installs had no tables when grants ran); pipe the schema via stdin so the postgres user need not read the repo checkout; locate pg_hba via SHOW hba_file (was hardcoded) and PREPEND the peer rule (pg_hba is first-match); grants target hive_nodes/hive_nodes_id_seq. - build-colibri.sh: fast-forward a checked-out branch to origin so it builds current upstream code, not a stale local copy. Validated: prettier + sh -n green. Schema migration/UPSERT to be exercised on osa (no local postgres server here). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
6 KiB
Mother Node MCP Setup
What this is
The mother node (OSA) runs the Colibri MCP host for USB operator node coordination. USB nodes send hardware profiles via SSH → MCP → PostgreSQL. This directory contains the scripts and schema for that infrastructure.
Files
| File | Purpose |
|---|---|
setup-mother.sh |
Idempotent deploy — run once as root, safe to re-run |
mother_schema.sql |
PostgreSQL schema (hive_nodes, build_queue, audit_log + triggers) |
node-register-mcp |
MCP tool: receive hw-probe JSON → UPSERT into hive_nodes |
geodesic-dome-mcp |
MCP tool: geodesic dome wireframe + structural BOM |
build-colibri.sh |
MCP tool: build a colibri crate (branch-allowlisted) |
colibri-mcp-ssh |
SSH forced-command wrapper (allowlisted: "", "tools" only) |
Architecture
USB node Mother (osa)
──────── ────────────
clawdie-hw-probe PostgreSQL (mother_hive)
│ ▲
▼ │
colibri-daemon │ INSERT / UPSERT
│ (external MCP) │
▼ │
ssh colibri@mother (no cmd) │
│ (mother-mcp key) │
▼ │
colibri-mcp-ssh ◄─ authorized_keys command="..."
│ allowlist: "" or "tools"
▼
colibri-mcp ──► node-register-mcp ──► psql -v :'variable' (heredoc)
(parameterized UPSERT, no shell interpolation of SQL)
The USB's colibri-mcp spawns ssh -i ~/.ssh/mother-mcp colibri@mother
with NO remote command. SSH is restricted via command= + restrict to
run only colibri-mcp-ssh, which delegates to colibri-mcp in stdio MCP
mode. The node_register tool on mother receives the hw-probe JSON and
UPSERTs it into PostgreSQL using psql -v :'variable' quoting in a
heredoc — the JSON blob is a bound variable, never interpolated into SQL.
Security properties
- colibri-mcp-ssh: allowlists
SSH_ORIGINAL_COMMANDto""(stdio MCP mode) or"tools"(one-shot discovery). All other values are rejected. This prevents callers from passing arbitrary colibri-mcp flags through the forced-command boundary. - build-colibri.sh: branch is validated against an allowlist (
main, semverv*tags, plusCOLIBRI_BUILD_ALLOW_BRANCHEScolon-separated extras). Features are validated against^[A-Za-z0-9_,-]+$. Cargo args use a shell array — no unquoted string concatenation. - node-register-mcp:
psql -v :'variable'quoting in a heredoc (not-c). The JSON blob is dollar-quoted by psql; shell never interpolates it into SQL. - mother-mcp key: NOT baked into images, NOT reused for Forgejo.
Lives on seed partition (
CLAWDIESEED/colibri/ssh/mother-mcp). One key per trust domain — blast radius is MCP-over-SSH only.
Setup (one-time)
On mother, as root:
# Build colibri from current main first, then:
cd /home/clawdie/ai/colibri
sudo ./packaging/mother/setup-mother.sh
# The script prints the mother-mcp private key — copy it for USB nodes.
What setup-mother.sh does
- Installs colibri binaries from
target/release - Installs MCP server scripts
- jq-merges mother servers into
/usr/local/etc/colibri/external-mcp.json - Creates
colibriOS user + SSH authorized_keys withcommand=wrapper - Generates mother-mcp keypair (prints private key for seed placement)
- Configures PostgreSQL peer auth for colibri on mother_hive
- Runs
mother_schema.sql(idempotent) - Updates colibri daemon env (
COLIBRI_AUTOSPAWN,COLIBRI_MCP_EXTERNAL_CALL) - Restarts
colibri_daemon
Idempotent — running again is a no-op.
Key management
The mother-mcp key is NOT baked into images. It lives:
- On mother:
/var/db/colibri/.ssh/mother-mcp+.pub(auto-generated by setup-mother.sh) - On USB nodes: placed on the seed partition at
CLAWDIESEED/colibri/ssh/mother-mcp(the live-seed importer picks it up at first boot and installs it at~/.ssh/mother-mcp)
One key per trust domain. The mother-mcp key is not reused for Forgejo or other services — its blast radius is limited to MCP over SSH.
USB-side external-mcp.json
The USB node registers mother as an external MCP server. Note: NO remote command — the forced-command wrapper handles entry:
{
"servers": {
"mother": {
"command": "ssh",
"args": [
"-i", "/home/clawdie/.ssh/mother-mcp",
"-o", "StrictHostKeyChecking=accept-new",
"colibri@100.72.229.63"
],
"env": {}
}
}
}
The colibri-daemon spawner pipes JSON-RPC on stdin/stdout. SSH connects
with an empty remote command; the forced-command wrapper starts
colibri-mcp in stdio MCP mode automatically.
Verification
# On mother: check the external MCP tools are live
colibri-mcp tools 2>&1 | grep external
# On mother: test node_register with a sample hw-probe
sudo clawdie-hw-probe 2>/dev/null | \
jq '{jsonrpc:"2.0",method:"tools/call",id:1,
params:{name:"node_register",
arguments:{hostname:"test-node",hw_profile:.}}}' | \
/usr/local/bin/node-register-mcp
# Check PostgreSQL
sudo -u colibri psql -d mother_hive -c \
"SELECT hostname, status, capabilities FROM hive_nodes;"
# From a USB node with the mother-mcp key:
ssh colibri@mother tools | grep node_register
Adding a USB node
- Copy the mother-mcp private key to the USB node's seed partition
(
CLAWDIESEED/colibri/ssh/mother-mcp) - On the USB, install
external-mcp.jsonas shown above - On the USB, install
clawdie-hw-probefrom clawdie-iso - Restart
colibri_daemon— autospawn runs hw-probe and registers the node with mother
See docs/USB-MOTHER-MCP-CONNECTION.md in clawdie-iso for the full
USB-side procedure.