Saphan StudioDocs
MCP server

MCP design principles

Eight principles, each with what it means in practice.

PrincipleIn practice
Projection, not a brainZero 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 exceptionEleven 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 surfacesThe 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 commentTool 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 silenceA 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-dataEvery 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 scopeAn 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 firstNo model call exists anywhere on the serving path.