Tool reference

Twenty-seven tools over MCP. Names use underscores; the same capabilities are on the REST API with dotted names.

Reading

ToolArgumentsWhat it does
project_list{}Every project in the workspace, with status, next step and public URL.
project_resume{ project }The whole document in one call — purpose, architecture, features, roadmap, tasks, activity, decisions, feedback, people, plus the page URL and an inbox of answered and open questions. Call this first.
task_list{ project, state? }The work list, with each task's key.
feature_list{ project }Every feature with the key feature_upsert takes. Call it before editing a feature on a project you did not create — guessing the key makes a duplicate.
theme_get{ project }Preset, overrides, the stored CSS verbatim, resolved token values, and every token you may override. Read this before theme_set.
feedback_list{ project, state?, kind? }What stakeholders asked for, highest-voted first, with a count of what is still unanswered.

Writing

Every write requires a token with write scope, and is logged and revertable.

ToolArgumentsWhat it does
project_ensure{ name, slug?, summary? }Idempotent — returns the existing project if the slug is taken, and the page URL either way.
project_import{ project, …state, purpose?, architecture?, roadmap?, features[]?, tasks[]?, updates[]?, theme?, visibility?, ifRevision? }The whole document in one call. Use it for a first import instead of thirty separate writes, and for bulk corrections after. A bad row is reported in refused; the rest still lands.
status_set{ project, status, note? }Moves the standing. Pass a note; a status change with no reason is noise.
next_set{ project, next, owner? }Exactly one next step.
update_create{ project, title, body?, tags?, kind?, statusChange?, happenedAt?, links? }An update, or a decision with kind: "decision". Pass happenedAt (ISO 8601, past only) when writing up work that already happened, or a year of history all reads as minutes old.
feature_upsert{ project, key, name, state?, area?, version?, owner?, summary?, detail?, shipped?, links?, question? }A capability someone could have an opinion about. Keyed, so it edits rather than duplicates.
task_upsert{ project, key, title, state?, detail?, area?, owner?, internal?, links?, question? }A job on the list. No task appears on the published page, so internal is a marker for chores rather than a visibility control.
task_delete{ project, key }For a duplicate or one created in error.
feature_delete{ project, key }For a feature that should not exist. Mis-filed work should use feature_to_task instead.
update_delete{ project, at?, title? }For something posted in error. Identify it by at, the exact timestamp from project_resume; an ambiguous title is refused rather than guessed at.
project_ask{ project, question }A question about the project itself rather than any one piece of work — instead of inventing a task to hang it on.
feedback_to_task{ project, id, title?, state? }Turns feedback into work, keeping the trace back to who asked. Does not reply — follow it with feedback_reply.
feature_to_task{ project, feature }Reclassify build work that was filed as a feature. Nothing is lost.
purpose_set{ project, why?, who?, success?, constraints?, ifRevision? }Merges into the purpose section.
architecture_set{ project, summary?, services?, entrypoints?, environments?, integrations?, conventions?, openQuestions?, ifRevision? }Merges into architecture. Provenance is stamped from the token.
roadmap_set{ project, doing?, planned?, considering?, ifRevision? }Each bucket you pass replaces that bucket.
theme_set{ project, preset?, css?, overrides?, fonts?, dryRun?, ifRevision? }Styling. fonts is { display, body } from theme_get's fontsAvailable — self-hosted, so an arbitrary family is refused. css replaces the stored stylesheet rather than merging: read theme_get first. dryRun resolves without saving.
logo_set{ project, url, alt? }Copies an image to Ticulate and shows it above the project name. Copied rather than linked, so the page never fetches from another host and it survives the original moving. url: null removes it.
publish_set{ project, visibility }private, shared or public. Returns the URL. Ask first.
feedback_reply{ project, id, text, state? }Answers on the object the feedback was left on.
review_open{ project, feature, ask }Asks stakeholders a specific question about something you shipped.

Values that are fixed

statusshipped ontrack atrisk blocked idle
visibilityprivate shared public
feature statelive building beta deprecated
task stateopen doing done
feedback statetriaged planned review answered declined
theme presetticulate terminal editorial blueprint

ontrack and atrisk have no space and no underscore. An unknown value is refused with an error naming the legal ones.

Tuple shapes in architecture_set

Order matters.

services:      [["name", "what it does", "language", "repo", "runs on"]]
entrypoints:   [["label", "path", "why it matters"]]
environments:  [["name", "url", "branch", "note"]]
openQuestions: [["the question", "what it is blocked on"]]
integrations:  ["Stripe", "GitHub"]
conventions:   ["Every agent write carries an actor and a revision"]

Errors worth handling

MessageWhat to do
No project "x" in this workspaceproject_list, or project_ensure to create it
This token is read onlyStop, and ask for a write token rather than working around it
Token rejectedRevoked or wrong — a new one is needed
The project moved on while you were workingResume again, merge into what is there now, retry — see several agents at once
This token is scoped to a single projectIt was issued for one project and cannot reach others. project_list shows which
"x" is archivedSomeone took the project down. It has to be restored before it accepts writes