Health — the server_health MCP tool

Phase 0 does not expose an HTTP GET /api/health endpoint. Health is surfaced the same way every other capability is surfaced: as an MCP tool in the 14-tool surface defined by ADR-004. The tool name is server_health and it lives in the α System Core, registered from src/tools/health.ts by bootstrap() at src/server.ts:555.

Why an MCP tool, not an HTTP endpoint. Phase 0 transport is stdio only. There is no HTTP server, no dashboard, no port to bind. The AMS donor’s GET /api/health and npm run dashboard both belonged to a web-UI layer that Phase 0 does not ship; both are cited in the donor reference (../reference/extractions/) but not carried forward. When the Phase 2+ web surface lands, a health HTTP handler may wrap the same underlying probe — but server_health stays the tool-surface entry point.


Tool contract

Name. server_health

Inputs. None. The input schema is z.object({}) (empty object) — the tool accepts zero arguments. Non-object arguments are rejected by stage 2 of the α middleware chain with the standard INVALID_PARAMS envelope. See s17 — Environment and middleware §Stage 2 for the schema registration pattern.

Output shape. A flat 6-field payload, exactly as returned by buildHealthPayload(ctx) in src/tools/health.ts:

{
  "status": "ok",
  "version": "0.1.0",
  "uptime_ms": 1283,
  "db_tables": 12,
  "phase": "phase2",
  "mode": "FULL"
}
Field Type Meaning
status literal "ok" The handler never throws and never returns a non-"ok" status in Phase 0. See “Failure posture” below.
version string Server version; populated from package.json at createServer time.
uptime_ms integer ≥ 0 Wall-clock milliseconds since bootStartMs, floored to an integer. Uses performance.now() so clock adjustments cannot make it negative.
db_tables integer ≥ 0 Count of user tables in the Colibri SQLite DB (excludes sqlite_* internals). Falls back to 0 when ctx.db is undefined or the query throws (closed handle, locked WAL, migration-in-progress).
phase "phase1" | "phase2" "phase1" during transport-only boot; "phase2" once startup.ts Phase 2 has opened the database.
mode "FULL" | "READONLY" | "TEST" | "MINIMAL" The runtime mode fixed at createServer time. Mirrors RUNTIME_MODES in src/modes.ts.

The payload is assembled synchronously; tests assert a response time well under the 100 ms SLA (src/__tests__/tools/health.test.ts describe 3).

Failure posture. The handler never throws. The only branch with a defensive fallback is db_tables, which becomes 0 when ctx.db is undefined (Phase 1 boot) or when the SQLite probe throws. There is no side-effect on the runtime from this tool — mode is a pure read-through of ctx.mode, fixed at createServer time.


server_health has one sibling in the α System Core:

Tool Purpose When to call
server_ping Minimal liveness probe — returns version, mode, uptime_ms Smoke tests, handshake confirmation

These are the only two system-tier tools in the Phase 0 14-tool surface. See ../reference/mcp-tools-phase-0.md for the full 14-tool inventory.


Deferred to Phase 1+

Note. The following are aspirational features targeted for Phase 1+ and are not part of the Phase 0 response: a periodic-check loop, a ring buffer of historical check results, structured sub-objects with heap and RSS readings, a degraded-status reporting surface, and event-loop lag probes. The Phase 0 response is exactly the 6 flat fields listed above; anything richer is scheduled for a later milestone once the monitoring contract is ratified. The R82 manifest (.agents/spawns/r82-phase-0-1-stabilization/manifest.md row H) is the record of this decision.


Logging

All server output goes to stderr. Stdout is reserved exclusively for MCP JSON-RPC frames — see s18 — Stdio Invariant. Overriding process.stdout.write or emitting any non-JSON byte on stdout corrupts the MCP transport and is the kind of bug that was caught the hard way in the AMS donor (documented in ../reference/extractions/).

Log verbosity is controlled by COLIBRI_LOG_LEVEL:

Level Shows
error Errors only
warn Errors + warnings
info Normal operation (default)
debug Verbose; every α-chain dispatch

The donor AMS_LOG_LEVEL variable is not read by Phase 0 code. Any environment variable in the AMS_* namespace is heritage — Phase 0 reads COLIBRI_* only per s17 — Environment.


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.