Tech docs — the agent door
A console an editing agent can read, and a tree that answers with its own law.
OpenMixer ships an MCP server over stdio. Its tools read a running console through the console’s own REST contract, and read the repository’s governing design — the spec map, the rulings, the traps, the conformance suites, the job ledger — at the moment they are asked. It decides nothing: every answer is data the desk or the tree already holds, named with where it came from.
01
Running it.
It is a workspace package, @openmixer/mcp-server, and it speaks MCP over stdio — an MCP client starts the process and talks to it over the pipe. There is no port, no daemon and nothing to leave running.
# From the top of the workspace.
pnpm -r --filter "@openmixer/mcp-server..." build
# stdio; an MCP client starts it and speaks to it over the pipe.
node packages/mcp-server/dist/main.js
The server walks up from its working directory to the workspace root and reads the laws of that tree, so a second checkout answers with its own design records and nothing is bundled into the package.
| Variable | Meaning | Default |
|---|---|---|
| OPENMIXER_CONSOLE | base URL of the console the console_*/rig_* tools talk to; named in every result | http://127.0.0.1:8080 (core's DEFAULT_WEB_PORT) |
| OPENMIXER_KNOWLEDGE_MCP | Streamable-HTTP URL of the knowledge MCP rulings_search asks first | a site-local address |
02
16 tools, in two halves.
One half is the REST entity door as it stands — the roster, a row, its declared travels, one frame of a metered row. The other half is the tree’s own design material. The table below is generated from the package’s registered tool table, not written by hand, and the package’s own test refuses a description that has drifted from the registry.
The console
| Tool | Arguments | What it answers |
|---|---|---|
| console_discover | filter | The served entity roster from the console's own contract (OPTIONS /api/): every path template it serves, which rows are pump-fed (measured only while watched), and which carry declared travels and defaults. Optional substring filter over paths. |
| console_get | path | GET one row by path (e.g. /channel/input/3/fader). The console's status, Allow header and body come back as they are. |
| console_options | path | OPTIONS one row: what it MAY be — its methods, fields, travels (limit/taper), writability and instances, as the console declares them. |
| console_patchwrites | path, body, confirm | PATCH one row with a JSON delta. A REAL WRITE to a desk, sent exactly once and never retried; the console's answer — status, Allow, and the body with its fault, refusal and reason — is returned verbatim. A fire on a confirm-gated row (a channel-config apply that would move gain/trim/pan) is REFUSED BY THE CONSOLE with 409 CONFIRM_REQUIRED while its preview lists moves and the operator's sign-off is on; the body carries the preview. Re-call with confirm: true — it rides the delta as the row's own confirm argument — to apply anyway. |
| console_health | — | The console's health row: engine, graph and xrun state as it reports them. Reads /health when the contract serves it; answers the console's no-such-resource fault when it does not. |
| console_warnings | — | The console's current warnings. Reads /warnings when the contract serves it; answers the console's no-such-resource fault when it does not. |
| console_meters | strips | One reading of the meter frame, decoded through the windows /meters declares on OPTIONS, projected to the strips asked for (channel keys like "input/1"; all strips when omitted). A pump-fed row measures only while watched, so an unmeasured GET is followed by ONE watch that is closed the moment the first measured frame lands — no stream is held. |
| console_takes | — | The recorder's take library. Reads /takes when the contract serves it; answers the console's no-such-resource fault when it does not. |
| console_history | — | Where the desk sits in its journal: the undo/redo cursor. Reads /history/cursor when the contract serves it; answers the console's no-such-resource fault when it does not. |
The rig
| Tool | Arguments | What it answers |
|---|---|---|
| rig_journal | — | The history ring: the journal newest-first, with the cursor and the ring's bound. Reads /history when the contract serves it; answers the console's no-such-resource fault when it does not. |
| rig_links | — | The patchbay as the console serves it: the external route memory (/patchbay/external, the links the graph showed) and the node view (/patchbay/nodes). Read through REST rows only; a row the contract does not serve is named under "unserved". |
The governing design
| Tool | Arguments | What it answers |
|---|---|---|
| law_governs | paths | The governing spec and the law line for each path, from the design gate’s spec map with the design gate's own matching (a shell glob as a prefix, first row wins). An ungoverned path is reported as such. |
The design corpus
| Tool | Arguments | What it answers |
|---|---|---|
| rulings_search | query, limit | Search the design corpus (the design specs and the working notes, archive excluded). Mode "rag" asks the knowledge MCP on the cluster when it is reachable AND indexes an openmixer source; otherwise mode "local" ranks paragraphs in the tree. Every result names its mode and what searched. |
The traps
| Tool | Arguments | What it answers |
|---|---|---|
| traps_recall | query, limit | The traps that have cost real time, from the "traps" section of the tree’s own working notes, ranked against the query (empty query: all of them). Read at call time; a tree without the file says so. |
Before an edit
| Tool | Arguments | What it answers |
|---|---|---|
| compliance_preflight | paths | Before editing: for each path, the governing spec and law, the traps its words recall, and the conformance/ratchet suites that reach it (with the evidence: an import, a named prefix, or a tree walk). The suites listed are the ones to run after the edit. |
The job ledger
| Tool | Arguments | What it answers |
|---|---|---|
| jobs_proofs | job | The job-level round-trip ledger as data: an internal design record, row by row, with the tier number, whether the job is proven (tier 1) or owed, the test a proven row cites and the shadow probe the deploy gate runs for it. |
03
One tool writes, and it writes once.
Fifteen of the sixteen tools read. The sixteenth, console_patch, sends a real write to a real desk — so it sends exactly one request, never retries it, and hands back the console’s status, its Allow header and its body as they arrived. A refusal is the desk’s ruling and is returned verbatim rather than interpreted, which is the same contract every other client works under: the console decides, and what comes back is what it decided.
The tool holds nothing back on its own account. A write that fires an operation the console’s own confirms sheet gates — a channel-config apply that would move gain, trim or pan is the example — is sent, and the console refuses it with CONFIRM_REQUIRED while the preview lists moves and the operator’s sign-off is on. The refusal comes back with the preview in the body, like any other answer. Calling again with confirm: true — which rides the delta as the row’s own confirm argument — applies it, because the agent has now been shown what it is agreeing to. The gate is the desk’s, so an agent, a browser and an OSC surface are refused identically and answer identically; there is no client-side policy to keep in step.
The metered row is the one place a read is not simply a GET. A pump-fed row measures only while something is watching it, so an unmeasured frame is followed by a single watch that closes the moment the first measured frame lands. No stream is left open.
The tools stand on a fake console with the real console’s shapes, checked across the wire on values rather than on shapes — a −20 dBFS reading has to decode to −20. A live desk is not part of that suite.
04
The process skills the tree carries.
Alongside the server, the repository keeps its working discipline as readable documents, one per subject, checked in beside the code they govern. Each one exists because something went wrong the other way. They are listed here because they describe how this project is built, not because a reader needs to run them.
- design-first
- Resolve the governing design before reading or writing a line. It is three questions — which primitive does this belong to, does it need a new word in the vocabulary, and why is it not an existing thing configured differently — and a search of the specs and the log for the subject before anything is built. The week that produced it lost most of its time re-deriving decisions that were already written down.
- design-ruling
- Record a decision where the automation reads it. When a spec is written or amended, a contract field changes, or a law is superseded, the ruling goes into the design records and the spec map that the pre-edit gate consults — otherwise the next person to touch that file is told the old law.
- false-signals
- The house rule for a signal that does not observe what it claims to. A green suite over an empty function body, a grep that finds nothing because it is broken, a probe that reports silence because it was pointed at the wrong strip: each one has cost a night here. The rule it enforces is to prove a check can detect presence before believing its report of absence.
- round-trip-proof
- A feature is done when the operator’s whole job has been measured end to end, not when its parts pass. It is the skill to read before calling anything finished, and the one that governs any audio measurement that comes back a null, a ratio or a surprise — a gain test needs a real signal well above the noise floor before its delta means anything.
- openmixer-dev-discipline
- The house style, in one place: how a change lands in git, what the TypeScript and C look like, the rules for the surface’s components and its translations, which testing tier a change owes, and how the packaging stays parametrised. Its first principle is operator authority — the console states the cost of a choice and lets the operator make it, rather than vetoing; the narrow exception is anything irreversible that lands on people who are not at the desk.
- lane-discipline
- How parallel work stays separable. Each lane gets its own worktree and branch, commits often with explicit paths, keeps its evidence in the repository rather than in a scratch file, and never merges its own work onto the integration branch. Written after a fan-out lost a night of findings that existed only outside the repository.
- settle-gate
- The procedure that puts an integration branch on the live console. It is deliberately not something a lane can invoke: it builds before it deploys, verifies with a question only the new commit can answer rather than with a health check, and drops real audio if it is wrong.
The repository is not public yet, so these documents live in a tree you cannot clone today. They are named rather than summarised away, because a name is what makes the description checkable the day it opens.