Skip to content

ams(mcp): AMS management tool family — governor-gated mutations, doctor split, hosted tenant tools #9523

Description

@JSONbored

Context

Part of #9515 — the AMS half of "MCP as the management plane." The miner MCP (packages/loopover-miner/bin/loopover-miner-mcp.ts) exposes 11 read-only tools, while the entire mutating ops surface is CLI-only: governor pause/resume (lib/governor-pause-cli.ts), queue ops (lib/portfolio-queue-cli.ts: next|claim-batch|done|release|requeue), claim ops (lib/claim-ledger-cli.ts), run-state set (lib/run-state-cli.ts), deny-hooks approve/reject (lib/deny-hooks-cli.ts), calibration apply/revert (lib/calibration-cli.ts, double-gated), right-to-be-forgotten purge (lib/purge-cli.ts), store migrations (lib/migrate-cli.ts). The safe-dispatch chokepoint already exists: lib/chat-action-registry.ts + chat-action-dispatch.ts structurally refuse any handler that isn't governorGatedHandler-wrapped (built for the dashboard chat, #6521/#6838/#6839), and the miner dashboard already dispatches governor pause/resume + queue release/requeue through it (apps/loopover-miner-ui vite-governor-api.ts:56-58, vite-portfolio-queue-actions-api.ts:92-94).

Hosted AMS bones also exist: control-plane/ tenant CRUD + cron wake (ams-wake.ts), loopover-miner-hosted entry with /health+/ready (lib/ams-health-server.ts), tenant CLI (lib/tenant-cli.ts) — and #9199 wants tenant-scoped, chat-groundable health tools.

The 11 existing tools gain contract registration + output schemas in #9518 (not here). This issue adds the mutating and hosted tool families.

Tool catalog (the deliverable — renames/cuts recorded on this issue first)

Local ops, read (availability selfhost, locality miner): loopover_miner_doctor (dedicated tool — today doctor rides inside loopover_miner_status; split so status stays cheap and doctor can grow checks) · loopover_miner_get_metrics_snapshot (the Prometheus families already exported by the metrics CLI, as structured JSON).

Local ops, mutating (availability selfhost, all dispatched through the governor-gated chokepoint — a raw handler that bypasses chat-action-registry is defective by definition, mirroring test/unit/no-direct-octokit.test.ts's structural rule):
loopover_miner_governor_pause / loopover_miner_governor_resume (mirror the dashboard actions; fire the same ams-notifications side-channel) · loopover_miner_queue_release / loopover_miner_queue_requeue (per-item, mirroring the dashboard's two queue actions) · loopover_miner_claim_release · loopover_miner_deny_hooks_decide (approve|reject on a pending synthesized hook) · loopover_miner_run_migrations (existing-stores-only, dry-run default like the CLI) · loopover_miner_purge_repo (destructive: right-to-be-forgotten; requires confirm: z.literal(true) + elicitation; returns the same per-store purge report as the CLI).

Deliberately excluded from MCP (recorded as decision): calibration apply-min-rank/revert-min-rank (stays CLI-only behind its existing double gate — an agent-reachable path to loosen calibration floors is not wanted), state set (raw run-state mutation is a repair tool, not an operation), kill-switch trip/untrip (one-way breaker semantics stay out of agent reach; pause/resume is the agent-safe control).

Hosted tenants (availability cloud, auth control-plane admin; served by the hosted/remote side, not the local bin): loopover_ams_tenant_create / loopover_ams_tenant_list / loopover_ams_tenant_destroy (destructive, confirm + elicitation) — wrapping lib/tenant-client.ts's control-plane calls · loopover_ams_tenant_health (#9199: per-tenant health/status — wake schedule, last cycle outcomes, container health) · loopover_ams_tenant_wake (trigger an immediate cycle for one tenant via the ams-wake machinery, bounded by the same per-tenant schedule guards).

Requirements

  1. Every tool: @loopover/contract entry (real input/output schemas, auth/locality/availability/destructiveHint), registered per contract(remote): migrate the remote MCP server's tools to @loopover/contract — typed handlers, real output schemas #9518, smoke-called in validate:mcp (mcp: validate:mcp contract validator — Ajv output enforcement, per-tool smoke gate, version tri-lock across all three servers #9520) with fakes for stores/control-plane.
  2. Structural governor gating: the miner MCP's mutating tools register through chat-action-registry (or a shared registry both chat and MCP consume — preferred; record the shape in the PR), so the compile-time/structural "only governor-gated handlers" rule covers MCP identically. Add the structural test.
  3. Mutating tools write the event ledger exactly as their CLI twins do (same event types), so loopover_miner_get_audit_feed shows MCP-initiated actions indistinguishably from CLI ones, with an actor/source field distinguishing origin.
  4. Tenant isolation for hosted tools (per Epic: hosted AMS chat platform — sign up, connect GitHub, converse with your miner #9184's constraints): every hosted tool resolves tenant scope server-side from the authenticated identity; no cross-tenant reads/writes; deny-path tests for wrong-tenant access on every tool.
  5. Privacy boundary unchanged: no wallet/hotkey/reward/trust-score data in any tool response (existing FORBIDDEN_CONTENT matchers extended to the new tools in the miner contract parity suite).
  6. The dashboard's governor/queue endpoints and the new MCP tools call the same underlying action functions — one implementation, asserted by test.
  7. Docs regenerate via contract: generate every derived surface — typed stdio client, CLI from one spec table, tool-reference docs, miner dedup, UI z.infer types #9521's generators (tool tables pick the new tools up automatically — no hand-edits).
  8. Full branch-counted coverage; fix-what-you-find applies (the docker-compose.miner.yml/k8s runloop defect is already being fixed separately — do not duplicate it here).

Non-goals

Deliverables

  • Local mutating family live behind the structural governor gate, ledger-audited, elicitation+confirm on purge_repo
  • doctor split + metrics snapshot tool
  • Hosted tenant family incl. miner-ui(hosted): per-tenant miner health/status strip and chat-groundable health tools #9199's health tool and wake, tenant-isolated with deny-path tests
  • Exclusion decisions above recorded (calibration/state-set/kill-switch stay CLI-only)
  • Generated docs picked up the catalog with zero hand-edits

Expected outcome

A dual-role operator (or the #9184 hosted chat) can pause/resume the governor, groom the portfolio queue, decide deny-hooks, run store migrations, execute a confirmed right-to-be-forgotten purge, and administer hosted tenants — all over MCP, all schema-validated, all governor-gated and ledger-audited, with the dangerous calibration/kill-switch levers deliberately unreachable by agents.

References

Part of #9515. Blocked by #9518. Advances #9184 (action catalog) and #5230 (AMS cloud convergence); implements #9199's health-tool half. Relates to #5221/#5226 (fleet rollout/health design).

Metadata

Metadata

Assignees

Labels

maintainer-onlyOwner-only work — yields no Gittensor points.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions