S17 — MCP Tool Surface

Phase 0 shipped. This document specifies the MCP tool surface Colibri exposes in Phase 0. The surface is live: src/server.ts and the domain controllers referenced here are shipped (P0.2.1 onward, across R75 Waves A–I). The original 19-tool plan was amended to 14 shipped tools in ADR-004 (R75 Wave H amendment); the amended catalogue is authoritative in §1 below and in docs/reference/mcp-tools-phase-0.md.

1. Shape of the surface

Phase 0 ships 14 tools across 5 domains over one transport (MCP stdio) — ADR-004 R75 Wave H amendment (19 planned → 14 shipped). The full per-tool specification — Zod schemas, request/response shapes, examples — lives in docs/reference/mcp-tools-phase-0.md. S17 is the contract for how the surface behaves; the tools reference is the catalogue.

Domain Count Tools
β Task Pipeline 5 task_create, task_get, task_update (accepts status; routes via state-machine.ts), task_list, task_next_actions
ζ Decision Trail 3 thought_record, thought_record_list, audit_verify_chain
η Proof Store 3 audit_session_start, merkle_finalize, merkle_root
ε Skill Registry 1 skill_list
α System Core + γ Lifecycle 2 server_ping, server_health

Total: 14 shipped tools. audit_session_start is registered by the η loader (registerMerkleTools, src/server.ts L571–L575) but participates in the ζ Decision Trail chain — every thought_record must cite a live session started by audit_session_start per the ordering rule in the writeback protocol.

Not in Phase 0.

  • Agent spawning (agent_spawn, agent_status) is a Phase 1.5+ concern, when δ Model Router and an agent runtime domain land. There is no src/domains/agents/ in the Phase 0 target tree.
  • Per-skill fetch (skill_get) is a Phase 1 refinement. Phase 0 exposes only the list, backed by the SKILL.md parser.
  • A HTTP, WebSocket, or dashboard tool surface. stdio is the only transport in Phase 0.
  • Claude API bridge tools. ν Integrations provides Obsidian bridging and git-facing helpers only in Phase 0; a Claude API bridge belongs to a later phase.

Heritage note: The AMS donor runtime exposed ~480 tools across ~30 controllers (task/roadmap ~60, GSD orchestration ~40, thought/memory ~30, merkle/audit ~20, context ~15, Claude API ~276, admin ~20). That total is donor heritage, not a Colibri target. Colibri earns each tool by citing a Phase 0 acceptance criterion that requires it. Target surface for the full roadmap is 60–80 tools across 10 domains (ADR-004), not 480. See docs/architecture/decisions/ADR-004-tool-count.md.

2. Transport

  • Transport: @modelcontextprotocol/sdk StdioServerTransport. JSON-RPC over stdin/stdout.
  • Language: TypeScript 5.3+, ESM, NodeNext resolution.
  • Entry point: src/server.ts (P0.2.1).
  • No authentication in Phase 0. The process runs under the owner’s user and trusts its stdin. Any auth design belongs to π Governance.
  • No HTTP surface. No dashboard, no REST endpoint, no websocket — not in Phase 0.

3. Tool lifecycle

  1. Client launches the server as a subprocess and connects via stdio.
  2. @modelcontextprotocol/sdk performs the MCP handshake.
  3. Client calls tools/list → the server returns the 14 tool definitions with name, description, and Zod-derived JSON schema.
  4. Client calls a tool → the middleware chain executes → the handler runs inside a better-sqlite3 transaction as needed → the response is returned.
  5. Every call is audited (actions table, ζ) at both enter and exit.

4. Middleware chain (canonical order)

Phase 0 ships the five-stage chain defined by α System Core. No additional middleware runs on the tool hot path in Phase 0.

# Stage Owner file (target) Failure mode
1 Tool lock src/middleware/tool-lock.ts Serializes handlers; a handler cannot run concurrently with another
2 Schema validate src/middleware/validate.ts Rejects the call with a structured Zod error before the handler is reached
3 Audit enter src/middleware/audit.ts Writes an actions row with outcome: "running" and a fresh sequence_no
4 Dispatch src/middleware/dispatch.ts Resolves the tool name → handler; unknown tools short-circuit as errors
5 Audit exit src/middleware/audit.ts Updates the same actions row with the result hash and outcome

Order is part of the contract. A tool registered outside this chain is not a valid tool.

Not on the Phase 0 hot path. ACL, rate limiting, retry budget, timeout, reputation, rule enforcement, metrics, response formatting, and circuit breaking are all out of scope for Phase 0. Each is earned by a later concept (κ, λ, μ, π). If any of them are added ahead of their concept’s phase, it is a scope drift and must be flagged in review.

Heritage note: The AMS donor runtime had an 11-layer middleware chain (tool-lock, acl, audit, auth, auth-permissions, metrics, orchestration, runtime-pid-lock, startup-lock, watcher-leader, index). Each of those layers was a response to an integration problem Colibri does not yet have. Phase 0 deliberately ships the five layers α can justify and no more. Donor algorithms are available in docs/reference/extractions/ when later phases need them.

5. Schema enforcement

  • Every tool has a Zod schema declared next to its handler in src/domains/<domain>/.
  • tools/list returns JSON Schema derived from the Zod schema.
  • The middleware chain stage 2 runs the same Zod schema against the raw request before the handler runs.
  • A tool without a Zod schema cannot be registered. There is no “soft” or “optional” validation path.

6. Response shape

The α middleware emits a uniform success envelope. Failure paths use one of two patterns, depending on whether the handler threw or returned a structured error value. Both patterns are intentional and stable on the Phase 0+ MCP surface; clients MUST handle both.

6.1. Success envelope

{ "ok": true, "data": { /* tool-specific payload */ } }

Every successful handler return is wrapped in this shape by src/server.ts:357-361. The data payload is the unwrapped return value.

6.2. Failure envelopes — two patterns

Pattern A — middleware-emitted (handler threw). The α middleware catches a thrown error at Stage 4 (src/server.ts:362-375) or rejects an invalid input at Stage 2 (src/server.ts:309-336) and emits:

{ "ok": false, "error": { "code": "INVALID_PARAMS|HANDLER_ERROR", "message": "<human>", "details": { /* optional */ } } }

The JSON-RPC structuredContent IS this envelope; isError: true is also set at the transport layer. The two transport-level codes:

  • INVALID_PARAMS — Zod input validation failed. details.issues carries the Zod issue list.
  • HANDLER_ERROR — the handler threw at runtime. message carries the thrown error’s .message; some domains encode a structured prefix (e.g. "ROUND_NOT_FOUND: <round_id>", "INVALID_KEY: <reason>").

Pattern B — handler-returned (no throw). Some handlers return a structured error value as their normal return; the middleware wraps it in the success envelope of §6.1, leaving the domain error inside data:

{ "ok": true, "data": { "ok": false, "error": { "code": "<DOMAIN_CODE>", "message": "...", /* optional fields */ } } }

structuredContent.ok === true but structuredContent.data.ok === false. A client that checks ok at the top level alone WILL miss the error. This pattern is the canonical “domain error vs transport error” distinction and is documented at src/tools/merkle.ts:392-405 (which calls out the parallel pattern in src/domains/tasks/repository.ts).

A defensive client SHOULD inspect both structuredContent.ok and, when it is true, also structuredContent.data?.ok before treating the response as success.

6.3. Pattern attribution by tool family

Tool family Pattern Examples of error codes seen
α System (server_ping, server_health) A INVALID_PARAMS only
ε Skill (skill_list) A INVALID_PARAMS, HANDLER_ERROR
ζ Decision Trail (thought_record, thought_record_list, audit_verify_chain) A INVALID_PARAMS, HANDLER_ERROR (SQLite UNIQUE violation, etc.)
β Task Pipeline (task_create, task_get, task_update, task_list, task_next_actions) B ERR_NOT_FOUND, ERR_WRITEBACK_REQUIRED, ERR_INVALID_TRANSITION, …
η Proof Store (audit_session_start, merkle_finalize, merkle_root) B ERR_SESSION_EXISTS, ERR_SESSION_NOT_FOUND, ERR_ALREADY_FINALIZED, ERR_NO_RECORDS, ERR_NOT_FINALIZED
λ Reputation (reputation_get, reputation_history, reputation_leaderboard, reputation_check_gates) A INVALID_PARAMS, HANDLER_ERROR
θ Consensus (consensus_propose, consensus_vote, consensus_finality, consensus_gossip, vrf_eval) A INVALID_PARAMS, HANDLER_ERROR (ROUND_NOT_FOUND, ALREADY_VOTED, INVALID_KEY encoded in message)
δ Router (router_score, router_call, router_fallback, router_stats) A INVALID_PARAMS, HANDLER_ERROR (FallbackChainExhaustedError, …)

Future phases MAY unify on a single pattern, but that is a separate scope (see docs/architecture/decisions/).

6.4. Stable error codes

The complete catalogue of stable error codes per tool — both Pattern A error.code strings and Pattern B data.error.code values — lives in docs/reference/mcp-tools-phase-0.md. That catalogue is the source of truth for the precise string each tool produces.

7. Relationship to other concepts

  • α System Core — owns the transport, middleware chain, and database file.
  • γ Server Lifecycle — owns boot / ready / shutdown; registers tools with α at startup.
  • β Task Pipeline — owns 5 shipped tools (task_create, task_get, task_update, task_list, task_next_actions).
  • ε Skill Registry — owns skill_list and the SKILL.md parser.
  • ζ Decision Trail — owns 3 shipped tools (thought_record, thought_record_list, audit_verify_chain). The ζ chain is anchored by an audit session started via the η tool audit_session_start.
  • η Proof Store — owns 3 shipped tools (audit_session_start, merkle_finalize, merkle_root). Sessions close implicitly on merkle_finalize; there is no explicit audit_session_end in Phase 0.
  • ν Integrations — registers tools against α but (in Phase 0) exposes none of them in the MCP surface; its bridge work is internal to γ boot and to Obsidian sync via the existing sync-full.bat.

8. Acceptance criteria

S17 acceptance per ADR-004 R75 Wave H amendment (shipped Waves A–I):

  • src/server.ts exposes the 14 tools listed in §1.
  • Every tool has a Zod schema in its owning domain.
  • tools/list returns the 14 tool definitions with derived JSON Schema.
  • Every tool call passes through all five middleware stages in order (P0.2.4 inlined wrapper).
  • Every tool call produces one actions enter row and one actions exit row linked by sequence_no.
  • npm test includes end-to-end coverage across β, ζ, η, ε, and system domains plus Zod-reject tests (1085/1085 passing at main 77e579b8).
  • No tool depends on any AMS_* environment variable or any src/*.js file.

9. Cross-references


Back to top

Colibri — documentation-first MCP runtime. Apache 2.0 + Commons Clause.

This site uses Just the Docs, a documentation theme for Jekyll.