MCP Task Orchestrator · Field guidePlate 7 of 9

Ask the graph what to do next

Agents read state far more often than they change it. A handful of read calls answer the questions a session actually has: where was I, what is next, why is this stuck, and what does this item need.

Which call answers which question

The questionThe callWhat comes back
Where did we leave off?get_context(since="…")Active items, recent transitions with their actors, and stalled items.
Is anything unhealthy?get_context()Active, blocked and stalled items, plus a count of live and expired claims.
What does this item need?get_context(itemId="a3f2")Its gate status: which required notes exist, which are missing, and the guidance or skill for the next one.
What should I pick up?get_next_item()Ranked items that can start right now.
Why can't this start?get_blocked_items()
get_next_status(itemId)
Each blocker, the role it must reach, and whether that is satisfied. Or a one-item verdict: Ready, Blocked or Terminal.
What is under this feature?query_items(operation="overview", itemId)The item, its direct children, and a count of children per role.
Have we seen this before?query_items(operation="search", query="…")
query_notes(operation="search", query="…")
Relevance-ranked hits with snippets, across items or note bodies.
What must this note contain?query_items(operation="schema", itemId)The resolved schema with full description, guidance and skill for every note.

An item is stalled when it is in work or review and a required note for its current phase is still missing.

How the next item is chosen

A sample backlog, listed oldest first. Change the call and watch which items qualify and in what order.


    
RankItemPriorityComplexityOutcome

Ranking

By default: high, then medium, then low priority. Within a priority, lowest complexity first, with unset complexity last. oldest gives fair first-in, first-out draining.

What never appears

Items whose blockers have not reached their threshold, items another agent has claimed, and items under a claimed ancestor. includeClaimed lifts the two claim filters for operators.

Other roles

The default role is queue. A review fleet asks with role="review", a triage agent with role="blocked".

The fields on every item

FieldValuesWhat it drives
title, summaryUp to 500 and 2000 charactersWhat agents see in lists and search.
typeOne schema key, such as bug-fixSelects the schema, so the gates and the lifecycle mode.
tagsComma-separated, lowercase with hyphensFiltering, and schema selection when no type matches.
priorityhigh, medium (default), lowFirst key of the next-item ranking.
complexity1 to 10, optionalSecond key of the ranking, and the complexityMax filter.
traitsComma-separated trait namesExtra notes, seats, resources and dispatch for this one item.
parentIdAn item id, or none for a rootThe hierarchy. Depth is computed and has no fixed limit.

The role is not among them: it only changes through advance_item. Ids accept a prefix of four or more hex characters. An ambiguous prefix is an error. The server never guesses.

Read cheaply

Overview before detail

One overview call returns a feature, its children and per-role counts. That replaces a get per item plus their notes when all you need is status.

Note metadata first

query_notes lists notes without bodies by default and returns each body's length. Fetch a body only for the note you will read, filtered by role.

Search is ranked, not exact

Full-text search runs a substring index and a word-stem index and fuses the two rankings. Several words mean all of them. Scope it to a subtree, a role or tags.

One database, several projects

Project Atype: project feature bugs task task bug a project read: ancestorId = root A Project Btype: project feature tech debt Personaltag: personal-root quick task anchors new items, reads stay unscoped Session Retrospectivescontainer Improvement Proposalscontainer Retrospective Trendscontainer agent-observation itemseach its own root process-wide, outside every project
Every box in the top row is a root item at depth 0. A project root is an ordinary item of type project. Its id is the rootId that per-project config, plan documents and rules are stored under.

Set up a project

/task-orchestrator:init finds or creates the project root, writes project: { rootId, name } into the repo's .taskorchestrator/config.yaml, pushes the config and seeds the bundled rules.

Set up a personal root

init --user creates one root for every directory that has no config of its own. It gives new items a home. It does not narrow what reads return.

Scope every read

With a project root, agents pass ancestorId on query_items, get_next_item, get_context and get_blocked_items, and parent new top-level items under the root.