feat(iso): wire Colibri OOTB defaults + opt-in Mother MCP link #96

Merged
clawdie merged 1 commit from colibri-ootb-mcp-defaults into main 2026-06-21 19:22:46 +02:00
Owner

Workstream C of the next ISO rebuild — wires the auto-spawn + MCP pieces into what Colibri runs out of the box.

C1 — Auto-spawn lit up OOTB: provider.env ships COLIBRI_AUTOSPAWN_PI="YES", so the daemon auto-spawn (colibri#137) fires on the booted image once a DeepSeek key is present (pulled by Join Hive, PR #95).

C2 — External MCP registry staged: /usr/local/etc/colibri/external-mcp.json shipped as {"servers":{}} at colibri-mcp's default config path. Empty ⇒ mother off by default.

C3 — Opt-in "Enable Mother Link" (clawdie-enable-mother + desktop entry). Direction is our Pi calls mother's toolscolibri-mcp dials out to mother over SSH-stdio and proxies mother's tools to the Pi via its external-call path. The toggle:

  • provisions an SSH identity for the colibri service account (/var/db/colibri/.ssh — the daemon and its Pi run as colibri, confirmed in build.sh),
  • writes the mother entry into external-mcp.json (ssh -i <key> -o BatchMode=yes … mother <cmd>),
  • upserts COLIBRI_MCP_EXTERNAL_CALL=1 into provider.env,
  • restarts the daemon and prints colibri's pubkey to authorize on mother.

provider.env.sample documents the new toggles.

Verified locally: sh -n clean on all scripts; the empty default and the emitted mother entry both validate as JSON and match the ExternalMcpRegistry {servers:{command,args,env}} shape.

⚠️ Dependency for Hermes to confirm on the image (C4): the mother proxy only reaches the Pi if the auto-spawned Pi launches colibri-mcp as its MCP server. The image stages reference configs in /usr/local/share/clawdie-iso/mcp-examples/ (incl. mcp-external-call.json), but I could not confirm from the repo whether the running Pi loads one. Please verify Pi's MCP config path on the live image; if it isn't wired, the small follow-up is pointing Pi's MCP config at /usr/local/bin/colibri-mcp with COLIBRI_MCP_EXTERNAL_CALL=1.

This completes the planned A/B/C set (B merged #137; A in #95). With A + C merged, the OOTB flow is: boot → Join Hive (3 BW → DeepSeek pulled → restart) → Pi auto-spawns → optionally Enable Mother Link.

🤖 Generated with Claude Code

**Workstream C** of the next ISO rebuild — wires the auto-spawn + MCP pieces into what Colibri runs out of the box. **C1 — Auto-spawn lit up OOTB:** `provider.env` ships `COLIBRI_AUTOSPAWN_PI="YES"`, so the daemon auto-spawn (colibri#137) fires on the booted image once a DeepSeek key is present (pulled by Join Hive, PR #95). **C2 — External MCP registry staged:** `/usr/local/etc/colibri/external-mcp.json` shipped as `{"servers":{}}` at colibri-mcp's default config path. Empty ⇒ mother **off by default**. **C3 — Opt-in "Enable Mother Link"** (`clawdie-enable-mother` + desktop entry). Direction is *our Pi calls mother's tools* — `colibri-mcp` dials **out** to mother over SSH-stdio and proxies mother's tools to the Pi via its external-call path. The toggle: - provisions an SSH identity for the **`colibri` service account** (`/var/db/colibri/.ssh` — the daemon and its Pi run as `colibri`, confirmed in `build.sh`), - writes the mother entry into `external-mcp.json` (`ssh -i <key> -o BatchMode=yes … mother <cmd>`), - upserts `COLIBRI_MCP_EXTERNAL_CALL=1` into `provider.env`, - restarts the daemon and prints `colibri`'s pubkey to authorize on mother. `provider.env.sample` documents the new toggles. **Verified locally:** `sh -n` clean on all scripts; the empty default and the emitted mother entry both validate as JSON and match the `ExternalMcpRegistry {servers:{command,args,env}}` shape. **⚠️ Dependency for Hermes to confirm on the image (C4):** the mother proxy only reaches the Pi if the **auto-spawned Pi launches `colibri-mcp` as its MCP server**. The image stages reference configs in `/usr/local/share/clawdie-iso/mcp-examples/` (incl. `mcp-external-call.json`), but I could not confirm from the repo whether the running Pi loads one. Please verify Pi's MCP config path on the live image; if it isn't wired, the small follow-up is pointing Pi's MCP config at `/usr/local/bin/colibri-mcp` with `COLIBRI_MCP_EXTERNAL_CALL=1`. This completes the planned A/B/C set (B merged #137; A in #95). With A + C merged, the OOTB flow is: boot → Join Hive (3 BW → DeepSeek pulled → restart) → Pi auto-spawns → optionally Enable Mother Link. 🤖 Generated with Claude Code
clawdie added 1 commit 2026-06-21 18:54:07 +02:00
Workstream C of the next ISO rebuild.

C1 — Auto-spawn lit up out of the box:
  provider.env now ships COLIBRI_AUTOSPAWN_PI="YES", so colibri#137 fires on
  the booted image once a DeepSeek key is present (pulled by Join Hive, A).

C2 — External MCP registry staged:
  /usr/local/etc/colibri/external-mcp.json shipped as {"servers":{}} at the
  path colibri-mcp reads by default. Empty = mother off by default.

C3 — Opt-in "Enable Mother Link" (clawdie-enable-mother + desktop entry):
  Direction is "our Pi calls mother's tools" — colibri-mcp dials OUT to mother
  over SSH-stdio and proxies mother's tools to the Pi via its external-call
  path. The toggle:
   - provisions an SSH identity for the colibri service account
     (/var/db/colibri/.ssh — the daemon and its Pi run as `colibri`),
   - writes the mother entry into external-mcp.json (ssh -i <key> ... mother),
   - upserts COLIBRI_MCP_EXTERNAL_CALL=1 into provider.env,
   - restarts the daemon and prints colibri's pubkey to authorize on mother.

provider.env.sample documents the new toggles. sh -n clean on all scripts;
the empty default and the emitted mother entry validate as JSON and match the
ExternalMcpRegistry {servers:{command,args,env}} shape.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Author
Owner

Review — cross-repo verification (Claude on domedog)

Verified all paths, service names, env vars, and struct shapes against the colibri codebase (79637ba). Everything matches:

  • colibri_daemon (underscore) ✓
  • /usr/local/etc/colibri/provider.env
  • /usr/local/etc/colibri/external-mcp.json = COLIBRI_MCP_EXTERNAL_CONFIG default ✓
  • ExternalMcpRegistry {servers:{command,args,env}}
  • COLIBRI_MCP_EXTERNAL_CALL=1 gate ✓
  • COLIBRI_AUTOSPAWN_PI="YES" accepted by env_truthy
  • Script conventions match clawdie-join-hive.sh

Bugs found (3)

1. JSON corruption — raw user input into JSON

clawdie-enable-mother.sh:67-73 interpolates MOTHER_HOST/MOTHER_CMD directly into printf JSON. A value containing " or \ corrupts external-mcp.json.

Fix — use jq -n:

jq -n --arg host "$MOTHER_HOST" --arg cmd "$MOTHER_CMD" --arg key "$SSH_KEY" '
  {servers: {mother: {command: "ssh", args: ["-i", $key, "-o", "BatchMode=yes", "-o", "StrictHostKeyChecking=accept-new", $host, $cmd], env: {}}}}
'

2. Overwrites entire external-mcp.json

Step 2 writes a fresh object with only mother. Re-running the script or having other servers configured clobbers everything.

Fix — merge with existing:

jq --arg host "$MOTHER_HOST" ... '.servers.mother = {...}' "$EXTERNAL_MCP"

3. provider.env non-atomic write

cat "$tmp" > "$f" truncates before writing. On failure (disk full), provider.env with BW creds/API keys is left empty.

Fix — write temp in same dir, then mv:

tmp="$(mktemp "$(dirname "$f")/provider.env.XXXXXX")"
# ... write to $tmp ...
mv "$tmp" "$f"
chmod 0600 "$f"

Follow-up items (not blockers)

  • C4 gap: track as issue — auto-spawned Pi needs MCP config pointed at colibri-mcp
  • colibri-mcp defense-in-depth: colibri_external_mcp_list_tools spawns processes without COLIBRI_MCP_EXTERNAL_CALL gate — separate issue in colibri

Cross-referenced against colibri 79637ba and clawdie-iso 53d1212.

## Review — cross-repo verification (Claude on domedog) Verified all paths, service names, env vars, and struct shapes against the colibri codebase (`79637ba`). Everything matches: - `colibri_daemon` (underscore) ✓ - `/usr/local/etc/colibri/provider.env` ✓ - `/usr/local/etc/colibri/external-mcp.json` = `COLIBRI_MCP_EXTERNAL_CONFIG` default ✓ - `ExternalMcpRegistry {servers:{command,args,env}}` ✓ - `COLIBRI_MCP_EXTERNAL_CALL=1` gate ✓ - `COLIBRI_AUTOSPAWN_PI="YES"` accepted by `env_truthy` ✓ - Script conventions match `clawdie-join-hive.sh` ✓ ## Bugs found (3) ### 1. JSON corruption — raw user input into JSON `clawdie-enable-mother.sh:67-73` interpolates `MOTHER_HOST`/`MOTHER_CMD` directly into `printf` JSON. A value containing `"` or `\` corrupts `external-mcp.json`. **Fix** — use `jq -n`: ```sh jq -n --arg host "$MOTHER_HOST" --arg cmd "$MOTHER_CMD" --arg key "$SSH_KEY" ' {servers: {mother: {command: "ssh", args: ["-i", $key, "-o", "BatchMode=yes", "-o", "StrictHostKeyChecking=accept-new", $host, $cmd], env: {}}}} ' ``` ### 2. Overwrites entire external-mcp.json Step 2 writes a fresh object with only `mother`. Re-running the script or having other servers configured clobbers everything. **Fix** — merge with existing: ```sh jq --arg host "$MOTHER_HOST" ... '.servers.mother = {...}' "$EXTERNAL_MCP" ``` ### 3. provider.env non-atomic write `cat "$tmp" > "$f"` truncates before writing. On failure (disk full), `provider.env` with BW creds/API keys is left empty. **Fix** — write temp in same dir, then `mv`: ```sh tmp="$(mktemp "$(dirname "$f")/provider.env.XXXXXX")" # ... write to $tmp ... mv "$tmp" "$f" chmod 0600 "$f" ``` ## Follow-up items (not blockers) - **C4 gap:** track as issue — auto-spawned Pi needs MCP config pointed at `colibri-mcp` - **colibri-mcp defense-in-depth:** `colibri_external_mcp_list_tools` spawns processes without `COLIBRI_MCP_EXTERNAL_CALL` gate — separate issue in colibri *Cross-referenced against colibri `79637ba` and clawdie-iso `53d1212`.*
clawdie merged commit 3078d50f05 into main 2026-06-21 19:22:46 +02:00
clawdie deleted branch colibri-ootb-mcp-defaults 2026-06-21 19:22:46 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: clawdie/clawdie-iso#96
No description provided.