MCP tools
The tuckit MCP server exposes these tools at /mcp.
The daily loop is the part about when to reach for
each one.
Your client’s tool list is the authority. If it disagrees with this page, trust the client. The server describes itself.
One name differs from the screen: a slice is what the app calls a card.
At a glance
Section titled “At a glance”| Tool | What it’s for |
|---|---|
get_project_state |
The entry point. Whole-board snapshot plus who you are |
list_areas |
Area names and their ids |
create_area |
Add an area |
list_slices |
Search and filter work |
get_slice |
One card in full, as markdown |
create_slice |
Make a card |
update_slice |
Edit, file, reorder, or decide |
add_note |
Append to the activity log |
append_decision |
Add to the record of how this was decided |
record_verification |
Write down what you actually saw |
Reading state
Section titled “Reading state”get_project_state
Section titled “get_project_state”Start here. One call gives you the caller’s identity, the organisation, every non-archived area split into finished and upcoming, and the Inbox count.
| Parameter | Type | Notes |
|---|---|---|
area_id |
int, optional | Scope to a single area |
Returns caller (user_email, workspace_slug, workspace_name), workspace, inbox
(open_count plus the ten most recent), and areas[] with each area’s
shipped[], roadmap[] and counts.
inbox counts cards that have no area yet: things someone decided mattered
before deciding where they belong. They’re ordinary cards, not a separate kind
of object.
list_areas
Section titled “list_areas”No parameters. Returns every non-archived area with its id, name and
slug.
Call this before filing anything. Area ids are what the write tools take, and an agent that guesses either fails or invents a near-duplicate area.
list_slices
Section titled “list_slices”Search and filter. Every filter is optional.
| Parameter | Type | Notes |
|---|---|---|
area_id |
int | '', optional |
Omit for the whole workspace including the Inbox; pass '' for the Inbox alone |
status |
string, optional | open, shipped, dropped |
tag |
string, optional | |
query |
string, optional | Text match on title and spec |
assignee |
string, optional | 'me' or an email address |
limit |
int, optional | Defaults to 50 |
Each row carries a derived stage, so you can see what a card needs next
without opening it.
The area_id argument has three meanings and they’re easy to conflate. Omitted
searches everything. '' returns only the Inbox: open cards with no area,
exactly the ones get_project_state counted. A numeric id scopes to that area.
A card that was finished or dropped without ever being filed has left the
Inbox, so area_id='' won’t return it. Omit area_id and pass status to find
those.
get_slice
Section titled “get_slice”One card rendered as markdown: title, Status:, Stage:, then the spec,
## Constraints, ## Done when, and ## Decisions.
| Parameter | Type | Notes |
|---|---|---|
slice |
int | string | An internal id or a number like ACME-42 |
with_activity |
bool, optional | Append the notes thread |
Read this before touching the work. The Stage: line, not Status:, is where
progress lives.
Writing
Section titled “Writing”create_area
Section titled “create_area”| Parameter | Type | Notes |
|---|---|---|
name |
string | required |
description |
string, optional |
Areas are long-lived. Check list_areas first: a second area called backend
splits the board in a way nobody notices for weeks.
create_slice
Section titled “create_slice”| Parameter | Type | Notes |
|---|---|---|
title |
string | required |
area_id |
int | '', optional |
Leave empty to park it in the Inbox |
spec |
string, optional | What we’re building |
constraints |
string, optional | Landmines and invariants |
done_when |
string, optional | What somebody would have to observe to call this finished |
status |
string, optional | Defaults to open |
tags |
string[], optional | |
assignee |
string, optional | 'me' or an email |
external_key |
string, optional | Makes re-runs safe |
after_id / before_id |
int, optional | Position relative to another card |
Leave spec empty if the work hasn’t been thought through. An empty spec is
what reads back as needs_design. Filling it with a rough note makes
un-designed work look designed to whoever picks it up next.
external_key is the one to reach for in automation: the same key updates the
existing card instead of creating a duplicate, so a re-run is safe.
update_slice
Section titled “update_slice”Omitted fields are left alone.
| Parameter | Type | Notes |
|---|---|---|
slice_id |
int | required. The internal id |
title, spec, constraints, done_when |
string, optional | |
area_id |
int | '', optional |
An id files it; '' sends it back to the Inbox |
status |
string, optional | open, shipped, dropped. A decision only |
tags |
string[], optional | |
assignee |
string, optional | '' clears, 'me', or an email |
after_id / before_id |
int, optional | Reorder |
Filing works in both directions and neither is one-way.
status records a decision and nothing else. Never read progress from it. Read
stage, which list_slices and get_slice both report.
add_note
Section titled “add_note”| Parameter | Type | Notes |
|---|---|---|
slice |
int | string | internal id or card number |
body |
string | required |
Appends to the card’s activity log. Notes are past tense: what was tried, what broke, where the work landed. The spec is what we’re building; constraints are the standing warnings; a note is what happened.
append_decision
Section titled “append_decision”| Parameter | Type | Notes |
|---|---|---|
slice_id |
int | required |
body |
string | required |
Adds one entry to the card’s decision record. The server stamps the date and who wrote it, so the body is just the reasoning: what was chosen, why, what was turned down, and what the choice is leaning on.
It only ever appends. There is no tool that rewrites the record, and that is deliberate: the spec is where we arrived and gets edited as the work moves, and this is the snapshot of how we got there, which must not.
record_verification
Section titled “record_verification”| Parameter | Type | Notes |
|---|---|---|
slice_id |
int | required |
evidence |
string | What you actually observed. An empty string withdraws it |
Writes the evidence and stamps when. That stamp is what moves the card to
ready_to_ship, and the app will not let the card be shipped without it.
Write what you saw, not what you ran. pytest -q is a command; “an expired
token came back as HTTP 401 instead of an error inside a 200” is an
observation, and only the second one can turn out to be false.
This is a claim, not proof. tuckit cannot run your tests and does not try to judge what you wrote. What it does is refuse to open the irreversible button until somebody has put a claim next to the work.
Passing an empty evidence withdraws it and sends the card back to
executing. Do that the moment the claim stops being true.
Things that are not tools
Section titled “Things that are not tools”There’s no tool to set a stage, because a stage is worked out rather than
stored. There’s no tool to promote a quick note into a heavier object, because
there’s only one object. There’s no step list, because nobody read one. And
there’s no tool to mark something finished on your behalf: that’s
update_slice with an explicit status, and it should follow a human saying
so.

