MCP server
MCP design principles
Eight principles, each with what it means in practice.
| Principle | In practice |
|---|---|
| Projection, not a brain | Zero own read paths — every request calls the same composition seams the CLI verbs use, and renders with the same renderers. Zero cache beyond the read; state is fresh from the record on every request. reload (SIGHUP) swaps configuration only, never state. |
| Read-only without exception | Eleven read tools. Mutating tools do not exist, not even as stubs. Unknown methods and unknown tools are refused with messages that name the full tool set. |
| One contract, both surfaces | The tool registry is data in the service layer, consumed by every transport from one function — the tool list cannot fork. Payload parity between MCP and CLI is a conformance test on the real binary (deep-equal across the eight record-projection tools). The three aggregates have no CLI verb to be equal to — they are rollups over the same store, served through the same registry, and the parity scenario covers the eight tools that project a CLI verb's payload. |
| The descriptor is a commitment, not a comment | Tool descriptions enumerate response content exhaustively, and a test fails when descriptor and behaviour drift. This principle was bought with a measured defect: a summary mode that promised five fields and shipped twenty-three. |
| Refusal, not silence | A response over the byte cap is an error naming the exact narrowing to apply — never a silent truncation for a downstream layer to mangle without a marker. A limit above the maximum is rejected, never clamped. A bind address with an implicit host is refused at every configuration tier alike. |
| Denial-as-data | Every access denial is ledgered as a zero-cost refusal row with tool, cause, correlator, tenant and actor claim. The wire carries an opaque reference; the cause lives only in the record. |
| Fail-closed scope | An absent scope denies every class-gated tool. The one intentional unrestricted grant (the local stdio operator) goes through a single named constructor, never a silent default. |
| Deterministic first | No model call exists anywhere on the serving path. |