MCP tools reference
49 tools, registered in mcp/server.py (31 inline) and five satellite
modules (agents_tools.py, beurteilung_tools.py, hall_of_fame_tools.py,
lehren_tools.py, statistik_tools.py). Every tool calls exactly one Core
REST route — no tool has its own business logic or its own invariants; a
409/422 from the Core comes back to the calling model as a structured
ToolError, never swallowed. See
Connect Claude Code, Cursor, and Codex for
how a client authenticates.
Two read tools treat a documented empty result as a valid answer, not an
error: gilt returns {"gilt": false, ...} on the Core's 404, and
prozess_bild returns {"bild_url": null, ...} on its 404. Every other
tool passes a non-2xx response through as an error.
Reading a Sache
| Tool | Parameters | Returns |
|---|---|---|
sache_list |
bereich?, stufe?, suche?, persona_slug?, alle=False, gehoert_persona? |
Sachen with their question and current rule. persona_slug filters by the calling persona's visibility (sent as sichtfeld=); gehoert_persona filters by ownership (sent as persona=) — independent filters. |
sache_get |
slug |
The Sache plus every statement, by kind, plus history. No visibility filter — this is a single lookup, not a list. |
gilt |
slug, subjekt_id?, persona_slug?, alle=False |
The one currently-held rule, or a valid empty result. |
gilt_am |
slug, datum, subjekt_id?, persona_slug?, alle=False |
What held on that date, with status. |
warum |
slug |
The rule's decision text, history, last check result. |
suche |
q, subjekt_id?, persona_slug?, alle=False |
Full-text search over statements and events. |
konflikte |
— | Sachen with a conflict. |
graph |
slug?, id?, tiefe=2 |
Nodes and edges around a Sache/statement/process. |
Writing a Sache or statement
| Tool | Parameters | Returns |
|---|---|---|
sache_put |
slug, titel, frage, bereich?, stufe?, eltern_slug?, subjekt_typ? |
Creates a Sache, idempotent on slug. |
aussage_put |
sache, art, text, herkunft, angelegt_von, subjekt_id=1, gilt_seit?, gilt_bis?, beobachtet_am?, quelle?, sicherheit?, ort?, pruefweg_slug?, beleg?, ersetzt?, status="gilt", frist?, prozess_slug?, schritt_key?, frame_ref? |
New statement. 409 with the current statement in the error body if ersetzt is missing and one already holds. |
hypothese_put |
sache, text, frist, pruefweg_slug, sicherheit, quelle, angelegt_von |
New hypothesis. The tool itself rejects sicherheit >= 1 before calling the Core. |
hypothese_bewerten |
id, ergebnis, quelle, neue_frist? |
Resolves a hypothesis (bestaetigt|widerlegt|verlaengert, validated client-side). |
pruefweg_run |
slug |
Runs a check, stores the result, writes a fact. |
abweichungen |
seit? |
Lists deviations. |
ereignis_put |
subjekt_id, typ, zeitpunkt, inhalt_ref, text? |
Records an event. |
frage_stellen |
sache, frage, optionen, gestellt_von, empfehlung_key?, frist? |
Raises a Schaltzentrale question. The tool rejects fewer than two options, or any option missing a folge, before calling the Core. |
offen_fuer_mensch |
— | Everything currently needing a human click. An open question arrives complete: the question itself and, per option, key, label and consequence — so an agent can put it to a person without inventing anything. |
frage_beantworten |
id, key, notiz? |
Answers an open question. Only as a signed-in person over an OAuth connection — with a key, or after persona_waehlen, the call is refused. The answer carries the signed-in person's name (from the session, not from the call) and the note "im Chat". |
seit_wann_neu |
seit |
Answered questions since a timestamp (see the deviations note on the REST reference page). |
Processes
| Tool | Parameters | Returns |
|---|---|---|
prozess_get |
slug, version? |
One state of a process: steps, per-step rules, gaps, ueberholt, and versionen (every state with gilt_seit/gilt_bis). Without version the current one, with version exactly that one — this is how to look up what held before a change. A state that does not exist is an error, not the latest one. |
prozess_put |
slug, titel, diagramm_md, schritte, angelegt_von, subjekt_typ?, ersetzt_slug? |
Creates a process or a new version. |
prozess_beenden |
slug, grund, angelegt_von |
Ends a process with no successor. There is deliberately no aussage_beenden tool — ending a single statement is a human decision made over Web/REST, not an agent tool; a process is the one exception because ending it is part of an agent's routine rule-book upkeep. |
prozess_bild |
slug, schritt |
The step's image, or a named empty result. |
kern_render |
subjekt_id |
The rendered core as Markdown, plus a hash. |
Personas, memory, and templates
persona_put and from_vorlage are deliberately not MCP tools — task,
boundaries, style, and rules change only through a human with a rw key on
the Web UI. Writing memory about oneself is the one exception agents get.
| Tool | Parameters | Returns |
|---|---|---|
persona_list |
— | Every persona with its counts. |
persona_get |
slug |
A persona in full, plus its rules and 10 newest memory entries. |
persona_brief |
slug, max_gedaechtnis?, max_lehren? |
The deterministic Markdown brief. |
persona_waehlen |
slug |
Binds this chat to a persona: from then on its tool permissions and scope apply, and it is the author of whatever gets written. Only over an OAuth connection — a key already carries its own binding. Active personas of your own project only; every call is logged. Without a choice, nothing changes. |
firma_get |
— | The six company-memory fields, read-only. Only a signed-in person may change them — over the API too; an agent inside a person's session counts, a key alone does not. |
memory_search |
persona_slug, q, art?, limit=20, lesende_persona?, alle=False |
Full-text search over a persona's memory. lesende_persona is the visibility filter here (not persona_slug, which already names whose memory is searched — a deliberately different parameter name for a different question). |
memory_put |
persona_slug, art, text, tags=[], gilt_bis? |
Writes a memory entry. |
vorlagen_list |
— | The persona template catalog. |
vorlagen_vorschlag |
bedarf |
Up to 3 ranked templates for a free-text need. |
Agents: presence and inbox
Module mcp/agents_tools.py.
| Tool | Parameters | Returns |
|---|---|---|
agent_herzschlag |
persona_slug, sitzung, client, status="online", arbeitet_an?, kontext_zeichen?, modell? |
Session heartbeat; a read-only key is enough — a heartbeat is not a write to knowledge. |
agent_offline |
persona_slug, sitzung |
Explicitly ends a session. |
agents_liste |
— | Every active persona with presence and inbox counts, including personas that never sent a heartbeat. |
nachricht_senden |
an_persona, text, art="info", betreff?, von_persona?, antwort_auf?, prioritaet="normal" |
Sends a message. |
auftrag_senden |
an_persona, text, betreff?, von_persona?, prioritaet="normal" |
Shorthand for nachricht_senden(art="auftrag"). |
auftrag_status |
id, status, notiz? |
Sets a task message's status. |
nachricht_an_mensch |
von_persona, von_sitzung, text, betreff?, art="info", prioritaet="normal", schwere? |
Message/task to the human — appears in "Your inbox" on the control room. For a rule-changing decision, frage_stellen remains the way; for a lesson/insight, hinweis_an_mensch. |
nachrichten_abholen |
persona_slug, sitzung, nur_neue=True |
Reads a session's inbox; marks undelivered messages delivered. |
postfach_stand |
persona_slug |
How much is in the mailbox — without touching it (no delivery stamp, no write). |
nachricht_gelesen |
id, persona_slug? |
Marks one or several messages read (id also takes a list). For a round post persona_slug is required — only that persona's read position moves. |
runde_eroeffnen |
titel, frage, teilnehmer, von_persona?, von_sitzung?, slug? |
Opens a round: a conversation of several personas on one question (with a question mark), at least two participants. |
runden_liste |
persona_slug?, nur_offene=True |
Lists rounds, newest first. |
runde_lesen |
slug |
One round with all posts, the cap per participant and the open, explicitly addressed questions. |
runde_beitrag |
slug, text, von_persona?, von_sitzung?, antwort_auf?, frage_an? |
Posts into a round. At most three posts per persona; after that only as an answer to a question explicitly addressed to it. Whoever agrees stays silent. |
runde_schliessen |
slug, ergebnis, von_persona? |
Closes a round — only whoever opened it, with a result in one sentence. |
Hall of Lessons
Module mcp/lehren_tools.py.
| Tool | Parameters | Returns |
|---|---|---|
lehre_put |
art, titel, was, lehre, bereich, ursache?, wirkung?, persona_slug?, belege?, regel_vorschlag?, quelle_ref?, herkunft? |
Files a lesson. ursache is required client-side for art="fehler". bereich is required — if you don't know where it belongs yet, use unsortiert. |
lehre_korrigieren |
id, bereich?, titel?, was?, lehre?, grund? |
Corrects the area or wording of an existing lesson. Not changeable: art, cause, evidence, status, persona. When you correct the wording, send the whole text — the correction replaces the field, it does not append to it. If the reason for the correction sits in the cause, a correction cannot do the job: a new lesson supersedes the old one instead. |
lehren_suche |
q?, art?, status?, bereich?, lesende_persona?, limit? |
Searches lessons; lesende_persona filters by visibility, same pattern as memory_search. |
hinweis_an_mensch |
titel, was, lehre, persona_slug, wirkung?, herkunft? |
Same write path as lehre_put, fixed to art="hinweis". |
lehre_aufnehmen |
id, von, notiz? |
Marks a lesson seen and endorsed. von is required by the tool — the Core route requires it, so a tool without it would always fail with 422. |
lehre_regel_vorschlagen |
id, sache, regel_text, von, titel?, frage? |
Raises a Schaltzentrale question to turn a lesson into a rule — never writes the rule directly. Same von note as above. |
Beurteilung (personnel file)
Module mcp/beurteilung_tools.py.
| Tool | Parameters | Returns |
|---|---|---|
beurteilung_get |
persona_slug |
The five-block personnel-file view (open proposals, wins, self-reported mistakes, relapses, human feedback). |
rollen_vorschlag |
persona_slug, feld, neu, begruendung, lehre_ids, von?, alt? |
Proposes a change to one persona field, backed by lessons. |
Hall of Fame
Module mcp/hall_of_fame_tools.py. Read-only — scoring itself happens in
the Core at the moment the underlying event occurs; no agent tool awards
points or thumbs.
| Tool | Parameters | Returns |
|---|---|---|
hall_of_fame |
woche? |
The weekly leaderboard. |
meine_anerkennung |
persona_slug |
A persona's own thumbs total and recent history. |
Statistik
Module mcp/statistik_tools.py.
| Tool | Parameters | Returns |
|---|---|---|
statistik |
— | The same six blocks as GET /statistik, unchanged. |
Export
Module mcp/export_tools.py — "your data is yours".
| Tool | Parameters | Returns |
|---|---|---|
export |
format? (json|markdown, default json) |
Only header + counts (GET /export/kopf) plus a pointer to the full REST path — the full export (every statement with its history, or the entire rule book) would be an unnecessarily large tool output for a language model. For the full export: GET /export?format=json or ?format=markdown directly against the core. |
Visibility (sichtfeld)
gilt, gilt_am, suche, and memory_search (as lesende_persona) take
the calling persona's own slug and filter the answer to its sichtfeld
(visibility — a list of areas). sache_list does the same thing but under
a different parameter (persona_slug, since persona= on /sachen already
means "owned by") — the same reasoning behind gehoert_persona being a
second, independent filter. alle=True deliberately lifts the filter and
is logged as an event. A 403 ("outside the visibility") from these tools
is a real error, not an empty result — unlike the documented 404 from
gilt.
What is not an MCP tool, on purpose
persona_put/from_vorlage— task, boundaries, style, and rules change only through a human on the Web UI with anrwkey.aussage_beenden— ending one statement is the same kind of human decision as writingpersona_put; onlyprozess_beendengets an exception, because ending a process is part of an agent's routine upkeep of the rule book.- A thumbs-up tool — "stage one: only the human hands them out."
Deviation found while writing this page
mcp/beurteilung_tools.py's rollen_vorschlag calls
CoreClient.request(..., json=body), but CoreClient.request() takes
json_body, not json — as written this raises a TypeError before the
Core is ever called, and the call also omits rw=True despite writing.
Reported here, not fixed — out of scope for this documentation change.