mcp
rigger mcpServes the record over MCP on stdin and stdout: the same packet context prints, plus the tools that write back to it. An assistant with this server connected reads where a project stands and records what it decides as it decides it - instead of the session’s findings living in a transcript nobody reads again.
This command is not meant to be typed. A client starts it, talks JSON-RPC to it, and stops it when the session ends.
Connecting
Section titled “Connecting”$ claude mcp add rigger -- rigger mcpAdded stdio MCP server rigger with command: rigger mcp to local configThe installer runs this for you, along with adding the Stop hook that closes a sitting. It is skipped when the assistant is not on the PATH, and never fails the install - registration that is tidy is worth less than an install that works. RIGGER_NO_REGISTER=1 opts out.
In Git Bash the command needs MSYS_NO_PATHCONV=1 in front of it: otherwise the shell rewrites the bare -- separator into a Windows path and the server ends up registered under the name of a directory. The installer does this already.
doctor says whether the server answers:
$ rigger doctor...mcp: answers - protocol 2025-06-18, 18 tools, 1 promptIt asks the server rather than starting a process and speaking the protocol down a pipe. “Does the server answer” is a question about this code; a subprocess would test the shell, the PATH and the binary on disk instead - three things that can be wrong while the server is fine, and one, a stale binary earlier in the PATH, that would make a broken install look healthy.
The server needs the database, so run rigger init first; without one it exits saying so rather than serving an empty record.
Anything the server writes on stdout is a protocol message, so a diagnostic never goes there. If a client reports the server as broken, its stderr is where the reason is.
| Tool | What it does |
|---|---|
context |
Where the project stands - the packet, as a session’s first read |
pick |
Which project to work on now, when none was named - the answer rigger pick prints, read from git first |
event |
One recorded event whole, by the [id] the packet printed: a wish before building it, a decision the packet cut to its first sentence |
plan |
The stage being built and its open tasks, each with an id |
record_decision |
A decision and the reason behind it |
record_finding |
Something learnt about the code or the domain |
record_pitfall |
A trap worth remembering |
record_change |
Something that changed in the product |
record_state |
One line for the top of the hub’s state block, when the state shifted |
set_next_step |
The one line the next session starts from; the newest wins |
ask_owner |
A question only the owner can settle; it waits in the packet, with a due day when the answer is needed by one |
record_shipped |
A release as the release engine made it: tag, release, registries |
wish |
Something to sort into the plan later |
resolve |
Answers a question or sorts a wish, so it leaves the packet |
close_task |
Marks a task of the current stage done |
doc_show |
Reads a handwritten text - the vision, the rituals, a research note; lists them without a slug |
doc_write |
Writes one into the record: a research note made on request, or a correction to the vision |
set_task_status |
Gives a task a status: new, active, waiting-handoff, frozen or done |
snooze_task |
Puts a task to sleep until a day (until: 2026-10-05, monday, 3d, 2w), or wakes it when until is left out |
task_find |
Finds the card a line of text means, and says whether to take it, ask, or make a new one |
task_context |
Where a card stands: what it is, where it is worked, everything written against it |
record_plan |
A step of the plan of edits, against a card |
principles |
The principles the record stands on, with how often each is invoked |
why_principle |
Every decision across the line that stands on one principle |
link |
Ties two projects together: a pair, a consumer or a donor |
links |
What a project is tied to, and what its neighbours have asked it for |
doc_write replaces the whole body of a document, so read it with doc_show first and send back the whole of it. What it is not told, it keeps: a rewrite without kind or title leaves both as they were, so a correction to the vision cannot silently retitle it or turn it into a research note. An empty body is refused - a document is removed with rigger doc remove, not by emptying it.
This is what lets an assistant write a research note or fix a vision into the record rather than into a file somebody has to remember to import. See doc.
record_decision also takes a principle: the name of the thing this line already believes that the decision is one more instance of. Read principles before naming one, so that a decision joins a thread rather than starting a synonym of it; why_principle reads the whole thread back, across every project. See note and why.
wish takes a from, naming the project that is asking, when one product needs something of another. The order then shows on the neighbour’s packet and in the owner’s inbox as theirs - it is still an ordinary wish, sorted by the same resolve.
ask_owner takes a due - a date, tomorrow, +3d, friday - when the answer is needed by a day; past it, the question is shown as overdue in the inbox, the Monday brief and the packet. See note.
record_shipped is what a release engine calls when it has made a release: the tag, whether a release with its archives went out, and the registries it reached. The version closes on it, and sync’s own look at GitHub does not overwrite it. See note --kind shipped.
link states a tie between two products, anchoring a version on a side by writing it kasl@v1.13.0. Only pairs are checked for drift, and the drift is raised on the owner’s own screens without anyone asking. See link.
The recording tools - record_decision, record_finding, record_pitfall, record_change, record_plan and set_next_step - take a task instead of a project: the event is then written against that card, under the desk the cards live in.
Every tool takes a project - the name rigger project list shows. The recording tools take a text; an empty one is refused, because a record with nothing in it helps nobody.
plan prints the ids close_task takes, which is why it exists beside context:
sample · v0.3.0 · Search- [4] full-text index- [5] a query languageA task id belongs to its project: an id from another project’s plan is refused rather than closing someone else’s line.
The packet as a prompt and a resource
Section titled “The packet as a prompt and a resource”The same packet is served two more ways, so a session can start without the assistant remembering to call a tool:
- Prompt
start session, taking aproject. In Claude Code it appears under/mcp. - Resource
rigger://<project>/context, one per recorded project, so a client can browse the record rather than having to know a name to ask for it.
The prompt wraps the packet in the instruction that tells an assistant what it is holding - the state of the work to pick up from, not a document to summarise.
Errors
Section titled “Errors”A tool that runs and fails answers with its reason and isError, so the model reads what went wrong and can act on it:
no project named 'ghost'; the projects are listed by `rigger project list`Only a malformed request is a JSON-RPC error - an unknown method, a call without a name. Either way the server keeps going: one bad request does not end a session, and a line that is not JSON at all is reported on stderr and skipped.