> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fermata.run/llms.txt
> Use this file to discover all available pages before exploring further.

# Fermata MCP server tool reference

> Every tool the Fermata MCP server serves: arguments, results, and whether it runs on the call or waits for a confirmation card.

This page lists every tool the Fermata MCP server serves, the arguments each one takes, what it returns, and whether it runs on the client's call or waits for you to answer a confirmation card in Fermata. To turn the server on and connect a client, see [connect a client](https://docs.fermata.run/mcp/connect.md). For the same tools phrased as requests you type to Claude, see [what you can do](https://docs.fermata.run/mcp/what-you-can-do.md).

Every result is JSON text. Absent values are `null` rather than missing, dates are ISO 8601 strings, and ids are UUID strings. A malformed argument fails as an invalid-params error. A call that is well formed but cannot be done, such as an action that is illegal in the piece's current phase, fails as a tool error with a sentence explaining why.

## The consent rule

[Consent and safety](https://docs.fermata.run/mcp/consent-and-safety.md) explains these rules in full; this section is the summary.

The client's call is your consent. A client acting on your request already has your go-ahead, so actions that create or publish work run on the call, with no card in Fermata.

Two actions always wait for a confirmation card: `stopAgents`, because it kills running work, and `markDone`, because it can tear down a worktree. The card names the piece and the project, and you answer **Allow** or **Deny**. A denied card fails the call with no change to the piece, and nothing on the server times a waiting card out.

If you want a card in front of runs and pull requests too, turn on **Ask before runs and pull requests** in Settings → MCP. It is off by default. With it on, nine more actions wait for a card: `startExecution`, `resumeAgents`, `retryFailedAgents`, `resumeTask`, `editTaskBrief`, `messageTask`, `answerTaskQuestion`, `createPR`, and `approveSpec` with lane `auto`. Releasing a draft on the Auto lane waits for one too, whether through `release_draft` or `create_draft` with `release` set. The setting is read on every call, so a change applies to the next one.

A client that gives up on a waiting call sends a cancellation, and Fermata denies the call and removes its card. A card for a piece that belongs to no project shows in every open project window.

## Fermata's own agents

Agents that Fermata itself runs cannot use the server's write tools. Once you register the server with Claude Code, every session Fermata starts loads it too, and without this rule an agent inside one piece could start runs or open pull requests on others. The rule covers every kind of session: build agents on any permission profile, the spec interview, reviews, feedback sessions, and sessions you open on the canvas. The planning passes Fermata runs in the background have the write tools removed outright.

The write tools are `create_piece`, `create_draft`, `update_draft`, `cancel_draft`, `release_draft`, `register_project`, `open_piece_workspace`, `piece_action`, `snooze_cue`, and `reveal`. A call to one of them from inside Fermata is refused with: "Fermata's own agents can't drive Fermata through its MCP server. Ask the person to do this from the app or from their own MCP client." The read tools stay available under the session's normal approval rules.

The rule matches the server by the name Register gives it, `fermata`. If you add the endpoint to Claude Code by hand under a different name, Fermata's own agents are not fenced off from it.

## `list_projects`

Lists every project registered in Fermata. Read, runs on the call.

Takes no arguments.

Returns `{"projects": [...]}`, one row per project: `id` (the `projectId` other tools take), `name`, `path` (the repository folder), and `branch` (the branch Fermata tracks for it).

## `list_echoes`

Lists the Echoes, the remote machines pieces and sessions can run on. Read, runs on the call.

Takes no arguments.

Returns `{"echoes": [...]}`, one row per Echo: `id` and `name` (either is what `runAt` accepts), `kind` (`ownMac`, `bitriseMac`, or `bitriseLinux`), and `state`, the last health check (`ready`, `asleep`, `stopped`, `unreachable`, or `checking`), or `unknown` before the first one. Echoes is an Edge feature that starts off, so until it is turned on in Settings › Edge, `list_echoes` returns an empty list.

## `register_project`

Registers a directory as a Fermata project so pieces can be created in it. If the directory, or a folder above it, is already a project, that project comes back unchanged. Write, runs on the call.

| Argument | Type | Required | Notes |
| - | - | - | - |
| `path` | string | yes | Absolute path of the directory, usually the repository root. |

Returns `{ok, projectId, name, path, alreadyRegistered}`.

The directory must be a git repository with at least one commit, because every piece runs in its own git worktree. A directory that is not a repository is refused with an error that names the fix: run `git init` there, make a first commit, and call `register_project` again. Nothing is registered, and the tool never initializes a repository for you.

## `list_pieces`

Lists pieces and Backlog drafts, optionally scoped to one project. Read, runs on the call.

| Argument | Type | Required | Notes |
| - | - | - | - |
| `projectId` | string | no | Scope to one project. |
| `cwd` | string | no | Your working directory. Used when `projectId` is absent to find the project that contains it. |
| `includeArchived` | boolean | no | Include archived pieces. Defaults to false. Drafts are listed either way. |

Returns `{"pieces": [...]}`. Every row carries `kind`, either `"piece"` or `"draft"`, and drafts follow the pieces.

A piece row carries `id`, `name`, `projectId`, `phase` (`{key, display}`), `gate` (the decision waiting on you, or null while the machine is working), `activity` (the live run state), `taskCount`, `completedTaskCount`, `progress` (0 to 1), `prURL`, `createdAt`, `updatedAt`, `completedAt`, and `isArchived`. While a piece waits on other pieces, `activity` is `waiting`; when a piece it waits on fails, stops, or is archived, it is `dependencyBlocked`, which needs you.

A draft row carries `id`, `name` (the draft's title), `projectId`, `lane` (`manual`, `auto`, or `loop`), `phase` (always `{"key": "backlog", "display": "Backlog"}`), `createdAt`, `hasSpec`, `refine`, `modelId`, `source` (`{key, url, kind}` for a draft started from a tracker issue or linked to one with `keys`, otherwise null), `related` (the further linked keys as `{key, url, kind}`, always present and empty when there are none), and `attachmentCount`.

Both kinds of row also carry the piece dependency fields:

* `dependsOn`: one `{id, key, name, origin, state, ignored}` per link. `id` is the blocker's id, or null for a tracker issue that is not a piece yet. `key` is the blocker's tracker key, or null when it has none. `origin` is `manual`, `linear`, `github`, or `split`. `state` is the blocker's phase as the board shows it (`Agents 2/4`, `Done`), `Backlog` for a draft, `open` or `closed` for a tracker issue, and `deleted` for a blocker that no longer exists.
* `waiting`: true while the dependencies actually hold the item back. Only the Auto and Loop lanes are held, and only before building starts, so a Manual item is never `waiting` unless a split holds it.
* `blockingKeys`: what is still unmet or has gone wrong, whatever the lane, each as the blocker's key when it has one and its id otherwise. Every entry is a value `piece_action` `removeDependency` accepts.

While piece dependencies are turned off (only during a maintenance shutdown), every row reports `dependsOn: []`, `waiting: false`, and `blockingKeys: []`. Links are kept, only hidden.

A piece row also carries its split state, read-only:

* `splitProposals`: one `{id, title, direction, source, revisedFrom}` per split waiting for a person in Fermata. `direction` is `prerequisite` (the new piece lands first) or `followUp`, `source` is `agent` or `manual`, and `revisedFrom` is the title the proposal was first shown under when a later agent pass revised it, otherwise null.
* `splitLinks`: one `{originalID, splitOffID, direction, proposalId}` per split the piece took part in, on both pieces of the split. `proposalId` is the proposal the split-off piece was created from, or null on a link written before it was recorded.
* `splitHold`: `{reason, blockingPieceIds}` while an unmet link to a piece of the same split holds the piece, in any lane, otherwise null. The split relationship decides, not the link's `origin`, so a link a person adds back between two pieces of a split holds too. An archived piece reports null. `piece_action` refuses `approveSpec` and `generateStrategy` with `reason` while it is set, and `legalActions` leaves them out. Only Start anyway in Fermata overrides it.
* `splitPending`: `{reason, proposalIds}` while split proposals wait for the person at the "Review split" gate, otherwise null. `reason` opens with why when Auto-split is off and stopped an Auto or Loop piece.
* `splitStart`: `{startSplitPiecesAutomatically, mode, waitsForYou, reason}`. `startSplitPiecesAutomatically` is the Pieces setting as it is now. `mode` is how the piece's latest split started its pieces, read from the setting when the split was applied: `automatic` (the new pieces keep the original's Auto or Loop lane), `waitsForYou` (the setting was off, so the new pieces wait at Spec ready in the Manual lane and the original stops at its strategy review), or `manual` (the original was Manual), otherwise null. `waitsForYou` is true until the person moves the piece on, and `reason` says why it waits when no split link holds it, otherwise null.

Both kinds of row carry `runAt` as `{choice, resolved, echoName, removed}`. `choice` is the item's own setting (`thisMac`, an Echo id, or null to follow the project), `resolved` is where it runs (`thisMac` or an Echo id), `echoName` names that Echo, and `removed` is true when the Echo it resolves to has been removed; such a piece waits and never falls back to this Mac. A piece row also carries `echo` as `{id, name, state, reason}`, where `state` is `local`, `connecting`, `connected`, `waiting` (with `reason`), or `removed`, and `id` and `name` are null for a local piece.

Releasing a draft creates a piece with the same id, so a client polling one id sees its row turn from `kind: "draft"` into `kind: "piece"`.

## `get_piece`

Reads one piece or one draft by id. Read, runs on the call.

| Argument | Type | Required | Notes |
| - | - | - | - |
| `pieceId` | string | yes | A piece id or a draft id, from `list_pieces`. |

For a piece, returns everything its `list_pieces` row carries plus `branchName`, `worktreePath`, `config`, the agent graph as `tasks` and `edges`, the linked `sessions`, `legalActions` (the `piece_action` values accepted right now), `reviewProgress` during review, `artifacts` (which documents exist), `splitEvents` (the piece's split history as `{at, kind, summary, startMode, proposalId}`, oldest first, kept across relaunches; `startMode` is set on the events of an applied split, and `proposalId` on the applied events that created a piece from a proposal), and, during Spec, `interview` with any unanswered questions.

For a draft, returns its `list_pieces` row plus `seed`, `spec` (the full text, or null), and `legalActions: ["update_draft", "cancel_draft", "release_draft"]`, followed by `addDependency` and `removeDependency` while piece dependencies are on.

An id that is neither fails with "Unknown pieceId".

## `get_artifact`

Reads one of a piece's documents or structured records. Read, runs on the call.

| Argument | Type | Required | Notes |
| - | - | - | - |
| `pieceId` | string | yes | The piece that owns the artifact. |
| `kind` | string | yes | `spec`, `strategy`, `summary`, `learnings`, `analysis`, `codeReview`, `handoff`, or `workReview`. |
| `taskId` | string | for `handoff` | The agent whose handoff to read. |

Returns `{pieceId, kind, present, format, content}`. The four documents come back as markdown, and the rest as JSON. An artifact that does not exist yet returns `present: false` with null content rather than an error.

`workReview` returns the work review's stored record: the verdict, the acceptance criteria it checked, what it cost, and two fields worked out the same way the app works them out: `outcome` (`pass` or `fail`) and `failedTasks`, a list of `{taskId, ordinal, name}` for the agents the review failed. A piece with no work review returns `present: false` and the message "This piece has no work review yet."

## `list_sessions`

Lists sessions with their state, piece, model, effort, branch, worktree, timestamps, cost, and whether one is waiting on a tool approval. Read, runs on the call.

| Argument | Type | Required | Notes |
| - | - | - | - |
| `projectId` | string | no | Scope to one project. |
| `cwd` | string | no | Your working directory, used when `projectId` is absent. |
| `includeHidden` | boolean | no | Include the hidden spec-interview and code-review sessions. Defaults to false. |

Each row carries `error`: the reason a failed session failed, and null for any other session.

## `get_session`

Reads one session: its `list_sessions` row plus, optionally, the tail of its transcript. Read, runs on the call.

| Argument | Type | Required | Notes |
| - | - | - | - |
| `sessionId` | string | yes | From `list_sessions`. |
| `transcriptLimit` | integer | no | How many of the latest messages to include, 0 to 200. Defaults to 0. |

## `create_piece`

Creates a piece and starts its spec interview from a prompt. The interview carries on in the background: poll `get_piece` for questions and answer them with `piece_action` `interviewMessage`. Write, runs on the call.

| Argument | Type | Required | Notes |
| - | - | - | - |
| `prompt` | string | yes | The idea the interview starts from. |
| `projectId` | string | no | The project. Found from `cwd` when absent. |
| `cwd` | string | no | Your working directory. |
| `name` | string | no | A working name until the spec's title replaces it. |
| `depth` | string | no | `quick`, `balanced` (default), or `thorough`. |
| `model` | string | no | An exact model id for the interview only. |
| `runAt` | string | no | Where the piece runs: `thisMac`, or an Echo by id or name (case-insensitive), from `list_echoes`. Omit it to follow the project, then the app default. |
| `id` | string | no | A UUID you choose, so a retry never creates a second piece. |

Returns `{ok, pieceId, name, phase}`.

An Echo named in `runAt` must exist. An unknown id or name, or a name two Echoes share, fails the call before anything is created, and the error lists the Echo names you can use. The same rule applies to `create_draft` and `update_draft`. A piece's Run at is fixed once its agents start on an Echo; after that only Run here in the app moves it. Echoes is an Edge feature that starts off; while it is off, a `runAt` that names an Echo fails the call, and `thisMac` or an omitted `runAt` runs the piece on this Mac.

## `create_draft`

Files a draft into a project's Backlog from a pre-written spec, a rough seed, or a tracker issue. Filing does not start anything: the draft waits for `release_draft`, or for you to release it in the app. There are two exceptions. With `release` set, the draft is released in the same call, exactly as `release_draft` would. A `loop` draft filed while that project's Loop is playing starts at once. Write, runs on the call; with `release` set on an Auto draft it waits for a card when the setting is on, and the card shows before anything is filed, so a denied card leaves nothing behind.

| Argument | Type | Required | Notes |
| - | - | - | - |
| `spec` | string | one of `spec`, `seed`, `issue` | The spec in markdown. |
| `seed` | string | one of `spec`, `seed`, `issue` | A rough prompt. |
| `issue` | string | one of `spec`, `seed`, `issue` | A tracker key: `SUP-12` for Linear or `owner/repo#12` for GitHub. Not a URL. Cannot be combined with `spec`, `seed`, `refine`, or `keys`. |
| `keys` | array of strings | no | Tracker keys that your `spec` or `seed` implements, 1 to 10, in the same two shapes as `issue`. Needs `spec` or `seed`; cannot be combined with `issue`. |
| `title` | string | no | Used when the spec has no title heading. For an issue, defaults to the issue's title. |
| `lane` | string | no | `manual` (default), `auto`, or `loop`. |
| `refine` | string | no | `none`, `if_gaps` (default), or `always`. |
| `model` | string | no | An exact model id for the spec step. |
| `release` | boolean | no | Release the draft right after filing it. Defaults to false. |
| `dependsOn` | array of strings | no | Up to 20 pieces or drafts of the same project this draft waits on, each by id or tracker key. |
| `projectId` | string | no | The project. Found from `cwd` when absent. |
| `cwd` | string | no | Your working directory. |
| `runAt` | string | no | Where the piece runs: `thisMac`, or an Echo by id or name (case-insensitive), from `list_echoes`. Omit it to follow the project, then the app default. |
| `id` | string | no | A UUID you choose, so a retry never files a second draft. |

An `issue` is fetched from a Stream Source linked to the project, of the same kind as the key. It needs Loop Intake, and it fails with a sentence saying why when that is unavailable, when the project links no source of that kind, or when the tracker refuses the request. The issue becomes the draft's spec and is formatted into a full spec when the draft is released, as a picked issue is in the app. An issue that is still blocked by open issues is filed anyway.

`keys` links tickets to text you wrote, without fetching their content. Use it when one piece covers several tickets, or when your spec carries decisions the ticket does not. Duplicates are dropped case-insensitively and the order is kept. Every key is verified through the project's linked Stream Source before anything is filed and before any card shows, so the call is all or nothing: a key that cannot be verified fails it with "Couldn't verify SUP-12: " followed by the reason, which covers a key that does not exist, Loop Intake being unavailable, no linked source of that kind, and a tracker error. Keys from Linear and GitHub can be mixed; each is checked against a source of its own kind. The first key becomes the draft's source, so the card shows its pill, the branch carries the key, and the pull request closes it. Every further key is related: it adds its own `Closes` line to the pull request, one per key, and appears nowhere else on the card. The spec stays the draft's only content and the title still comes from the spec's title heading, then `title`, then the seed. `refine` applies as usual. A malformed key, an empty array, more than 10 keys, `keys` without `spec` or `seed`, and `keys` with `issue` are argument errors that name the problem, the last one starting "create\_draft 'issue' can't be combined with 'keys':".

`dependsOn` makes the new draft wait on other pieces or drafts of its project, as "+ Add dependency" does in the inspector. Each entry is an id or a tracker key, which matches the piece or draft filed from that issue. Every entry is resolved before anything is filed, so one that names nothing in the project, or names something in another project, fails the call and files nothing. A draft filed from an `issue` also takes the issue's own "blocked by" links, as a pick in the app does. A link that would create a loop is skipped rather than failing the call, because the draft is already filed by then; it is listed in `skippedDependencies` as `{blocker, reason}`.

Returns `{ok, draftId, title, lane}`. A draft filed from an issue adds `source` (`{key, url, kind}`), and, while the issue is blocked, `blockedBy` (the open blockers' keys) and `blockedByCount`. A draft filed with `keys` adds `source` (the first key) and `related` (the rest, possibly empty), both as `{key, url, kind}`. A draft filed with `dependsOn` adds its `dependsOn` rows. With `release` set it returns the new piece's row instead, as `list_pieces` shows it, with `released: true`. When the draft's dependencies hold the release, the call still succeeds and returns `{ok, draftId, title, lane, released: false, waiting: true, waitsOn, dependsOn}`, where `waitsOn` lists what it waits on as `blockingKeys` does; the draft starts on its own once they are met. A resend after the draft was released returns `{ok, draftId, pieceId, released: true}`.

Running an issue on Auto is one call:

```json theme={null}
{"name": "create_draft", "arguments": {"issue": "SUP-12", "lane": "auto", "release": true, "cwd": "/path/to/repo"}}
```

Filing your own spec for two tickets, with the first as the source:

```json theme={null}
{"name": "create_draft", "arguments": {"spec": "# Balanced controls\n\n## Goal\n...", "keys": ["SUP-12", "SUP-13"], "cwd": "/path/to/repo"}}
```

## `update_draft`

Edits a Backlog draft before it runs. Pass at least one field to change; the others keep their value. A spec with a title heading renames the draft from that heading. An empty `seed` or `spec` clears it, but a draft has to keep one of the two. Moving a draft to `loop` while the project's Loop is playing starts it, as `create_draft` does. Write, runs on the call.

`keys` replaces the draft's linked tickets rather than adding to them, so sending the same list twice changes nothing and sending a shorter one removes the rest. The new keys are verified exactly as `create_draft` verifies them, before any field in the call is written, so a key that fails leaves the whole draft unchanged. An empty array clears every link. A draft filed from an `issue` refuses `keys` with a tool error, because its spec is that issue's text; file a new draft with `spec` and `keys` instead.

| Argument | Type | Required | Notes |
| - | - | - | - |
| `draftId` | string | yes | A draft id from `list_pieces`. |
| `title` | string | no | The card's title. |
| `seed` | string | no | The rough prompt. |
| `spec` | string | no | The spec in markdown. |
| `refine` | string | no | `none`, `if_gaps`, or `always`. |
| `model` | string | no | An exact model id for the spec step. |
| `lane` | string | no | `manual`, `auto`, or `loop`. |
| `keys` | array of strings | no | Up to 10 tracker keys, replacing the linked set; the first is the source. `[]` clears it. |
| `runAt` | string | no | Where the piece runs: `thisMac`, or an Echo by id or name (case-insensitive), from `list_echoes`. Omit it to follow the project, then the app default. |

Returns the draft's row as `list_pieces` shows it, or the new piece's row when moving it to `loop` started it.

## `cancel_draft`

Deletes a Backlog draft and any files staged with it. A released draft is a piece and is not affected. Write, runs on the call.

| Argument | Type | Required | Notes |
| - | - | - | - |
| `draftId` | string | yes | The draft to delete. |

Returns `{ok, draftId}`.

## `release_draft`

Starts a Backlog draft, as "Run spec" or "Play" does on the board. The draft's lane decides what runs: a `manual` or `loop` draft runs its spec step, and an `auto` draft runs the whole piece unattended up to Review. Write, runs on the call; an `auto` draft waits for a card when the setting is on.

| Argument | Type | Required | Notes |
| - | - | - | - |
| `draftId` | string | yes | The draft to release. |
| `model` | string | no | An exact model id for the spec step, written onto the draft first. |

Returns the new piece's row as `list_pieces` shows it. The piece keeps the draft's id. When the draft's dependencies hold the release, the call is not an error: it returns `{ok, draftId, title, lane, released: false, waiting: true, waitsOn, dependsOn}`, and the draft starts on its own once what it waits on is met. Resending for a draft that was already released returns that piece and starts nothing.

## `open_piece_workspace`

Gets a piece's worktree ready so you can work on it in your own terminal session, recreating it from the branch if it was removed. It does not move your session: the result tells the client to ask you before changing directory. Write, runs on the call.

| Argument | Type | Required | Notes |
| - | - | - | - |
| `pieceId` | string | yes | The piece to open. |

Returns the worktree path, branch, phase, pull request URL, the agents, the spec and strategy, and `agentInstruction`.

## `piece_action`

Moves a piece through its lifecycle, one action per call. An action that is illegal in the current phase fails and names the actions that are legal now, which `get_piece` also lists up front. Write.

| Argument | Type | Required | Notes |
| - | - | - | - |
| `pieceId` | string | yes | The piece to act on. `addDependency` and `removeDependency` also take a draft id. |
| `action` | string | yes | One of the actions below. |
| `prompt` | string | for `interviewMessage` and `editTaskBrief` | `interviewMessage`: the message for the interview. `editTaskBrief`: the agent's new brief. |
| `lane` | string | for `setLane` | `approveSpec`: `manual` (default) or `auto`. `setLane`: `manual`, `auto`, or `loop`. |
| `taskId` | string | for `approveTask`, `resumeTask`, `editTaskBrief`, `messageTask` and `answerTaskQuestion` | `approveTask`: the agent to approve. `resumeTask`: the failed agent to resume, from `get_artifact` `workReview`. The steering actions: the agent to steer, from `get_piece` `tasks`. `requestChanges` refuses it. |
| `text` | string | for `requestChanges`, `messageTask` and `answerTaskQuestion` | The change you want for `requestChanges`. The message for `messageTask`, or the answer for `answerTaskQuestion`, each up to 2,000 characters. Otherwise a note for `approveTask`, or closing feedback for `confirmDone`. |
| `taskIds` | array of strings | no | `sendBackToAgents`: the failed agents to send back, from `get_artifact` `workReview`. `retryFailedAgents`: the failed agents to recover, from `get_piece` `tasks`. Both default to every failed agent and refuse an agent that did not fail, listing the ones that did. |
| `guidance` | string | no | `sendBackToAgents` and `resumeTask`: your note for the rerun, sent after the review's findings. `retryFailedAgents`: your note for every agent the retry touches. Up to 2,000 characters. |
| `level` | string | no | `runCodeReview` only: `high` or `max` (default). |
| `title` | string | no | `createPR` only. Leave out both `title` and `body` and Fermata writes them from the diff, as the Loop does. |
| `body` | string | no | `createPR` only. Empty when you give a `title` alone. |
| `isDraft` | boolean | no | `createPR` only. Defaults to false. |
| `blocker` | string | for `addDependency` and `removeDependency` | The piece or draft to wait on, by id or tracker key, looked up in the piece's own project. `removeDependency` also takes the key of a tracker issue that is not a piece. |

Returns `{ok, pieceId, phase, gate}` after the action, plus `prURL` for `createPR`, `started` for `runCodeReview`, `sessionId` for `requestChanges`, `next` and `message` for `sendBackToAgents`, `started` and `message` for `resumeTask`, `next` and `message` for `editTaskBrief`, `messageTask` and `answerTaskQuestion`, and `isArchived` for `archive` and `unarchive`. `addDependency` and `removeDependency` return `{ok, pieceId, kind, dependsOn, waiting, blockingKeys}` after the edit, plus `phase` and `gate` for a piece.

The "Legal in" column names the phase the piece must be in, as the rail shows it. Within Agents, "the plan" is the agent graph before it runs, and "finished" is a run whose agents have all ended.

| Action | What it does | Legal in | Tier |
| - | - | - | - |
| `interviewMessage` | Answers or moves the spec interview along. | Spec | runs on the call |
| `approveSpec` | Approves the spec. `manual` goes on to the strategy; `auto` runs the rest unattended. `loop` is refused. | Spec | runs on the call; `auto` waits for a card when the setting is on |
| `generateStrategy` | Writes the strategy again. | Spec once the spec is ready, and Strategy | runs on the call |
| `approveStrategy` | Approves the strategy and splits it into agents. | Strategy | runs on the call |
| `decompose` | Splits the work into agents again. | Agents, at the plan | runs on the call |
| `startExecution` | Starts the agents. | Agents, at the plan | runs on the call; waits for a card when the setting is on |
| `pauseAgents` | Stops starting new agents and lets running ones finish their turn. | Agents, running | runs on the call |
| `resumeAgents` | Resumes a paused run. | Agents, paused | runs on the call; waits for a card when the setting is on |
| `stopAgents` | Cancels running agents and parks the run paused. | Agents, running or paused | always waits for a card |
| `retryFailedAgents` | Recovers every failed agent at once, or the ones `taskIds` names. An agent whose session can be steered continues there; the rest start fresh. With `guidance`, every agent it touches gets your note: as its continue message, or in its fresh brief. An agent whose brief changed since its session ran always starts fresh. | Agents, paused or finished, with at least one failed agent | runs on the call; waits for a card when the setting is on |
| `editTaskBrief` | Rewrites the brief of an agent that failed or hasn't started, from `prompt`. Nothing starts: call `retryFailedAgents` (it starts the agent fresh on the new brief) or `resumeAgents` next. The agent's card shows the brief changed over MCP. Refused for an agent that is running or finished, and for the review step. | Agents, paused or finished | runs on the call; waits for a card when the setting is on |
| `messageTask` | Sends `text` to an agent's own session while it is idle or failed, as if you typed it in Fermata. A failed agent runs again with the turn, and its state, attempts and failure follow it. Refused while the session is working, waiting on you, or still setting up. | Agents, running, paused or finished | runs on the call; waits for a card when the setting is on |
| `answerTaskQuestion` | Answers the question an agent is waiting on with `text`. Tool approvals and plan approvals are refused: those stay yours. | Agents, running or paused | runs on the call; waits for a card when the setting is on |
| `continueToReview` | Moves a paused or finished run into review. Unfinished agents stay as they are and show in review as not completed. Refused while an agent is running. | Agents, paused or finished | runs on the call |
| `approveTask` | Approves one agent on the review checklist, including one that did not complete, which accepts the piece without that agent's work. | Review | runs on the call |
| `runCodeReview` | Starts a code review, while that Edge feature is on. | Agents, finished, and Review, while the worktree exists | runs on the call |
| `createPR` | Opens the pull request. If the push fails, the piece stays in the phase it was in. | Agents, finished, Review, and Done while the branch exists; never while the piece has a pull request that is not closed | runs on the call; waits for a card when the setting is on |
| `markDone` | Removes the worktree and completes the piece. | Agents, finished, and Review | always waits for a card |
| `confirmDone` | Acknowledges a completed piece as done. | Done | runs on the call |
| `setLane` | Moves the piece to another lane. Leaving Auto clears a pressed Play, and moving to Loop hands the piece to the Loop, which runs it while the project's Loop is playing. | Spec, Strategy, and Agents at the plan, while no interview turn or plan build is running | runs on the call |
| `requestChanges` | Starts a feedback session in the piece's worktree with your `text`, for the whole piece. | Review (not while the pull request is being created) and Done, while the branch or worktree exists | runs on the call |
| `sendBackToAgents` | Sends the agents a failed work review named back, each with the review's findings and your `guidance` in its brief. The piece lands paused; call `resumeAgents` next. | After a work review that failed agents | runs on the call |
| `resumeTask` | Hands one failed agent's findings, plus your `guidance`, back to that agent's own session, and starts a fresh session with its brief when the old one can't be resumed. Nothing else in the run moves. Once the agent commits, the work review runs again. It answers on start. One resume runs per piece at a time, and a second one is refused with the reason. | After a work review that failed agents | runs on the call; waits for a card when the setting is on |
| `archive` | Takes the piece off the board and Home without deleting anything. | A done piece, or any piece with nothing running; not on an archived piece | runs on the call |
| `unarchive` | Brings an archived piece back. | An archived piece | runs on the call |
| `addDependency` | Makes the piece or draft wait on `blocker`, with origin `manual`. Adding a link that exists changes nothing. Refused with a tool error when the link would create a loop ("That link would create a loop."), when the blocker is in another project, or once building has started. | Drafts, and pieces before the strategy is approved, while piece dependencies are on | runs on the call |
| `removeDependency` | Stops the piece or draft waiting on `blocker`. A waiting Auto or Loop item whose last unmet link this was starts on its own. | Any phase, while piece dependencies are on | runs on the call |

## `list_cues`

Lists what needs you right now, grouped exactly as the menu bar popover groups it. Read, runs on the call.

| Argument | Type | Required | Notes |
| - | - | - | - |
| `cwd` | string | no | A directory inside a Fermata project, such as your working directory. Scopes the result to that project. |

With `cwd` inside a project, inside a worktree under that project's folder, or inside a git worktree of the project's repository checked out somewhere else, every field covers only that project: the groups, `count`, `snoozedCount`, and `running`, and `multiProject` is false. Fermata resolves the directory the same way `list_pieces` and `list_sessions` do. When no project contains `cwd`, the result is empty, so a session in an unrelated repository shows nothing. Without `cwd`, the result is the same global set the menu bar popover shows. The call never fails over the directory.

Returns `{schema, project, count, groups, multiProject, snoozedCount, running}`. `project` is `{id, name}` when the result is scoped and null when it is global. `groups` always holds all three groups, in the popover's order: `requiresApproval` (Requires approval), `readyForReview` (Ready for review), and `readyToMerge` (Ready to merge), each as `{key, title, items}`, and an empty group is kept. `count` never includes running work, and snoozed items are left out and counted in `snoozedCount`. `multiProject` is true when the items come from more than one project.

Each item carries `target` (`{kind, id}`, where `kind` is `piece` or `session`), `group`, `reason`, `label` (the popover's wording), `title`, `projectName`, `sourceRef`, `prNumber`, `prChecksLine`, `since`, and `fingerprint`, which `snooze_cue` takes. Three more fields say what you can do about it:

* `primaryAction` is the one `piece_action` action that answers the item, or null when the item can only be opened. It is never a merge: an item in Ready to merge always has null here.
* `confirmAvailable` is true only for a Ready for review item whose piece has no open Work Review findings, so a piece with findings is opened rather than confirmed.
* `legalActions` is what `get_piece` would list for the piece, and empty for a session.

`running` is `{line, running, advancing, projectNames, pieces}`, where each piece is `{pieceId, title, projectName, progress}` and `progress` runs from 0 to 1.

## `snooze_cue`

Hides one item in every Fermata surface until its state changes, as Snooze does in the popover. A snooze lasts until Fermata quits. Write, runs on the call.

| Argument | Type | Required | Notes |
| - | - | - | - |
| `target` | object | yes | The item's `target` from `list_cues`. |
| `fingerprint` | string | yes | The item's `fingerprint` from `list_cues`. |

Returns `{snoozed: true, snoozedCount}`. When the item changed since you read it, nothing is snoozed and the call fails with "This cue changed; refresh", so a snooze can never hide a decision you have not seen.

## `reveal`

Opens a piece or a session in Fermata on the Mac, the way tapping its notification does. Write, runs on the call.

| Argument | Type | Required | Notes |
| - | - | - | - |
| `pieceId` | string | one of the two | The piece to open. |
| `sessionId` | string | one of the two | The session to open. |

Returns `{revealed: true}`.

## Opening pull requests for many pieces

There is no bulk tool. A client loops: call `list_pieces` for the project, keep the rows whose phase key is `complete` and whose `prURL` is null, and call `piece_action` with action `createPR` and no `title` or `body` for each one. Each call opens one pull request with text Fermata writes from that piece's diff, and a failure on one piece leaves it as it was and does not stop the others.

```json theme={null}
{"name": "list_pieces", "arguments": {"cwd": "/Users/you/code/app"}}
{"name": "piece_action", "arguments": {"pieceId": "<id of each complete piece without a prURL>", "action": "createPR"}}
```

## What a client cannot do

* **Merge a pull request.** Merging writes into a shared repository and cannot be undone, so it stays with you, in the app or on a paired phone.
* **Rewrite an agent's prompt on a paused run.** A rewrite there would race the brief the agent is about to get, so prompts are edited in the app before the run starts.
* **Set a base branch.** A piece branches from the project's base branch.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.