Skip to main content
Glama

taskops

A shared work board — milestones → cards → subtasks — for teams of coding agents working in parallel, with a human who decides. Zero runtime dependencies.

The truth is an append-only event log; the cache is disposable and the leases are not. Agents stay out of each other's way by mechanism, not by prompt: a lease (one row, one winner), a worktree (one directory each), a branch pinned to that directory for life. main is written by a person.

The CLI behaves like git: it connects, it never manages. Moving a card from the terminal does not exist — that is MCP. (v1 grew 35 management commands, each one a second way to do something the tools already did, and the two ways drifted.)

Why any of it is shaped this way: ARCHITECTURE.md. How to work in this repo: CLAUDE.md.

How it fits together

One server, many boards, one board per repo. Read this once and nothing below can be misread:

        ONE host, set up ONCE in its life            YOUR LAPTOP, per repo
   ┌──────────────────────────────────────┐
   │  taskops serve --root ~/boards       │      ~/code/tienda   ──┐
   │                                      │      ~/code/api      ──┼─ each joined
   │    ~/boards/tienda/   ← a board      │◀─────~/code/landing  ──┘   to one board
   │    ~/boards/api/      ← a board      │       (no ssh, ever)
   │    ~/boards/landing/  ← a board      │
   └──────────────────────────────────────┘
  • The host: one process, one port, every board you will ever make. You ssh into it exactly once, to install it and register your key.

  • A board: one directory on that host. Created from your laptop with taskops board create.

  • A repo: joined to one board. A clone carries the board's address (.taskops/board.json, committed), so taskops join is the whole step; taskops remote add covers a checkout that carries none.

  • Your agents: they never touch any of this — they talk to the board through the eleven MCP tools.

Related MCP server: cc-agent

Install

uv tool install taskops-cli        # or: pipx install taskops-cli · pip install taskops-cli

The PyPI distribution is taskops-cli; the command it installs is taskops. Install into the interpreter you will actually run init/join from: the git hooks pin sys.executable at that moment, so a python3 without taskops importable leaves commits un-stamped, silently.

The CLI

taskops init                              a local board in this repo
taskops join [<name>] [--invite <id>]     join a board, install the hooks
taskops remote add <url>                  the host this checkout operates, like git's origin
taskops remote git [--add]                the board's OWN git repository: the address to push to,
                                          printed to paste or wired here (never over your origin)
taskops serve                             host boards — the page, /git and each board's own repo.git
taskops server init                       bootstrap THIS host: its owner and their ssh key
taskops board create|ls|push|pull|rm      the boards on a host
taskops board visibility|forge            who may read one · which repo's team is enrolled
taskops invite <who>                      a single-use link
taskops revoke --key|--invite             a key or an invite stops working
taskops tidy                              remove worktrees whose work is in the trunk
taskops ui                                the dashboard: serve if needed, open the browser
taskops hook …                            internal: what the installed hooks call

Starting a board

taskops init                     # local: .taskops/board/ + 2 git hooks + .mcp.json

Joining a hosted one is bare, like every other verb — the host is recorded once and the key is discovered the way ssh discovers one:

taskops join                              # a clone: board.json carries the address, done
taskops join my-project --invite <id>     # first time by invite: it enrols your key too
taskops remote add https://host:8787      # no carried address? record the host once…
taskops join my-project                   # …and name the board
taskops join my-project                   # no key + public board: read-only window

Keys exist so tokens do not travel: what lands on disk is a session that renews itself, never a token anybody copies. Flags: --key <path> overrides the discovered key · --as <actor> when your unix user is not the principal's name · --discard-local when this repo already has a local board with events. The old full-URL form (taskops join "<url>?token=…") keeps working — boards joined before keys existed never rot.

A dev never types anything about GitHub. On a board that declared a forge (below), the owner's taskops board forge has already enrolled the team from their published ssh keys, so the bare taskops join above finds your key, signs a challenge with it and is in. No token of yours travels anywhere — there is no flag that would carry one.

Restart your Claude Code session after either — MCP servers load once, at session start, from .mcp.json.

Hosting — ONE server for ALL your projects

Set a host up once, ever. One process serves every board you will ever make — there is no server per project and no server per board. The author's host runs six boards on one port.

--root is the only thing to decide, and it is just a directory you pick on the server where the boards get stored. ~/boards below is an example, not a convention: any path works. Every immediate subdirectory of it IS a board, served at /<its name>:

~/boards/                     ← --root: you chose this path
├── server.sqlite             the host itself: who may sign in, and their ssh keys
├── allowed_signers           derived from it, whole, on every change
├── live.sqlite               the sessions this host has handed out
├── mi-proyecto/              ← a board, served at https://host:8787/mi-proyecto
│   ├── events.jsonl              THE TRUTH: append-only, this is the board
│   ├── cache.sqlite              derived — delete it and it rebuilds
│   ├── live.sqlite               who holds which card right now
│   └── repo.git                  the board's own git — created by the first push,
│                                 and it NEVER prunes a card branch
└── otro-proyecto/            ← another board, same process, same port
    └── …

Nothing else is in there, and nothing outside it is touched. To move the host to another machine you copy that one directory.

Three commands on the box, one time in its life. This is the only ssh in the design — after it, nothing on a host is ever administered over a shell:

ssh <host> 'pip install taskops-cli'
ssh <host> 'taskops server init --root ~/boards --key -' < ~/.ssh/id_ed25519.pub
ssh <host> 'taskops serve --root ~/boards --host 127.0.0.1 --port 8787'   # under pm2/systemd

server init writes server.sqlite + allowed_signers and makes YOU its owner; serve is the long-running process. It binds loopback on purpose — TLS and the public name are a reverse proxy's job.

Per project — no ssh, ever again

From your laptop, signed by the key server init registered. This is the part you repeat per repo; the host above is never touched again:

taskops remote add https://host:8787 [--replace]   # once per checkout
taskops board create [<name>]                      # defaults to the directory's name
taskops board push                                 # this repo's LOCAL board becomes that one
taskops join <name>                                # or: a teammate connects to an existing one
taskops board pull [<name>]                        # the reverse: it comes back down, verified by id
taskops remote git --add                           # and point git at the board's own repo

taskops remote git adds a remote called taskops — never origin, which is your own setup — plus a credential helper for that host. The push then authenticates with the ssh key you already have: git asks the helper (taskops hook credential), the helper mints a session from that key, and no token is written into .git/config. Run it with no --add to just print the address and the two lines to paste.

The host holds the git — GitHub is the copy

your worktree  ──git push──▶  the taskops HOST  ──best effort──▶  GitHub
 (every commit, via the           <root>/<board>/repo.git         the declared forge,
  post-commit hook)               THE history. Never prunes,      a projection nobody
                                  never a force, never a          reads the board from
                                  deletion.

The board's own git lives on the host at https://<host>/<board>/repo.git, and that is a real remote: git clone, git fetch and git push all speak to it (git smart-HTTP; the session token rides in HTTP Basic's password field, which is what the credential helper answers).

  • A read follows the board's visibility. A public board clones anonymously, with no credential and leaving no trace; a private one clones with the key you already joined with.

  • A push is a write. Only an enrolled principal may push — a dev: or an agent:; an anonymous push is refused at the door with a 401 naming taskops join.

  • Nothing is ever erased there. The receive door refuses a ref deletion and a non-fast-forward push, and there is no flag that opens either. So a tk-* branch is readable at its URL forever, including after its chapter lands and the branch is pruned everywhere else — which is the whole reason the host holds the history rather than mirroring somebody else's.

  • A board with no declared forge gets all of the above. Push, clone, the hosted window's diffs, the permanence: none of it needs a forge. The only thing it does not get is the outbound leg.

The outbound leg is the OWNER's, on the host, and it is opt-in. A declared forge (taskops board forge <owner>/<repo>) says whose team the board enrols; mirroring the code onward is a second, separate act, because it hands the host write access to that repo. Two things, once, on the box:

# 1. mint a deploy key WITH WRITE on <owner>/<repo> (GitHub → Settings → Deploy
#    keys) and install its private half where the host's user can read it
# 2. on the host, name the forge as a remote inside the board's own git:
git -C <root>/<board>/repo.git remote add forge git@github.com:<owner>/<name>.git

Those two are the last things anybody does on the box, and they are the owner's alone — nothing mints that key, discovers it, or asks a dev for it. A deploy key opens ONE repo, which is why it is not a token: revoke it on the forge and the leg is dead with the board untouched.

Then every push that lands on the host is pushed onward on a background thread. It is best effort and never a gate: a GitHub that is down cannot fail your push. It is also never silent — the outcome of the last mirror push rides on the board payload and the dashboard draws it as one MIRROR line, success included, so "nothing said" can never mean both up to date and the key expired a month ago. A forge declared with no forge remote reads as a failure naming that exact command.

A board's whole life, and what each step destroys

  taskops init         board create+push       board pull            board rm
 ┌──────────┐        ┌──────────────┐       ┌──────────────┐      ┌──────────────┐
 │ a LOCAL  │  ───▶  │ LIVE on the  │  ───▶ │ a SNAPSHOT   │ ───▶ │ off the host │
 │  board   │        │     host     │       │ back in here │      │  altogether  │
 └──────────┘        └──────────────┘       └──────────────┘      └──────────────┘
  destroys            destroys nothing:      destroys nothing:     DESTROYS the host's
  nothing             the local board is     the host keeps its    board — the only step
                      RENAMED to .taskops/   board byte for byte   that destroys anything,
                      board.local-<date>     and goes on moving    and it says so in the
                                                                   name of its own flag

Both transfers flip this checkout's config last: stream the history, prove every event id arrived, then change what the repo reads. A failure above that leaves the repo as it was and the command is simply run again.

What a pull leaves you is a snapshot that stops moving — nothing syncs afterwards, so a card taken on the host a second later never appears here, and the command prints that sentence itself every time. remote.json keeps its login, so board create and board push still go to the same server.

And the admin surface for any board on that host, from anywhere:

taskops board ls
taskops board visibility <name> public|private     # owner only
taskops board rm <name>                            # owner only — see below
taskops board forge <owner>/<repo> [--need push|admin]   # owner only: declare AND sync the team
taskops board forge --clear                        # invite-only again
taskops invite <who> [--board <name>]
taskops revoke --key SHA256:… | --invite <id>      # a GitHub-enrolled key too

board rm removes the board's whole directory on the host — its event log and its repo.git with it — so it refuses unless this checkout already holds that history, and names both ways out — take the history down first, or say out loud that you are destroying it. The judgement is the host's, against the board's real event ids:

taskops board rm <name>                      # refused: 402 of the host's 402 events are not here
taskops board rm <name> --discard-history    # destroys it anyway

There is no --force and there will not be one: a flag that does not name what it overrides is how somebody destroys a history they meant to keep.

Declaring the forge — the repo whose team works on a board — is a board fact, op=forge with {host, repo: <owner>/<name>, need: push|admin}, absent until an owner records it and cleared again with --clear. A board that was never opted in is invite-only, exactly as before.

The board says so out loud. The declared forge rides on the board payload — derived per read from the one event that declared it, never a second copy — so anybody who can read the board can see what opens it, and the dashboard draws it under the board's own identity as github.com/<owner>/<repo> · push. Before that, the only two parties who knew were the owner who typed the command and the stranger the sync had not enrolled. A board with no forge sends no such key at all, which is what keeps every older reader working unchanged.

And declaring it SYNCS the team, in the same command. taskops board forge <owner>/<repo> lists that repo's collaborators with the declared access (one authenticated call to GitHub, paginated, with the owner's own token — gh auth token, else $GITHUB_TOKEN, else a hidden prompt), reads each one's published ssh keys from the PUBLIC https://github.com/<login>.keys, and enrols them all in one batch. Re-run it to re-sync; a run that changes nothing writes nothing.

bernatch22/taskops — 4 collaborator(s) with push
  enrolled  ana, dan, leo
  keys      3 added
  no ssh key published on GitHub — 1, not enrolled:
    mia            github.com/mia.keys is empty — taskops invite mia
  on this host but NOT a collaborator any more — 1, nothing revoked:
    tomas          taskops revoke --key SHA256:…
    a principal introduced by invite belongs here legitimately — revoking is yours

It adds only. Somebody who lost push is reported with the exact revoke command and nothing else happens: a principal introduced by an invite is not a GitHub login and a pruning sync would retire them for existing. The owner is never in that list. The token is spent on the collaborator pages and on nothing else — it never reaches the taskops host, which receives principals and ssh key lines and does not know what GitHub is.

The whole flow, and why cloning is not enough

Cloning the repo gives you the board's ADDRESS — .taskops/board.json is committed and travels with the code — but the host has never seen you: it is a different server from GitHub, sharing no session and no cookie with it. The owner's sync is what closes that gap, before you ever type anything, and then taskops join — no URL, no flag, no token — is the whole of your side.

        GitHub                                the board HOST
   <owner>/<repo>, private                principals + allowed_signers
          |                                          |
 0. taskops board forge <owner>/<repo>   ← the OWNER, once, from their laptop
    |                                                |
    |-- their own token (gh auth token, else $GITHUB_TOKEN, else a hidden
    |   prompt — never a flag value: the shell writes those into
    |   ~/.zsh_history before the process starts) lists the collaborators
    |   with <need>, and github.com/<login>.keys — PUBLIC — gives their keys
    |                                                |
    |-- POST /rpc members.enroll ------------------->|
    |      { members: [{principal, keys}, …] }       |
    |                                    it writes two rows per person:
    |                                      principals:      <them>, member
    |                                      allowed_signers: <them> ssh-ed25519 …
    |
    the token dies with that command. It reaches neither disk nor the host.
          |                                          |
 1. git clone  ->  the code, and .taskops/board.json (the address).
                   remote.json is 0600 and gitignored: no credential travels.
          |                                          |
 2. taskops join   (the carried address, and the key ssh already discovered)
    |                                                |
    |-- POST /login: your key signs a challenge ---->|
    |                            checked against allowed_signers -> 12h session

    from here on GitHub never participates again, and it never saw you join:

    every session:  your key signs a challenge  ->  the host checks it
                    (~/.ssh/id_ed25519)             against allowed_signers
                                                    -> a 12h session

The alternative — the host re-checking GitHub, or each dev POSTing their own token to be verified at the door — would mean somebody's credential travelling for a fact the owner already holds. That is the whole category of problem this removes: there is no token to steal because there is none stored, and now none that leaves the owner's machine either.

One consequence, stated plainly: access is granted automatically and taken back by hand. Losing push on the repo does not close the board, because the credential is no longer GitHub — it is the enrolled key. Remove it with taskops revoke --key SHA256:…, which is the same verb an invite-enrolled key takes.

No URL and no --key after remote add: the host is recorded in the checkout, board create records the name, and the key is discovered the way ssh discovers one — ~/.ssh/id_ed25519, id_ecdsa, id_rsa, in that order.

Shared flags on the board/invite/revoke verbs: --key <path> overrides the discovered key (on revoke it is --sign-key, since --key there is the fingerprint being retired) · --as <principal> names who the key belongs to · --root <dir> is the break-glass path that runs against the files ON the box, for the day the server is down or the owner's key is lost.

<host>/<name> also works anywhere <name> does — the URL form, as in git.

Public means GitHub's thing: anonymous READ, a write that always needs a registered key, no third state. Anyone may then taskops join <url> with no invite — a read-only join that mints nothing and registers no key.

After a verified push there is exactly ONE source.taskops/board/ is renamed to .taskops/board.local-<date>, a dead archive nothing reads again, and there is no --force on a push either.

The eleven MCP tools

The only management interface. Every tool takes repo_path= and actor=.

taskops_board      THE pulse: what the board is waiting for, grouped by the move
                   each card needs. Open every turn with this
taskops_card       one card in full — spec, thread, graph, collisions, worktree;
                   or query=<text> to search titles and specs
taskops_plan       the whole tree in ONE call: a milestone and its cards, deps
                   included. `after`/`parent` take an index into this call
taskops_assign     assign cards, cut a worktree each, return a brief per card
taskops_merge      integrate DONE cards into the milestone branch (--no-ff);
                   milestone= lands a finished chapter. main is never touched
taskops_take       claim your card and get everything back
taskops_update     change the CARD: close, hand in for review, hand back, drop,
                   retitle, re-spec, re-prioritise, declare a dependency
taskops_review     the verifier's one door: claim a submitted card, then
                   verdict=pass|changes note=…
taskops_comment    say something on ANY card, including one somebody else holds
                   and a closed one. mentions=[…] addresses it to them — on an
                   OPEN card: a closed thread delivers nothing
taskops_activity   a whole chapter's story in ONE read: every card's standing,
                   commits with numstat, where it merged, the reports filed on
                   it. since=<seq> returns only what moved; depth=full adds each
                   spec and thread. Never a diff — follow branch and sha into git
taskops_filed      register a report you already COMMITTED under
                   .taskops/reports/: path, title, sha. The board keeps the
                   pointer, never the prose

plan, assign and merge are the orchestrator's (dev:<name>); take is a worker's (agent:<dev>/<name>). Reading and commenting are open to everyone — only taking, closing and releasing belong to the holder.

Three states are stored — open, done, dropped. ready, doing, blocked, stalled, review, reviewing, changes and mention are all derived per read, which is why there is no recover verb and no mark-as-read.

Reports — the narration a machine cannot regenerate

A report is what an agent understood, and until now it died in a chat transcript. It joins the board the way a commit does: the file lives in git, the board holds a pointer. Four steps, in this order, and the order is the whole design — the file is committed BEFORE it is registered, because a pointer to bytes that are not in history yet is a pointer to nothing.

1. read the chapter    taskops_activity milestone=ms-… depth=full
2. write the file      .taskops/reports/<something>.html   (or .md, .txt)
3. COMMIT it           git add + git commit — in your own worktree
4. register it         taskops_filed path=… title=… sha=<that commit> milestone=ms-…

Then taskops ui lists it under the chapter's Reports tab and renders it full width, read out of your own clone at that sha — the local dashboard never asks the server for the bytes. A host running taskops serve answers /git too, from the board's OWN git (<root>/<board>/repo.git, the same history your git push landed there) — the hosted window, for the reader with no clone. No forge is involved: a board nobody has pushed to yet refuses with a sentence naming the two ways in, and one commit from a joined worktree ends that state.

The hosted page is at the board's OWN address. https://<host>/<board>/ IS the dashboard — not a sub-path under it — and the machine doors sit under a prefix that can never collide with a page asset:

https://<host>/<board>/            the page          (also /<board>, no slash)
https://<host>/<board>/app.js      its assets        style.css, index.html
https://<host>/<board>/api/rpc     the verbs         also /<board>/rpc
https://<host>/<board>/api/git/…   diffs from repo.git     also /<board>/git/…
https://<host>/<board>/repo.git    the board's own git — clone, fetch, push
https://<host>/<board>/api/feed    the live feed     also /<board>/feed
https://<host>/healthz             the host itself

The right-hand spellings are 0.5.0's and they keep answering, unprefixed and un-redirected — including /<board>/ui/, which was the page's address for one day. Links were pasted, agents and the MCP client are configured against them, and taskops ui's upstream forward speaks them, so they are a contract now rather than a legacy. Re-derivable at any time with sh smoke.sh <host> <board>.

Reading one, from the other side. Everything above is the author's half; a reader needs no ceremony at all. Three doors onto the same bytes:

taskops ui                             # the Reports tab: the chapter's list, rendered
taskops_activity milestone=ms-…        # the same list as data: {path, title, sha}
                                       # newest first, with the honest total beside it
git pull && $EDITOR .taskops/reports/<name>.md    # it is a committed file, nothing more

Which one you want depends on what you are: a human wants the tab, an agent wants activity and then opens the file in its own worktree. There is no read_report tool and there is not going to be one — the bytes are already in the clone, and a tool that returned them would be a second way to do what opening a file does, with the whole chapter's prose pushed through context.

The one failure worth naming: the report renders blank or 404s when your clone does not have that sha yet — the pointer is fine, your git is behind. git fetch --all and reload. The board deliberately cannot help you here; it never had the bytes.

The rules that shape it, each of them the reason a step exists:

  • The log stores a reference, never the prose. The report event body is {path, title, milestone, sha} and nothing else, so a 200KB report grows events.jsonl by a few hundred bytes. Same rule that keeps diffs out of the log: a commit is recorded as a sha and a numstat, never a patch.

  • .taskops/reports/ is a shape, not a convention. core/reports.py::under() is the one place that decides whether a path is a report path, and both ends ask it — the verb that registers one and the /git door that later reads it. A traversal, an absolute path or the bare directory is refused, never repaired. The door is for reports; it is not a file server.

  • A report is untrusted HTML, and it is read in a sandbox. It renders inside <iframe sandbox="allow-scripts" srcdoc=…>. Scripts run — a panorama report is a self-contained page and rendering it dead ships a broken document — but never beside allow-same-origin, which together are not two permissions but the absence of the sandbox. The frame gets an opaque origin: no parent, no localStorage, no cookie. The dashboard's token is in that origin, so this is a boundary and not a preference. A Markdown report is served as text/markdown and rendered by the dashboard's own markdown renderer (ui/src/markdown.ts) — it emits no HTML, so it cannot run anything and needs no frame. A text/plain report is not framed at all.

  • The list is a fold, never a table. "Which reports does this chapter have" is answered from the report events on every read, newest first, capped with the honest total beside it.

Developing

uv run ruff check src tests       # lint
uv run pyright                    # types, strict
uv run pytest                     # the whole suite
cd ui && npm ci                   # once
cd ui && npm run check            # typecheck + build + smoke + committed-bundle diff
uv run python -m taskops.cli ui   # the dashboard, token included

The dashboard is built, not hand-written: source in ui/, and node build.mjs writes the bundle into src/taskops/ui/, which is committed — that is what makes pip install taskops serve a dashboard with no node toolchain.

tests/test_architecture.py pins the layering by AST — imports only point down, SQL only in store/, subprocess only in gitwork/run.py, the clock only in _clock.py and core/hours.py, 200 lines per module. A rule with no test is a suggestion.

Available Tools

11 tools
taskops_activityA

The whole story of a chapter in ONE read: every card's standing, commits (with numstat), where it merged, and what was reported — milestone=ms-… or tasks=[tk-…]. since= returns only what moved; depth=full adds each spec and thread. No diffs: follow branch and sha into git yourself.

ParametersJSON Schema
NameRequiredDescriptionDefault
actorNowho is speaking, when it is not the session's own identity. Sub-agents share the session's ONE MCP server, so a spawned worker MUST pass the agent:<dev>/<name> its brief names on EVERY taskops call — without it the board hears the orchestrator.
depthNoheadline (default): standing, commits with numstat, merged_into, notes, thread_total — 76 cards fit in ~90KB. full: adds each card's spec, criteria, files and whole thread — ~13KB per card.
sinceNoa seq from a previous answer — only cards that moved since come back. Every answer carries seq; send it back next time.
tasksNoexactly these cards instead, in the order given (any chapter)
milestoneNoms-… — the whole chapter; default: the single open one
repo_pathNoanother project's board, by any path inside it. Default: the board this server started in. The host runs ONE MCP server per session, pinned to the directory it opened, so without this a second project is unreachable and the work leaves through curl instead of the tools.

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the burden. It discloses what is returned (standing, commits with numstat, merged_into, notes), how depth changes output, and that diffs are not included. However, it does not mention side effects (likely none but not stated), auth requirements, or rate limits, and it doesn't explicitly confirm read-only behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences pack a lot of value: the first gives a clear overview, the second explains filters and depth, the third sets a critical limitation. There is zero fluff and every phrase earns its place, making the description appropriately sized for a complex read tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Without an output schema, the description must communicate return value essence, which it does by enumerating card standing, commits, merge info, and reports. The schema covers parameter details thoroughly, so the description need not repeat them. Minor gaps remain (e.g., error behavior or how to interpret seq) but the overall package is solid.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% so the baseline is 3, but the description adds meaningful layer: 'since=<seq> returns only what moved' and 'depth=full adds each spec and thread' reinforce the semantics. The milestone/tasks filter explanation also helps, going slightly beyond the raw schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it provides 'the whole story of a chapter in ONE read' including cards, commits, merge locations, and reports. While it lacks a direct verb like 'list' or 'get', the intent is unambiguous and the content distinguishes it from sibling tools like taskops_board or taskops_card.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly covers when to use it (for a comprehensive chapter view), how to limit scope (milestone, tasks), and how to do incremental reads (since=<seq>). The 'No diffs' note tells users to go to git for diffs, acting as a clear exclusion. It doesn't name alternative sibling tools, but the guidance is practical.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

taskops_assignA

Assign cards to workers, cut one worktree each, and return a paste-ready brief per card. Spawn one sub-agent per brief, all in one message. Orchestrator only.

ParametersJSON Schema
NameRequiredDescriptionDefault
actorNowho is speaking, when it is not the session's own identity. Sub-agents share the session's ONE MCP server, so a spawned worker MUST pass the agent:<dev>/<name> its brief names on EVERY taskops call — without it the board hears the orchestrator.
tasksYesthe cards to hand out
workersNonames for them; default w1, w2, … (the free ones)
repo_pathNoanother project's board, by any path inside it. Default: the board this server started in. The host runs ONE MCP server per session, pinned to the directory it opened, so without this a second project is unreachable and the work leaves through curl instead of the tools.
worktreesNocut one worktree per card (default true)

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description must carry the burden. It discloses mutating actions (assigning cards, cutting worktrees) and sub-agent spawning, but lacks detail on reversibility, permissions, or failure behavior. It gives core behavior without deep consequences.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, front-loaded with the main action, no redundant words. Efficiently packs the workflow into a readable format.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is complex (multi-step, sub-agent spawning) and there's no output schema. The description mentions returning paste-ready briefs but not their structure or additional side effects. It's adequate but lacks depth for a task of this complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

All parameters have schema descriptions (100% coverage), so the description doesn't need to add parameter info. It mentions 'cut one worktree each' which aligns with the worktrees parameter, but adds no new semantics beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's function: assign cards to workers, cut worktrees, return paste-ready briefs, and spawn sub-agents. The verb 'assign' and specific actions distinguish it from sibling tools like taskops_take or taskops_update.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Orchestrator only' provides explicit context on who should call it, and 'spawn one sub-agent per brief' implies it's for delegation workflows. However, it doesn't name alternative tools or specify when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

taskops_boardA

THE pulse: what the board is waiting for, grouped by the move each card needs (MERGE, MENTIONS, REVIEW, CHANGES, STALLED, TAKE, DOING, REVIEWING, BLOCKED). Open every turn with this.

ParametersJSON Schema
NameRequiredDescriptionDefault
tzNotimezone the days and months are cut in, e.g. Europe/Madrid (default UTC)
actorNowho is speaking, when it is not the session's own identity. Sub-agents share the session's ONE MCP server, so a spawned worker MUST pass the agent:<dev>/<name> its brief names on EVERY taskops call — without it the board hears the orchestrator.
windowNohours over "7d" (the last N calendar days), "month" (this month so far), "2026-07" (that calendar month) or "total" (the whole log)
milestoneNoms-… one chapter, * the whole board; default: the open one
repo_pathNoanother project's board, by any path inside it. Default: the board this server started in. The host runs ONE MCP server per session, pinned to the directory it opened, so without this a second project is unreachable and the work leaves through curl instead of the tools.

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burd of behavioral disclosure. "The pulse of what the board is waiting for" strongly implies a read-only, aggregated status view, but the description does not explicitly state that no changes are made or describe how the snapshot behaves under empty or stale states.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no filler: the first says what kind of information is returned and how it is grouped; the second says exactly when the agent should call it. Each sentence earns its place and the key usage rule is brief and memorable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description supplies the purpose, grouping model, and calling frequency for a board view meaning no required params and a fully described schema. It could say more about the exact shape of the returned pulse, but it gives enough for an agent to know whether and why to call it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description itself adds no parameter-level information, but schema description coverage is 100%, covering the meaning of timezone, actor identity, window, milestone, and repo path. This the baseline-3 case where the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the board as an informational pulse of what each card needs, grouping by moves like MERGE, MENTIONS, REVIEW, and BOCKED. This makes the tool's role distinct from the action-oriented sibling tool names, though it lacks an explicit operation verb such as 'list' or 'fetch'.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

"Open every turn with this" is an explicit, strong when-to-use instruction and implies it should come before the individual action tools. It does not list when-not-to-use cases or alternatives, but the guidance is clear and actionable.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

taskops_cardA

One card in full — spec, the whole thread, the graph, file collisions, its worktree. Or query= to search titles and specs.

ParametersJSON Schema
NameRequiredDescriptionDefault
taskNotk-…
actorNowho is speaking, when it is not the session's own identity. Sub-agents share the session's ONE MCP server, so a spawned worker MUST pass the agent:<dev>/<name> its brief names on EVERY taskops call — without it the board hears the orchestrator.
queryNosearch titles and specs instead
repo_pathNoanother project's board, by any path inside it. Default: the board this server started in. The host runs ONE MCP server per session, pinned to the directory it opened, so without this a second project is unreachable and the work leaves through curl instead of the tools.

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the behavioral burden. It clearly discloses the return scope (full card with spec, thread, graph, file collisions, worktree) and the search fallback, which strongly implies a read-only operation. It does not mention error behavior or auth, but the read intent is well conveyed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, front-loaded with the primary purpose and a list of contents. Every phrase adds useful information; there is no filler or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description is readable and informative for a retrieval tool, but it omits the expected relationship between task and query (e.g., whether they are mutually exclusive) and does not explain behavior when neither is provided. Since there is no output schema, the lack of return-format details is also a gap, though the explicit list of included data partially compensates.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description only restates the query behavior already in the schema ('search titles and specs') and adds no extra meaning for task, actor, or repo_path beyond the schema's own detailed descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with 'One card in full' — a specific verb+resource — and enumerates the full contents (spec, thread, graph, file collisions, worktree). It also distinguishes a second mode (query search) and implicitly separates this tool from siblings like taskops_board or taskops_activity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage: use it to view one card in full, or use query to search titles/specs. However, it never explicitly states when to prefer this over sibling tools, nor does it explain consequences of omitting both task and query.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

taskops_commentA

Say something on ANY card — including one somebody else holds, on another team, and a closed one (the log is append-only; a postscript is welcome, and it does not reopen it). mentions=[…] addresses it to them and reaches them on their very next call — on an OPEN card: a closed card delivers nothing, so address the living card instead. THE channel between agents in parallel: when your files meet theirs, say so on their card.

ParametersJSON Schema
NameRequiredDescriptionDefault
taskYestk-… — ANY card, including one somebody else holds and a closed one (only mentions= need an OPEN card to be delivered)
textYeswhat you want to say. The thread is never truncated.
actorNowho is speaking, when it is not the session's own identity. Sub-agents share the session's ONE MCP server, so a spawned worker MUST pass the agent:<dev>/<name> its brief names on EVERY taskops call — without it the board hears the orchestrator.
mentionsNoaddress it to somebody: dev:<name> or agent:<dev>/<name>. They see it in the pulse line of their very next call, and it clears itself when they write on the card — there is nothing to mark as read.
repo_pathNoanother project's board, by any path inside it. Default: the board this server started in. The host runs ONE MCP server per session, pinned to the directory it opened, so without this a second project is unreachable and the work leaves through curl instead of the tools.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full behavioral burden — and it delivers. It discloses that closed cards accept append-only postscripts without reopening, that mentions only deliver on open cards and clear automatically upon the recipient's next write, that the thread is never truncated, and that sub-agents must pass an explicit actor to avoid the board hearing the orchestrator. These are non-obvious side effects an agent needs to call the tool correctly.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but every sentence earns its place: the primary function, closed-card semantics, mention delivery, actor identity caveat, and repo_path purpose. It is front-loaded with the key action and packs critical edge cases into a few sentences without fluff. The structure with colons and semicolons keeps it scannable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 5 parameters, no output schema, and no annotations, the description covers all critical usage nuances: mention delivery only on open cards, the actor requirement for sub-agents, repo_path for multi-project scenarios, and the append-only thread behavior. There is no output schema to explain, and the description addresses every parameter's practical implication, leaving no operational gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the schema descriptions are already rich (e.g., task explains any card, mentions explains delivery). The description adds extra meaning beyond the schema: it explains why actor matters for sub-agents ('without it the board hears the orchestrator') and why repo_path is needed ('the host runs ONE MCP server per session ... without this a second project is unreachable'). This adds genuine value beyond the structured fields.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with 'Say something on ANY card' — a specific verb and resource — and immediately distinguishes it from sibling tools by emphasizing it works on closed cards, others' cards, and other teams. It clearly positions taskops_comment as the generic commenting tool, unlike taskops_update (which likely mutates card fields) or taskops_assign (which changes ownership). The purpose is unambiguous and differentiates from siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit when-to-use context: 'THE channel between agents in parallel: when your files meet theirs, say so on their card.' It also warns about closed cards for mentions ('a closed card delivers nothing, so address the living card instead'). However, it does not explicitly contrast with alternatives (e.g., 'use taskops_update for structured edits'), so it stops short of the highest bar for explicit when-not guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

taskops_filedA

Register a report you already COMMITTED under .taskops/reports/: path=, title=, sha=, milestone= (default: the single open chapter). The board stores the pointer, never the prose — every reader renders it from its own clone.

ParametersJSON Schema
NameRequiredDescriptionDefault
shaYesthe commit that carries the file at that path — required
pathYesthe COMMITTED file, e.g. ".taskops/reports/chapter-close.md"
actorNowho is speaking, when it is not the session's own identity. Sub-agents share the session's ONE MCP server, so a spawned worker MUST pass the agent:<dev>/<name> its brief names on EVERY taskops call — without it the board hears the orchestrator.
titleYeswhat it is called in the list — required
milestoneNoms-… it narrates; default: the single open chapter
repo_pathNoanother project's board, by any path inside it. Default: the board this server started in. The host runs ONE MCP server per session, pinned to the directory it opened, so without this a second project is unreachable and the work leaves through curl instead of the tools.

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden of behavioral disclosure. It does add valuable context with 'The board stores the pointer, never the prose — every reader renders it from its own clone,' which explains the storage model beyond the schema. Yet it leaves unspecified whether registration is idempotent, what happens on duplicate paths, and what output or errors are returned.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is exactly two sentences: the first compactly packs the required parameters and the prerequisite into a single line, and the second explains the pointer-based storage model. Every clause is purposeful with no filler or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The core concept is well covered: the tool requires an existing commit, stores only a pointer, and renders from each reader's clone, with a sensible milestone default. It does not discuss output/return behavior or error cases, but for a simple registration operation with fully documented parameters this is a minor gap rather than a critical one.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and each parameter already has a descriptive comment, so the description's inline list 'path=, title=, sha=, milestone=' adds no new semantic detail beyond restating names. The milestone default is also repeated from the schema, so the description does not elevate parameter understanding.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with an explicit verb ('Register') and a specific resource ('a report you already COMMITTED under .taskops/reports/'), immediately clarifying that this tool records a commit pointer rather than storing content. This operationally distinguishes it from siblings like taskops_card or taskops_review, which handle different board actions.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly states the prerequisite (the report must already be committed) and notes the milestone default ('the single open chapter'), giving the agent a concrete condition for when to use this tool. However, it does not name alternative tools or explicitly say when not to use it, so it stops short of full exclusion guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

taskops_mergeA

Integrate DONE cards into their milestone branch (--no-ff, in the integration worktree): task= one, tasks=[…] those in order, done=true every card waiting under MERGE. A batch stops at the first failure, reports per card, and continues on a re-run. A conflict aborts clean. main is never touched. Orchestrator only.

ParametersJSON Schema
NameRequiredDescriptionDefault
doneNointegrate every card the board groups under MERGE (done, not integrated), in that group's order. Re-run it after a stop: it continues where it left off.
noteNowith milestone= criteria_met=false: REQUIRED — which criteria are unmet and why landing is still right. It lands on the record beside the answer.
taskNoa DONE card → into its milestone branch
actorNowho is speaking, when it is not the session's own identity. Sub-agents share the session's ONE MCP server, so a spawned worker MUST pass the agent:<dev>/<name> its brief names on EVERY taskops call — without it the board hears the orchestrator.
tasksNointegrate exactly these DONE cards, in the order given — each through the same single-card path. Stops at the first failure and reports per card.
milestoneNoms-… → land the WHOLE milestone into the trunk. Refused while any card of it is open or unintegrated. The human's call — never do this with raw git in the shared checkout; the board must record the landing.
repo_pathNoanother project's board, by any path inside it. Default: the board this server started in. The host runs ONE MCP server per session, pinned to the directory it opened, so without this a second project is unreachable and the work leaves through curl instead of the tools.
criteria_metNowith milestone=: the human's answer to its criteria — recorded, never judged. true, or false with note= saying which are unmet and why landing is still right (a criterion that can only be checked after the trunk moves). Omitted, a chapter with criteria is refused and shown them.

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

There are no annotations, so the description carries the full disclosure burden. It states the failure semantics (a batch stops at the first failure, reports per card, and continues on re-run), describes conflict behavior, and asserts a strong safety guarantee ('main is never touched').

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The definition is compact and information-dense, with five short sentences, each adding a new behavioral or imperative detail. Nothing is filler, and the primary action is front-loaded in the first sentence.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 8-parameter mutating tool with no output schema, the description covers the main invocation modes, failure behavior, retry semantics, and a key safety property. It does not describe the return/report format in detail, but it names 'reports per card' and the schema covers the remaining conditions like milestone and criteria_met.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the scoring baseline is 3. The coverage provides useful grouping of the modes, but most parameter-level semantics are already in the schema; the description adds little new meaning beyond that.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence names a precise action and resource: integrate DONE cards into their milestone branch, and adds technical specificity with --no-ff and the integration worktree. This clearly distinguishes the tool from the other taskops siblings such as taskops_update or taskops_comment.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives concrete invocation modes (one task, ordered tasks, all cards under MERGE), plus how a stopped batch should be re-run. It also restricts use to the 'orchestrator only', but does not explicitly compare against alternative tool names or name when not to use the tool, so it stops just short of top-level guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

taskops_planA

Write the tree in ONE call: a milestone and its cards, dependencies included. after and parent take an index into this call's tasks. Orchestrator only.

ParametersJSON Schema
NameRequiredDescriptionDefault
goalNoWHY this milestone exists — it travels into every take
actorNowho is speaking, when it is not the session's own identity. Sub-agents share the session's ONE MCP server, so a spawned worker MUST pass the agent:<dev>/<name> its brief names on EVERY taskops call — without it the board hears the orchestrator.
rulesNowhat holds for EVERY card of this chapter, e.g. ["Decimal, never float", "no migrations in this milestone"]. Shown above the spec in every take: a rule read after building is a rewrite.
tasksYesthe cards, in order
reviewsNochapter default: cards get review=true — OPTIONAL; a per-card review= wins
criteriaNowhat the CHAPTER is accepted against — every card can be green while the milestone is not. Shown at taskops_merge milestone=, refused until answered.
milestoneNoa title to open a chapter, or an existing ms-… id
repo_pathNoanother project's board, by any path inside it. Default: the board this server started in. The host runs ONE MCP server per session, pinned to the directory it opened, so without this a second project is unreachable and the work leaves through curl instead of the tools.
union_filesNothe SEAM files every card of this chapter appends to — a registry, a table, an index, e.g. ["src/app/registry.py"]. Sibling conflicts in THESE paths union-merge during catch-up; every other conflict still refuses.

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, behavior is conveyed through the definition as a whole: atomic single-call creation, ordering semantics, review precedence ("the card's own value always wins"), collision behavior ("sibling conflicts in THESE paths union-merge... every other conflict still refuses"), and the identity trap ("without it the board hears the orchestrator"). The top-level description is terse, but the parameter descriptions carry the behavioral disclosure burden well; it does not describe what happens on dependency cycles or partial failure.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences with zero waste: the core operation and scope are front-loaded, the critical dependency-index semantics follow, and the role restriction closes. Every sentence earns its place, and nothing is repeated from the schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 9-parameter creation tool with no annotations and no output schema, the definition is nearly complete: the schema descriptions explain goal, identity, review defaults, conflict-resolution rules on the seam files, and precedence. The missing pieces — return value/result of a successful call, failure mode for invalid indices or cycles, sync between the index semantics and the tree — are gaps, but not clarity-blocking ones.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all nine parameters, which is equally the baseline of 3. The top-level description's note on the index semantics mostly restates what the property cannot be transformed into, so it adds qualified value. The parameter descriptions themselves are exemplary (priority scale 0-3, precedence rules, example lists), but the tool description is not what provides that benefit.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource — "Write the tree in ONE call: a milestone and its cards, dependencies included." — making the batch-planning scope unmistakable. It implicitly distinguishes itself from siblings through "ONE call" and "Orchestrator only", but it never names a sibling like taskops_card, so the differentiation is implicit rather than explicit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The definition implies when to use the tool — the whole milestone-and-cards tree at once, from the orchestrator only — and the schema adds strong guidance (repo_path warns about unreachable second projects, actor warns about identity confusion). But it never states explicit when-not conditions or directs the agent to a sibling (e.g., taskops_card for a single card), so the routing guidance is implied rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

taskops_reviewA

THE verifier's one door: taskops_review task=… CLAIMS a submitted card (one verifier per card, full dossier back, the worker's lease untouched); with verdict=pass|changes and note= it judges it — the note reaches the worker verbatim. You may never judge your own work.

ParametersJSON Schema
NameRequiredDescriptionDefault
noteNorequired with a verdict — what was checked, or what to change. The worker is shown it verbatim.
taskYesa submitted tk-… (its card has review=true)
actorNowho is speaking, when it is not the session's own identity. Sub-agents share the session's ONE MCP server, so a spawned worker MUST pass the agent:<dev>/<name> its brief names on EVERY taskops call — without it the board hears the orchestrator.
verdictNopass: ready for the orchestrator to close. changes: back to the worker. Omit it to CLAIM the review and read everything first.
repo_pathNoanother project's board, by any path inside it. Default: the board this server started in. The host runs ONE MCP server per session, pinned to the directory it opened, so without this a second project is unreachable and the work leaves through curl instead of the tools.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description discloses important behaviors: 'one verifier per card' (exclusivity), 'full dossier back' (return info), 'the worker's lease untouched' (no impact on worker), 'note reaches the worker verbatim' (note transparency), and the self-review ban. This is substantial context beyond the schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences and front-loads the tool's purpose. It uses cryptic capitalization and punctuation, but every clause adds information. It could be clearer on the two-step process.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has no output schema and no annotations, so the description must cover behavior. It explains the claim vs judge modes, the exclusivity, the dossier return, and the self-review rule. However, it doesn't detail the structure of the 'full dossier' or error conditions, but for a 5-param tool with schema descriptions, it's reasonably complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description adds meaning to key parameters: task is the submitted card, verdict accepts pass|changes, and note is passed verbatim. The schema already has detailed descriptions for all 5 parameters (100% coverage), so the description builds on that by explaining the workflow.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies this as the verification/review tool: 'THE verifier's one door' and explains it claims a submitted card and judges it with verdict=pass|changes. It distinguishes implicitly from siblings by being the only review tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states the workflow: claim a card (task=...) and then judge with verdict and note. It adds a key constraint: 'You may never judge your own work.' However, it doesn't explicitly compare to alternatives beyond calling itself the 'one door', but the workflow is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

taskops_takeB

Claim your card and get everything back: the milestone's goal, the spec, the whole thread, the previous worker's note, collisions, your worktree. Workers only.

ParametersJSON Schema
NameRequiredDescriptionDefault
specNowith title=: what done means
taskNotk-… — yours; empty takes what is assigned to you
actorNowho is speaking, when it is not the session's own identity. Sub-agents share the session's ONE MCP server, so a spawned worker MUST pass the agent:<dev>/<name> its brief names on EVERY taskops call — without it the board hears the orchestrator.
filesNowith title=: the edit surface
titleNocreate AND claim a card you found mid-work
labelsNorouting and search hints, e.g. ["backend", "urgent"]
criteriaNowhat this card is accepted against — the other half of the spec. The worker is shown these right under it; closing says which were met and what proves it.
milestoneNowith title=: which chapter it belongs to
repo_pathNoanother project's board, by any path inside it. Default: the board this server started in. The host runs ONE MCP server per session, pinned to the directory it opened, so without this a second project is unreachable and the work leaves through curl instead of the tools.

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses that claiming returns a bundle of information (goal, spec, thread, notes, collisions, worktree) and restricts use to workers, which adds useful behavioral context given no annotations. However, it does not mention the side effect of claiming (e.g., assigning the card to the caller, possibly locking it), leaving a transparency gap.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence that front-loads the core action ('Claim your card') and then lists the returned items compactly. It is efficient with no obvious fluff, though the long list makes it slightly dense. The structure is appropriate for the information conveyed.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has nine parameters, no output schema, and no annotations, the description is under-specified. It omits the create-and-claim functionality implied by the title parameter, does not describe the return format in a usable way, and fails to explain conditional parameter usage. The description covers only the most basic claim action, leaving substantial gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema covers all nine parameters with detailed descriptions (e.g., actor explains sub-agent MCP sharing, repo_path explains host pinning), so the schema itself provides strong parameter meaning. The tool description adds no parameter-specific information, meeting the baseline for high schema coverage but not exceeding it.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses the concrete verb 'Claim' and identifies the resource as 'your card', and it lists specific returned artifacts (milestone goal, spec, thread, etc.). This clearly conveys the tool's primary function. However, it does not explicitly differentiate this from sibling tools like taskops_assign or taskops_update, so the distinctiveness is not fully highlighted.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'Workers only' gives a clear audience restriction, and 'Claim your card' implies the main use case. But it does not state when to use this tool instead of alternatives, nor does it mention the create-and-claim behavior described for the title parameter. Guidance is implied rather than explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

taskops_updateA

Change the CARD: close it (done needs a commit, or no_code=true), hand it in for review (status=review on a card that requires it), hand it back (status=released, note= how far you got), drop it (note= why), retitle, rewrite the spec or criteria, re-prioritise, declare a dependency. To say something: taskops_comment.

ParametersJSON Schema
NameRequiredDescriptionDefault
goalNowith milestone= and no task=: rewrite the goal
noteNowhy THIS status change — released and dropped require it, and the next worker is shown a released note verbatim. To just say something, or to address somebody, use taskops_comment.
specNorewrite the spec
taskNotk-…
actorNowho is speaking, when it is not the session's own identity. Sub-agents share the session's ONE MCP server, so a spawned worker MUST pass the agent:<dev>/<name> its brief names on EVERY taskops call — without it the board hears the orchestrator.
afterNotk-… this card waits for
filesNoreplace the edit surface
rulesNowith milestone= and no task=: replace the chapter's rules, whole
titleNorename
labelsNorouting and search hints, e.g. ["backend", "urgent"]
reviewNothis card must pass review before it closes (flip after planning)
statusNodone needs a commit (or no_code); review hands the card in for its verdict (note= says what you did); released needs a note; dropped needs a reason
no_codeNoclosing with no commit — say what happened instead
reviewsNowith milestone= and no task=: change the chapter's review DEFAULT — it applies to cards planned after it, never retro-flags one
criteriaNowhat this card is accepted against — the other half of the spec. The worker is shown these right under it; closing says which were met and what proves it.
priorityNo0 urgent … 3 idle
milestoneNomove the card — or, with no task=, update the milestone
repo_pathNoanother project's board, by any path inside it. Default: the board this server started in. The host runs ONE MCP server per session, pinned to the directory it opened, so without this a second project is unreachable and the work leaves through curl instead of the tools.
union_filesNowith milestone= and no task=: replace the chapter's union seam files, whole

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With zero annotations, the description carries the full behavioral burdens and it does provide balance: it says what statuses preconditions exist (done needs a commit or no_code, released/dropped require a note) and that a released note is shown verbatim to the next worker. Where it falls short is on the bigger side effects: it never states whether changes are permanent, whether they can be undone, or what the mutation notices to the board.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is construct, frontloaded with the core mutation point and each clause serves a distinct purpose — status transitions, field rewrites, and the cross-reference to taskops_comment — no filler. It loses a half-point because the long comma-separated gut of status → field mutations is more dense and harder to parse than a short list or bullets, but ever sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 19-parameter write tool without annotations or an output schema, the description covers the most common modes but silently omiss some entire axes: card moves via milestone (tool), multi-project routing via repo_path, the all-important actor claim for sub-agents, along with resources-maintain fields like files and union_files. The schema patches most of these gaps with rich parameter descriptions, but a reader of the description along the surface offeature-uncovering would need to open every field to find them.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already documents all 19 parameters with clear semantic descriptions, so the bar is at baseline-3. The description reinforces status conditions (e.g. done needs a commit, released needs a note) but those largely duplicate the schema's restat and note descriptions rather than adding new parameter-level meanIng. It provides adequate, not exceptional, additive value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description leads with 'Change the CARD' — a specific verb and a clear resource — and then enumerates the concrete mutations: close, hand in for review, hand back, drop, retitle, rewrite spec/criteria, re-prioritize, and declare a dependency. It also distinguishes itself from at least one sibling by routing trivial messaging to taskops_comment, so the agent can visibly tell the tools apart.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear when-to-use context: it states welkwhat operations are supported and attaches conditions (done needs a command or no_code=true, review-on-a-card-that-requires-imb, released needs a not, dropped needs a reason). It explicitly says 'To say something: taskops_comment,' which is an honest exclusion, but it does not disambiguate among the other mutation siblings like taskopsinate, taskops_review, or taskops_assign, so it falls short of a full decision-guide.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 5 tool updatesv0.4.2
    • Changedtaskops_board3 fields changed
      • changedInput schema / properties / milestone / description
        Previous value: -"ms-… to focus one chapter; default: the open one"New value: +"ms-… one chapter, * the whole board; default: the open one"
      • changedInput schema / properties / tz / description
        Previous value: -"timezone for those days, e.g. Europe/Madrid (default UTC)"New value: +"timezone the days and months are cut in, e.g. Europe/Madrid (default UTC)"
      • changedInput schema / properties / window / description
        Previous value: -"hours over the last N calendar days, e.g. \"7d\""New value: +"hours over \"7d\" (the last N calendar days), \"month\" (this month so far), \"2026-07\" (that calendar month) or \"total\" (the whole log)"
    • Changedtaskops_comment1 field changed
      • changedInput schema / properties / task / description
        Previous value: -"tk-… — ANY open card, including one somebody else holds"New value: +"tk-… — ANY card, including one somebody else holds and a closed one (only mentions= need an OPEN card to be delivered)"
    • Changedtaskops_merge2 fields changed
      • changedInput schema / properties / criteria_met / description
        Previous value: -"with milestone=: the human's answer to its criteria — recorded, never judged"New value: +"with milestone=: the human's answer to its criteria — recorded, never judged. true, or false with note= saying which are unmet and why landing is still right (a criterion that can only be checked after the trunk moves). Omitted, a chapter with criteria is refused and shown them."
      • addedInput schema / properties / note
        Added value: +{
        +  "description": "with milestone= criteria_met=false: REQUIRED — which criteria are unmet and why landing is still right. It lands on the record beside the answer.",
        +  "type": "string"
        +}
    • Changedtaskops_plan1 field changed
      • addedInput schema / properties / union_files
        Added value: +{
        +  "description": "the SEAM files every card of this chapter appends to — a registry, a table, an index, e.g. [\"src/app/registry.py\"]. Sibling conflicts in THESE paths union-merge during catch-up; every other conflict still refuses.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
    • Changedtaskops_update1 field changed
      • addedInput schema / properties / union_files
        Added value: +{
        +  "description": "with milestone= and no task=: replace the chapter's union seam files, whole",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
  2. 11 tool updatesv0.1.0
    • First observedtaskops_activity
    • First observedtaskops_assign
    • First observedtaskops_board
    • First observedtaskops_card
    • First observedtaskops_comment
    • First observedtaskops_filed
    • First observedtaskops_merge
    • First observedtaskops_plan
    • First observedtaskops_review
    • First observedtaskops_take
    • First observedtaskops_update

TDQS

A3.8/5.0
Disambiguation4/5

Most tools have clearly distinct purposes: board gives the current state, activity gives history, card gives a single card's full details, and update/comment/review/merge/take/assign/plan/filed each target a specific workflow step. There is minor overlap between board and activity as both provide overviews, but descriptions clarify the current vs historical focus.

Naming Consistency3/5

All tools share the consistent 'taskops_' prefix, but the suffixes mix nouns (card, board, activity) and verbs (update, plan, assign, merge, take, review, comment, filed). 'filed' is a past tense verb, which is unusual. The pattern is not uniform, but the names are still readable and context helps.

Tool Count5/5

With 11 tools, the server is well-scoped for a task management system. Each tool addresses a specific part of the workflow (planning, assigning, executing, reviewing, merging, reporting), and none seem redundant or unnecessary.

Completeness4/5

The tool set covers the core lifecycle: plan creates milestones/cards, assign and take manage work, update and comment handle changes, review verifies, merge integrates, and filed reports results. Minor gaps exist, such as no explicit delete/archive (though 'drop' may serve) and no separate tool to list all workers, but these are not critical to the main workflow.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    MCP server that spawns autonomous Claude Code agents in GitHub repos, enabling task delegation with persistent state, multi-step workflows, and job monitoring.
    47
    94
    2
    Apache 2.0
  • A
    license
    Not graded
    quality
    D
    maintenance
    MCP server for a kanban task board that lets Claude Code manage tasks with priority, categories, and multi-agent safety, plus a web UI for visual drag-and-drop.
    3
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    MCP server for inter-agent communication. Gives multiple Claude Code sessions a shared message board, agent registry, and orchestration layer — backed by a cloud relay so agents can coordinate across machines, repos, and teams.
    8
    53
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/bernatch22/taskops'

If you have feedback or need assistance with the MCP directory API, please join our Discord server