MCP Task Orchestrator · Field guidePlate 2 of 9
Every work item sits in one of five roles. Agents never edit status directly. They call advance_item with a trigger, and that call is where the server checks required notes.
start passes it. Two triggers are not drawn: complete jumps from queue, work or review straight to terminal and checks the required notes of every phase, and cancel jumps to terminal from any role that is not terminal, blocked included, with no check at all.A simplified model of the server's rules for one item, using the server's own error wording. Fire triggers in any order and read what comes back. The highlighted station above follows along.
type feature-task · no status label
| Trigger | From | To | Gate |
|---|---|---|---|
start | queue, work or review | the next role on the line | Required notes of the current phase |
complete | queue, work or review | terminal | Required notes of every phase. A blocked item must resume first. |
block / hold | any non-terminal | blocked | None. Saves the previous role. |
resume | blocked | the saved role | None |
cancel | any non-terminal | terminal | None. Sets the status label to cancelled. |
reopen | terminal | queue | Bypassed. A terminal parent goes back to work. |
The role is what the server reasons about. Alongside it, each transition sets a status label: display text for people and dashboards. The five roles never change. The labels can be renamed per project.
| Trigger | Default label |
|---|---|
start | in-progress |
complete | done |
block | blocked |
cancel | cancelled, always |
| a cascade | done |
resume | the label from before the block |
reopen | cleared, always |
status_labels: start: "working" complete: "finished" block: "on-hold" cascade: "auto-completed"
The label comes back on every transition result and on item queries. Filter and gate on the role. Show the label.
Every failure carries a kind that says whether retrying can help, and a code to branch on. An agent never has to parse the message text.
details, such as a gate's missing notes or the blockers of a dependency, and contendedItemId when another agent got there first.{
"error": {
"kind": "transient",
"code": "claim_contention",
"message": "Item already claimed by another agent",
"retryAfterMs": 420000,
"contendedItemId": "550e8400-…"
}
}
Write tools accept a requestId. The server remembers the response for that actor and id for about ten minutes and returns it again instead of running the call twice. claim_item requires one.
No response arrived, such as a timeout: resend with the same id. A response arrived, even a failure: use a fresh id, because the remembered failure would be replayed.