Task — engineering-spec@1

"Distribution expansion — root CLI .sh commands (install/update/changelog/help) + remote MCP connector transport for agent UIs"

doneTASK-IMP-076
module improvement · class product · priority p0 · created 2026-07-13 · shipped 2026-07-13
depends on none · blocks none

§1 — Description

  1. update.sh, changelog.sh, help.sh MUST exist at the payload root beside the already-shipping install.sh, directly runnable (bash update.sh), mirroring the plugin commands' semantics: update = read-only check by default with --apply to execute (thin wrapper over install.sh, which owns the logic); changelog = installed version + rules_sha + pointers, read from the manifest beside the script; help = the command surface.
  2. build.sh MUST ship the trio in every payload (copy + chmod + npm files array) and declare the two new channels in manifest.yaml: root-cli, mcp-connector.
  3. cyberos-mcp.mjs MUST gain a --http [port] mode: MCP streamable-HTTP style endpoint (POST = one JSON-RPC message or batch → application/json; notifications → 202 empty; non-POST → 405; GET /healthz probe), reusing the existing handle() dispatch verbatim so stdio and http can never drift. stdio stays the default; zero new dependencies.
  4. A docs/deploy/mcp-connector.md runbook MUST capture the agent-UI hookup (Claude: Name + Remote MCP server URL + optional OAuth; Grok: Name + Server URL) and the production checklist: reverse-proxy TLS, supervisor, and the explicit warning that the transport ships unauthenticated - public exposure requires proxy-level auth since the tools execute repo workflows.
  5. Grok's dialog placeholder suggests legacy /sse; whether it accepts streamable HTTP is confirmed at hookup time, not asserted - if legacy SSE is required, that transport is a recorded follow-up (§9).

Length note: sanctioned lean profile - every §5 check ran live in-session (scripts executed, endpoint curl-verified).

§2 — Why

update.sh wraps install.sh instead of duplicating logic (single source of truth for vendoring + --check). The http mode reuses handle() so a tool added once serves both transports. Auth is deliberately NOT hand-rolled into the node process: proxy-level auth at nginx is the checklist item - a bespoke token check in a zero-dep server is worse than the battle-tested proxy layer already fronting the VPS.

§4/§5 — Acceptance + verification (all run live 2026-07-13)

  1. Payload contains executable trio; check-version-sync.sh still green. ✅ (build to /tmp, ls + run)
  2. help.sh prints the surface; changelog.sh prints version + rules_sha from its own manifest; update.sh (no args, offline) emits install.sh --check's three-value report + verdict. ✅ (all executed)
  3. --http: /healthz 200 JSON; POST tools/list returns the 4 workflow tools; notification → 202; GET → 405. ✅ (curl-verified)
  4. stdio unchanged (default branch untouched semantics). ✅ (code path conditional on --http only)
  5. Runbook exists with hookup + security checklist. ✅

§5b — Testing pass (2026-07-13, post gate-1 "approve all")

§9 — Open questions

§10 — Failure modes

FailureDetectionRecovery
endpoint exposed without authrunbook checklist item 3 (explicit warning)proxy auth before DNS
oversized POST1MB cap destroys requestclient retries within cap
batch of notifications only202 empty per transport semanticsn/a - correct
trio run outside a payloadchangelog/update print explicit error + exit 2run from payload/.cyberos
stdio/http driftimpossible by construction - one handle()n/a

End of TASK-IMP-076.

Audit

Findings (resolved in-pass)

  • ISS-001: draft hand-rolled a bearer-token check into the node server - replaced with the proxy-auth checklist (battle-tested layer, zero-dep server stays zero-dep); unauthenticated-by-default now stated loudly in both the runbook and §1 #4.
  • ISS-002: draft asserted Grok accepts streamable HTTP from the /sse placeholder alone - reworded to confirmed-at-hookup with legacy-SSE as the recorded fallback follow-up (§1 #5, §9). Score = 10/10.