feature-tracker-mcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| feature_proposeA | Record a feature, guardrail, schema change, risk or mitigation so it is not lost. The goal is created if it does not exist, and the id is allocated atomically by the database, so concurrent sessions cannot collide on a number. Only record what would otherwise be lost, is actionable, and is not already tracked -- check feature_list first. |
| feature_listB | List tracked items, lowest priority number first. Use before proposing, to avoid duplicates. |
| feature_updateA | Change a tracked item: status, title, body or priority. Every change is recorded in the append-only history, stamped with the git commit it was made against. |
| feature_historyB | The append-only record: what changed, when, by whom, and against which git commit. This is the audit trail that replaces git history for the tracker itself. |
| gate_raiseA | Raise a decision the working session must not take alone: an architectural choice, an install, a spend, or anything irreversible. The session should stop and wait -- this is how 'this costs $40, are you good with that' becomes a queued question rather than a message someone had to be present to catch. |
| gate_listC | Decisions awaiting a human. Read-only; costs no work. |
| gate_decideB | Approve or reject a pending gate, unblocking the session that raised it. |
| tracker_statusA | Counts by status and goal, pending gates, and which database and tree were read. Progress is two numbers -- done and tracked -- never a ratio: the denominator growing means real work was found, and a percentage would report that as regression. |
| goal_listA | Categories with their priority, parallelism cap, and item counts. Every feature must belong to one — an uncategorised item is one nobody picks up. Check here before proposing, so a near-duplicate goal is not created alongside an existing one. |
| goal_setB | Set a goal's priority and how many of its features may be worked at once. Parallelism is capped per goal rather than by token budget: the limit that matters is how many things are changing simultaneously. |
| goal_pruneA | List categories holding no features, and optionally remove them. Defaults to a dry run: a goal with work is never removed, and Miscellaneous is always kept. |
| feature_linkA | Record that one feature depends on another. Priority order is meaningless without this: the highest-priority item may be blocked, and handing it to a worker wastes the worker. |
| feature_unlinkB | Remove a dependency between two features. |
| feature_readyA | What can be worked right now: not done, nothing it depends on outstanding, and no gate open on it — in goal-priority then feature-priority order. This is what a worker pulls from. Returns skipped_pending_a_gate ALONGSIDE the ready list: a gate clears only when the principal answers it, so the worker skips those and works the rest rather than stalling a whole goal on one question — but it must SAY SO out loud, because silently working around a blocked item looks exactly like having finished the goal. |
| feature_blockedC | What is waiting, and on what. The mirror of feature_ready. |
| parity_setA | Record whether a feature is covered in one dimension — code, unit tests, functional tests, documentation, builds, infrastructure. Work is only done when it is done in every dimension; tracking code alone lets the rest drift silently. |
| parity_gapsB | Coverage by dimension: how many features are unknown, missing, partial or satisfied. The cheap probe's target list — it decides where to spend effort, and is not itself the fix. |
| parity_scanA | Run the cheap probe for one dimension across every feature and record the result. parity_gaps only reads; this is what makes the states real. A probe decides where to spend effort and is not itself the fix, so it is deliberately narrow: it records what was checked in each row's detail, because 'the id is not mentioned' must never be mistaken for 'the work is not done'. Probes exist for documentation and code; the others need a real check — a build, an applied migration — rather than a reference search. |
| feature_claimA | Take a feature to work on, if nobody else holds it. The claim is a LEASE with an expiry, not a flag: a worker that dies holding a flag blocks its feature forever, whereas a lease runs out and the work returns to the pool. Claim before starting, or two workers take the same item and you find out via a merge conflict. |
| feature_releaseA | Give up a claim, returning the feature to the pool. |
| worker_heartbeatA | Report that a worker is alive and extend its leases. Silence is what 'stale' means, so a worker that stops heartbeating has its claims expire and its work picked up by someone else. Call this every few minutes while working. |
| worker_listA | Workers, how long since each was heard from, whether it is stale, and how many features it holds. An idle worker and a working one look identical without this. |
| directive_issueA | Broadcast stop, pause, resume or rescan to every worker. Broadcast rather than addressed, so a worker that starts after the directive was issued still sees it — the case a point-to-point message silently misses. Scope it to a goal, or omit for all. |
| directive_pollA | Directives this worker has not acknowledged. Poll between units of work and obey what comes back: stop means finish the current step and stop, pause means stop and wait for resume. |
| directive_ackA | Acknowledge a directive so it stops being returned to this worker. |
| standupA | Cross-track state in one call: counts, blocked, pending gates, worker liveness, and every worktree's uncommitted work. Reads working trees, not just commits — measured on this project, every worktree reported zero commits ahead while two held real uncommitted work, so a standup built on git history alone calls active tracks idle. |
| study_openA | Open an investigation whose deliverable is a document and a decision, not code. Use when a question needs real analysis before anything can sensibly be built — whether an effect is real, which of two designs survives contact with the data, whether something is worth doing at all. A study is NOT a feature: it has no acceptance criteria, and it may correctly conclude 'do not build this'. |
| study_listB | Studies with what each spawned, killed or informed. Check before opening one — an already-answered question does not need answering twice. |
| study_showC | One study and every feature it touched — the provenance view. |
| study_concludeA | Record a study's recommendation and the document it produced. 'Do not build this' is a successful conclusion, not a failure; so is 'abandoned' when the question stopped mattering. Link the features it spawned or killed with study_outcome before concluding. |
| study_outcomeB | Record that a study spawned, killed or informed a feature. 'killed' matters as much as 'spawned': a study that closes work off is doing its job, and without the link the reason a feature was dropped disappears — leaving it to be re-proposed by someone who never saw the study. |
| study_statusB | Move a study between open, in_progress, concluded and abandoned. |
| checkpointA | Record everything agreed in one design session, in a single transaction. A design conversation produces features, risks, data sources and decisions together and they only make sense together; recording them one call at a time leaves a half-captured design if anything fails, and nothing afterwards can tell which rows came from that sitting. Duplicates are reported rather than skipped or forced — being told 'three of your fourteen already exist' is information the design session should see. |
| goal_refineA | Record a goal's objective after a refinement session with the principal. A goal carrying only a name and a priority is a filing label: nothing in it says what is being attempted, so a worker cannot judge whether a feature actually serves it. Do NOT call this mid-discussion — record once, when consensus is reached. |
| goal_showA | One goal in full — objective, what done means, what is explicitly excluded, constraints — with its item counts. A worker should read this before starting, so it can tell whether what it is about to build actually serves the goal. |
| goal_unrefinedA | Goals with no objective or no definition of done, ordered by how much work they already hold. These cannot be reasoned about: work under them is being ordered without anything saying what it is for. Refine the ones holding the most first. Each row carries its doc_ref where one is known, so the refine pass reads that section rather than searching the tracker markdown for it once per goal. |
| study_designA | Record the method agreed with the principal, BEFORE execution. This is pre-registration and it is the point of the design phase: a method chosen after seeing the data can be selected — consciously or not — for the answer it produces. Call this once, at consensus, and do not execute a study that has no method recorded. Revising a method later is allowed and is counted, because a silently revised method is indistinguishable from a fitted one. |
| goal_defineA | Create a goal that does not exist yet, at the END of a definition session. The name comes out of the conversation rather than going into it — nobody should have to invent an identifier before working out what the thing is. Follow immediately with goal_refine to record its objective. Check goal_list first: a near-duplicate goal fragments the queue. |
| goal_membershipB | Everything filed under a goal, for re-testing membership once its objective is agreed. Imported features inherited their goal from which document heading they sat under — a filing location, not a judgement that the item serves the objective, because at import time there was no objective to test against. Run this after refining a goal that already holds work. |
| feature_reassignA | Move a feature to a different goal. The id never changes, so anything citing it in a commit message or worktree name still resolves; the move is recorded in the history with its reason. Use when a refined objective shows an item does not belong where it was filed. |
| gate_queueA | Every pending decision, oldest first, shaped to be answered in one sitting rather than as interruptions. Carries age, what each gate blocks, the options and the raiser's recommendation — a gate that only asks is a gate that gets deferred. Use this for the periodic question round; it records that each gate was put to the principal. |
| gate_decide_batchA | Answer several gates at once, after a question round. Each decision applies independently and is reported separately: answering nine of eleven is a normal outcome, and one bad id must not throw away eight good answers. |
| derive_featuresA | Derive a feature checklist for a goal from the documentation and existing features, and put it straight in the backlog at 'proposed' — recorded, not yet agreed. Defining a goal must produce work, not just an objective. Call project_boundaries FIRST: re-proposing something already refused wastes a review round and teaches the principal that the queue does not learn. Candidates matching an existing feature are reported rather than created. |
| derive_pageC | A page of a derivation still awaiting review. Deliberately small — a long list gets skimmed, and a skimmed checklist is worse than none because it looks reviewed. |
| derive_reviewA | Review backlogged features: promote to 'agreed', reassign, or drop. Rejection means two different things — 'wrong_goal' is a routing error and the feature is still wanted, so it is MOVED not dropped; 'not_wanted' is a decision about the project. A rejection REQUIRES a rationale: accumulated rationales are how the project defines what it is not, and 'no' without a reason cannot be reasoned from. |
| project_boundariesA | What this project is NOT: goals' stated non-goals, plus every refusal with its reasoning. The accumulated negative definition — boundaries nobody wrote into a goal statement but which were decided one refusal at a time. Read before deriving or proposing anything. |
| derive_listC | Derivations and how far each review has got. |
| goal_refine_batchA | Refine several goals in one call. Drafting is derivable from each goal's own documentation, so the expensive part is the handful of genuine decisions, not a sitting per goal. Read the source document ONCE and slice it by heading — re-reading it per goal is the same file four times. Draft the lot, record the lot with doc_ref so the next pass has a pointer instead of a search, and raise the questions that remain as gates. |
| feature_refine_batchA | Set acceptance criteria on many features at once. Most are derivable from the body, the code and the docs, so doing them one at a time spends a round trip per item on work that needed no decision. Anything genuinely undecidable should become a gate rather than a guess. |
| feature_unrefinedB | Open features with no acceptance criteria — the work list for a refine pass. Until a feature says what done looks like, 'done' is whoever-built-it's opinion. |
| db_backupA | Dump the project's tracker to .oz/backups and verify it. Take one before any bulk change — a refine pass, a restore, a migration. A dump restores anywhere, unlike a copy of the data directory, and the dump is checked before being reported as a backup: an unverified backup is a file, not a backup. |
| db_backupsB | Backups on disk, newest first. |
| db_restoreA | Restore a backup over the live tracker. DESTRUCTIVE and irreversible: it takes a safety backup first and refuses without confirm: true. Restoring the wrong file over a working tracker is the mistake with no undo. |
| confer_recordA | Record an exchange with a peer model as its own act. Use for a diff review before a feature is marked done — a worker cannot both review its own work and close it in one call, so the review has to exist first — and for any conferral worth keeping that is not attached to another write. The subject must already exist. |
| confer_historyB | What a subject has been through with a peer, newest first. Omit both filters for the whole project. Read this before re-litigating something — an argument already had and settled is on the record here. |
| confer_digestB | Whether the peer channel is earning its place: where it changed the answer, and where it could not settle something. Both halves are reported, because showing only the first would make the mechanism unfalsifiable. |
| gate_reconcileA | Re-check a pending gate against the tree as it is now. A gate freezes its question at the moment it was raised and nothing re-reads it, so work that lands afterwards can answer it, invalidate its premise, or build the very thing it asks whether to build -- and it goes on being asked, because the row still says pending. Run this over every pending gate before putting any of them to the principal. 'moot' closes it as settled (never as a decision they did not take, and reversible with gate_reopen); 'repose' rewrites the question and resets asked_count. Both require evidence naming a path or a commit. |
| gate_reopenB | Pull back a gate the pair settled. Auto-settling is only safe because it is reversible: two models can be confidently wrong together, and the principal finding that out later needs a lever, not an argument. Reopened gates come back as hard. |
| gap_scanA | Everything needed to reason about coverage, in one read: every goal's objective, done-means, non-goals and constraints in its own words, what each holds, and every settled refusal. Read-only. This is the input to gap analysis — derive_features asks what ONE goal implies and so can only find work inside a goal somebody already wrote; this asks what the whole set fails to cover, which is the only way a MISSING goal is ever found. Returned unsummarised on purpose: a gap is noticed by reading the actual wording, and does not survive being condensed into counts. |
| derive_gapsA | Record what a gap analysis found. Feature gaps land in the backlog at 'proposed' under one proposal, so derive_page/derive_review work on them unchanged. Goal gaps become HARD gates: creating a goal reshapes what every feature hangs off, and gate_reopen cannot unwind it once work routes in, so it stays the principal's however well the pair agrees. Call gap_scan first and check every candidate against the refusals it returns — a settled refusal is a decision, not an oversight. Finding nothing is a real outcome; record it as one rather than manufacturing candidates. |
| feature_unblockedA | What a recently answered gate has released. Answering a gate changes a gate row and nothing else, so work it was holding stays invisible unless something looks — this is what a worker calls on resuming. Read each decision_note before starting: it is the answer the work was waiting on. |
| oz_shutdownA | Wind the project down and leave it resumable. Broadcasts stop, then stashes every uncommitted change in every worktree — untracked files included — and records where, tying each stash to the feature it belongs to. Does NOT wait for workers: waiting on one that may not poll again turns a wind-down into a vigil, and anything written afterwards is caught by the next run. Use force:true to also release every open claim, which is the 'kill it' form — deliberate, because releasing a live worker's claim invites two workers onto one feature. |
| stash_listA | Work interrupted by a shutdown and not yet restored, newest first. Each names the worktree it came from — a stash only applies in the tree it was taken in. |
| stash_restoreA | Put interrupted work back. Applied by sha rather than by position, and the stash entry is applied rather than dropped — so a restore that conflicts can be retried or abandoned without the work having evaporated. Refuses if the target worktree is already dirty: stacking a stash on top mixes two sets of half-finished work with no way to separate them afterwards. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |