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/healthandnpm run dashboardboth 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 — butserver_healthstays 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.
Related system tools (Phase 0)
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.mdrow 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
src/tools/health.ts— the live handler (registered viaregisterHealthTool(ctx)atsrc/server.ts:555)- ADR-004 — Tool Surface — the 14-tool list that includes
server_health - Boot — two-phase startup and when tools register
- Database — how
ctx.dbis opened in Phase 2 - Middleware — the α chain
server_healthflows through like any other tool - s18 — Stdio Invariant, s17 — Environment