taskops
A shared work board server for coordinating coding agent teams, structured around milestones and cards. It supports planning, assignment, execution, review, integration, and reporting with these tools:
Board pulse (
taskops_board): get a prioritized view of what the board needs grouped by action (MERGE, REVIEW, TAKE, etc.).Plan work (
taskops_plan): create milestones with goals, rules, and cards — including specs, dependencies, priorities, review requirements, and file surfaces.Assign cards (
taskops_assign): hand out cards to workers, auto-create one git worktree per card, and deliver paste-ready briefs.Claim and start a card (
taskops_take): retrieve full context (spec, thread, collisions, worktree path) for an assigned card, and optionally create new cards mid-work.Update state (
taskops_update): change card status (done, review, dropped, etc.), retitle, re-spec, prioritize, declare dependencies, or update milestone-level settings.Review work (
taskops_review): claim submitted cards, then pass or request changes with notes; self-review is prohibited.Merge work (
taskops_merge): integrate done cards into milestone branches or land entire milestones into the trunk.Comment (
taskops_comment): post on any open card and mention agents to notify them, the primary coordination channel.Inspect / search cards (
taskops_card): get full details of a card (spec, thread, dependencies, collisions) or search across titles and specs.Chapter activity (
taskops_activity): see a milestone’s complete story — card standings, commits, merge locations, and filed reports — with depth and incremental options.Register reports (
taskops_filed): link committed report files to a milestone for dashboard access.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@taskopsClaim the next task and start."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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), sotaskops joinis the whole step;taskops remote addcovers 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-cliThe 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 callStarting a board
taskops init # local: .taskops/board/ + 2 git hooks + .mcp.jsonJoining 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 windowKeys 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/systemdserver 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 repotaskops 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 anagent:; an anonymous push is refused at the door with a401namingtaskops 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>.gitThose 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 flagBoth 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 tooboard 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 anywayThere 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 yoursIt 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 sessionThe 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 proseplan, 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 itselfThe 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, renderedtaskops_activity milestone=ms-… # the same list as data: {path, title, sha}
# newest first, with the honest total beside itgit pull && $EDITOR .taskops/reports/<name>.md # it is a committed file, nothing moreWhich 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
reportevent body is{path, title, milestone, sha}and nothing else, so a 200KB report growsevents.jsonlby 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/gitdoor 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 besideallow-same-origin, which together are not two permissions but the absence of the sandbox. The frame gets an opaque origin: no parent, nolocalStorage, no cookie. The dashboard's token is in that origin, so this is a boundary and not a preference. A Markdown report is served astext/markdownand 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. Atext/plainreport is not framed at all.The list is a fold, never a table. "Which reports does this chapter have" is answered from the
reportevents 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 includedThe 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 toolstaskops_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.
| Name | Required | Description | Default |
|---|---|---|---|
| actor | No | who 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. | |
| depth | No | headline (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. | |
| since | No | a seq from a previous answer — only cards that moved since come back. Every answer carries seq; send it back next time. | |
| tasks | No | exactly these cards instead, in the order given (any chapter) | |
| milestone | No | ms-… — the whole chapter; default: the single open one | |
| repo_path | No | another 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
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| actor | No | who 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. | |
| tasks | Yes | the cards to hand out | |
| workers | No | names for them; default w1, w2, … (the free ones) | |
| repo_path | No | another 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. | |
| worktrees | No | cut one worktree per card (default true) |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| tz | No | timezone the days and months are cut in, e.g. Europe/Madrid (default UTC) | |
| actor | No | who 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. | |
| window | No | hours over "7d" (the last N calendar days), "month" (this month so far), "2026-07" (that calendar month) or "total" (the whole log) | |
| milestone | No | ms-… one chapter, * the whole board; default: the open one | |
| repo_path | No | another 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
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| task | No | tk-… | |
| actor | No | who 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. | |
| query | No | search titles and specs instead | |
| repo_path | No | another 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
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| task | Yes | tk-… — ANY card, including one somebody else holds and a closed one (only mentions= need an OPEN card to be delivered) | |
| text | Yes | what you want to say. The thread is never truncated. | |
| actor | No | who 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. | |
| mentions | No | address 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_path | No | another 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
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| sha | Yes | the commit that carries the file at that path — required | |
| path | Yes | the COMMITTED file, e.g. ".taskops/reports/chapter-close.md" | |
| actor | No | who 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. | |
| title | Yes | what it is called in the list — required | |
| milestone | No | ms-… it narrates; default: the single open chapter | |
| repo_path | No | another 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
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| done | No | integrate 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. | |
| note | No | with milestone= criteria_met=false: REQUIRED — which criteria are unmet and why landing is still right. It lands on the record beside the answer. | |
| task | No | a DONE card → into its milestone branch | |
| actor | No | who 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. | |
| tasks | No | integrate exactly these DONE cards, in the order given — each through the same single-card path. Stops at the first failure and reports per card. | |
| milestone | No | ms-… → 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_path | No | another 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_met | No | 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. |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| goal | No | WHY this milestone exists — it travels into every take | |
| actor | No | who 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. | |
| rules | No | what 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. | |
| tasks | Yes | the cards, in order | |
| reviews | No | chapter default: cards get review=true — OPTIONAL; a per-card review= wins | |
| criteria | No | what the CHAPTER is accepted against — every card can be green while the milestone is not. Shown at taskops_merge milestone=, refused until answered. | |
| milestone | No | a title to open a chapter, or an existing ms-… id | |
| repo_path | No | another 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_files | No | 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. |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| note | No | required with a verdict — what was checked, or what to change. The worker is shown it verbatim. | |
| task | Yes | a submitted tk-… (its card has review=true) | |
| actor | No | who 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. | |
| verdict | No | pass: ready for the orchestrator to close. changes: back to the worker. Omit it to CLAIM the review and read everything first. | |
| repo_path | No | another 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
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| spec | No | with title=: what done means | |
| task | No | tk-… — yours; empty takes what is assigned to you | |
| actor | No | who 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. | |
| files | No | with title=: the edit surface | |
| title | No | create AND claim a card you found mid-work | |
| labels | No | routing and search hints, e.g. ["backend", "urgent"] | |
| criteria | No | what 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. | |
| milestone | No | with title=: which chapter it belongs to | |
| repo_path | No | another 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
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| goal | No | with milestone= and no task=: rewrite the goal | |
| note | No | why 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. | |
| spec | No | rewrite the spec | |
| task | No | tk-… | |
| actor | No | who 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. | |
| after | No | tk-… this card waits for | |
| files | No | replace the edit surface | |
| rules | No | with milestone= and no task=: replace the chapter's rules, whole | |
| title | No | rename | |
| labels | No | routing and search hints, e.g. ["backend", "urgent"] | |
| review | No | this card must pass review before it closes (flip after planning) | |
| status | No | done 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_code | No | closing with no commit — say what happened instead | |
| reviews | No | with milestone= and no task=: change the chapter's review DEFAULT — it applies to cards planned after it, never retro-flags one | |
| criteria | No | what 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. | |
| priority | No | 0 urgent … 3 idle | |
| milestone | No | move the card — or, with no task=, update the milestone | |
| repo_path | No | another 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_files | No | with milestone= and no task=: replace the chapter's union seam files, whole |
TDQS
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.
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.
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.
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.
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.
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.
5 tool updates
v0.4.2- Changed
taskops_board3 fields changed- changed
Input schema / properties / milestone / descriptionPrevious value: -"ms-… to focus one chapter; default: the open one"New value: +"ms-… one chapter, * the whole board; default: the open one" - changed
Input schema / properties / tz / descriptionPrevious 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)" - changed
Input schema / properties / window / descriptionPrevious 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)"
- Changed
taskops_comment1 field changed- changed
Input schema / properties / task / descriptionPrevious 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)"
- Changed
taskops_merge2 fields changed- changed
Input schema / properties / criteria_met / descriptionPrevious 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." - added
Input schema / properties / noteAdded 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" +}
- Changed
taskops_plan1 field changed- added
Input schema / properties / union_filesAdded 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" +}
- Changed
taskops_update1 field changed- added
Input schema / properties / union_filesAdded value: +{ + "description": "with milestone= and no task=: replace the chapter's union seam files, whole", + "items": { + "type": "string" + }, + "type": "array" +}
11 tool updates
v0.1.0- First observed
taskops_activity - First observed
taskops_assign - First observed
taskops_board - First observed
taskops_card - First observed
taskops_comment - First observed
taskops_filed - First observed
taskops_merge - First observed
taskops_plan - First observed
taskops_review - First observed
taskops_take - First observed
taskops_update
TDQS
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.
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.
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.
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
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
Task & board management for AI agents + humans. Kanban, comments, digests via MCP.
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
AI-native Kanban board — connect Claude to claim, work and move your tasks over MCP.
Control plane for autonomous software labor. Agents claim objectives over MCP with audit trail.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceLocal MCP server for Claude Code providing persistent memory, task planning, and agent coordination with full transparency and no network calls.2MIT
- AlicenseAqualityBmaintenanceMCP server that spawns autonomous Claude Code agents in GitHub repos, enabling task delegation with persistent state, multi-step workflows, and job monitoring.47942Apache 2.0
- AlicenseNot gradedqualityDmaintenanceMCP 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.3MIT
- AlicenseAqualityDmaintenanceMCP 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.853MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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