tada

Docs

Agents & MCP

Your agent works the same board you do, through tada's MCP server. This page covers what the server gives it, how its edits and yours stay out of each other's way, and the rules it follows to keep the plan honest. Setting it up is on Quick start.

How an agent works a board

  1. It reads the board, usually just the In Progress and Planned columns.
  2. Before starting something, it moves that Story or Task to In Progress.
  3. As each piece lands it moves the Task along, and it writes what actually shipped into the description.
  4. Anything it finds along the way, like a bug or a follow-up, goes on the board as a new Story instead of being done silently.

You see each of those edits in your open browser as it happens, with no refresh. Whenever anything on a board is written, by you or by the agent, every open tab updates.

Finding Stories and Tasks

Tools find a Story by its title or its id, like tada-96. Titles are what an agent reads off the board; the id survives a rename. Each Task has its own id too, like tada-131.2. It survives reordering and renaming, so it's the reliable way to point at one Task, in a tool call or in chat.

Lookups also find Stories that have already been filed to the Changelog, so an agent can still edit or merge one. Only view_board is limited to the active board.

When you and the agent edit at once

Every agent write checks whether the Story changed since the agent read it. If it did, what happens depends on what changed:

Who changed what

Anything an agent creates, edits, or merges gets the ๐Ÿค– ai-generated tag, and the tag stays even after you edit the Story yourself. Moving a Story or Task between columns doesn't add it.

For the detail, story_activity_log lists a Story's recent writes, newest first, each marked with how it arrived:

browser
The web app: you, or an agent driving the browser without saying so.
browser:automated
An agent driving the web app that said so, by opening it with ?automated=1.
mcp
An agent using the MCP server.
system
tada's own housekeeping.

It keeps recent history, not a permanent record, and it can answer by id for a Story or Task that has been deleted. Each client reports its own label, so the label says which way a write came in, not who a person is. Don't treat it as proof.

Access

There is no API key. The server acts as the account you name in its config, and every call is checked against that account. Only a board's owner can write to it, and a private board is invisible to everyone else: its tools answer as if it doesn't exist.

The tools

Reading

ToolWhat it does
view_boardThe board grouped by column, with Tasks. Descriptions show as a one-line preview. Optional status and type filters keep a big board's output small.
get_storyOne Story and its Tasks in full, by title or id.
story_activity_logA Story's recent writes, newest first, with how each arrived. Works by id for a deleted Story or Task.
board_urlThe link to open the board in a browser.

Stories

ToolWhat it does
add_storyCreate a Story with a title and, optionally, a type (default Feature), status (default Planned), description, tags, and due date. A Bug with no description gets the Expected/Observed template.
update_storyChange a Story's title, type, status, description, tags, or due date.
set_statusMove a Story to another column.
move_storyPut a Story at a position in its column, where 0 is the top. Order is priority. Pass a status to change column in the same write.
delete_storyDelete a Story.
merge_storiesFold other Stories into one: their descriptions are appended, tags combine, Tasks move over, and the others are deleted.

Relationships

ToolWhat it does
link_storyRelate two Stories; by default, mark one as blocked by the other. Refused if it would make a loop of blockers. Two Stories have one relationship at most, and replace swaps it.
unlink_storyRemove a relationship between two Stories.

Tasks

ToolWhat it does
add_subtaskAdd a Task to a Story, optionally with a status and due date. The reply gives the Task's id.
edit_subtaskRename a Task, or set or clear its due date.
set_subtask_statusMove a Task to another column.
move_subtaskPut a Task at a position in its column, optionally changing column in the same write.
delete_subtaskDelete a Task.

Boards

ToolWhat it does
create_boardCreate a new, empty board you own, private unless you say otherwise. Its slug is permanent. The server stays on its own board, so the new one needs its own server entry.
delete_boardDelete this server's board; you type its slug to confirm. Nothing is erased, and restore_board brings it back.
restore_boardRestore a board you deleted, exactly as it was.

The rules your agent follows

This section is tada's agent instructions: the AGENTS.md file an agent reads when it works a board. It's generated from that file, so it says exactly what agents are told.

If a project's .mcp.json wires in the tada MCP server, you can read and edit that project's plan. Keep it honest โ€” it's the shared source of truth the human is watching in the browser. These are the rules.

Always start with view_board

Call view_board before editing so you know the exact story titles (the edit tools look stories up by title). It shows every card grouped by column, with tasks. On a large board, pass status (one value or a list, e.g. status: "in-progress") to scope to just the columns you need and keep the output small; omit it for the whole board. Notes are shown as a one-line preview (flagged "full note via get_story" when shortened) โ€” call get_story for a story's complete note.

When to update the plan

Stories you create, edit, or merge through the MCP tools are automatically tagged ๐Ÿค– ai-generated (add_story, content edits via update_story, and merge_stories; a plain status move isn't tagged). You don't set this โ€” it's a record that an agent touched the Story, and a human editing it later won't remove it. To mark a Story ๐Ÿ‘๏ธ ui, ๐Ÿงช testing, or ๐Ÿ”Œ api as well, pass a tags array to add_story / update_story (e.g. tags: ["ui"]) โ€” on update_story it replaces the Story's tags, with ai-generated always kept.

A Story may carry an optional due date: pass due_date as YYYY-MM-DD to add_story or update_story, and an empty string to update_story to clear it. It is a calendar day, not a timestamp, and relative dates are refused โ€” work out what "next Friday" is yourself and pass the date, since resolving it against the server's clock would give an answer that depends on where the server runs. view_board prints a due: line for each dated Story and marks the overdue ones โš ๏ธ overdue, so you can see what has slipped without knowing today's date.

Tasks carry due dates too โ€” add_subtask takes a due_date, and edit_subtask sets or clears one ("" clears, as on a Story). Same rules: a calendar day, no relative dates. A task may be due after its parent Story; that overrun is surfaced on the Story card, not refused, so you don't have to move the Story's date to record a later piece of work.

What not to do

Showing the human the board

If the human wants to watch progress, call board_url and give them the link. Your edits appear in their open browser as you make them โ€” no refresh needed.

Terminology: Stories vs. Tasks

("Task" is unambiguous: the maintenance Story type is Chore, so the word "Task" only ever means a unit of work belonging to a Story.)

Types vs. status

Every story is a Story โ€” a unit of work with one of four types. Pick the type by the nature of the work, not which part of the app it touches:

Borderline calls: a pure refactor is a chore (internal, no behavior change); adding/expanding tests is infrastructure (it hardens the platform, not the product). When a Story would fit two types, pick the one matching its primary outcome and note the rest.

Description templates. The card detail lives in the single note field (markdown). Some types seed a starter scaffold to capture the detail that matters: a bug seeds Expected / Observed markdown headings โ€” the variance that defines the bug. Creating a bug via add_story without a note seeds that scaffold for you; pass an explicit note to override it.

Each Story can also have Tasks โ€” use add_subtask to break it down.

Type and status are independent. A bug you're actively fixing is type: "bug", status: "in-progress".

Access to the hosted board

There is no API key. Access is gated by identity: the tada MCP server runs as a specific owner (--owner-email in the project's .mcp.json), and every read and write is authorized against that user's board ownership โ€” so a private board just works through the MCP tools, with no secret to handle.

A plain curl against a private board will 404 as an anonymous request. That is the access check working, not a misconfiguration โ€” read through the MCP tools instead.

Editing the board without MCP

Don't. The board lives in a database, not in a file you can open โ€” there is no board file to hand-edit or validate. If the MCP tools aren't available, fix the connection rather than reaching for the data directly.

add_story needs only a title: type defaults to feature and status to planned.