MCP server for ducklab, a project management and AI-assisted development platform
ducklab defines 17 tools with complete JSON schemas and descriptions. Naming follows verb_noun patterns (config_doctor, roster, status, run_get, decide, etc.). Most descriptions are substantive (100-300 chars), explaining WHAT the tool does and WHEN to use it. However, parameter descriptions are sparse or missing in several tools (e.g., roster's 'mode' and 'role' lack detail; answer's 'question_id' is vague). Output schemas are not documented, LLMs cannot predict response structure. Error handling is implicit (no recovery guidance in descriptions). Security-sensitive tools (decide, budget_lift, task_remove) lack permission/audit documentation. Composition is strong: tools chain well (run_get → decide → file_findings), and most accept natural identifiers (project_id, task_id). Overall: solid foundation with clear intent, but incomplete parameter guidance and missing output documentation limit LLM reasoning.
Answer a question a run asked (pending_kind=question in run_get).
Read a project document: intent, requirements, spec or plan — approved content plus any pending proposal.
Preflight a hand-written requirements, spec, or plan document against the same deterministic grammar used by proposal gates. Returns only syntax/contract diagnostics — no trace graph, repository, or semantic review — and never writes the candidate.
Remove one budget cap from a live or paused run so resume can proceed. One-way, per-cap, and attributed to this MCP operator; use kind tokens | usd | turns | wallclock | calls.
Read deterministic configuration findings; this never changes the project.
Decide a run waiting at its gate. `action` must come from the run's `next` list. `reason` is required and recorded — you are deciding as yourself, and the record will say so. request_changes sends the draft back with your note.
Output schemas not documented. LLMs cannot predict response structure (e.g., what fields does run_get return? what is the structure of status's next_steps?). This forces agents to reason blindly about downstream tool calls.
Parameter descriptions are sparse or missing. 'roster' tool has 'mode' and 'role' params with no guidance on valid values or semantics. 'answer' tool's 'question_id' lacks context. LLMs cannot infer constraints from names alone.
Destructive/sensitive tools lack permission and audit documentation. 'task_remove' (DESTRUCTIVE), 'decide' (WRITE), and 'budget_lift' (WRITE) do not declare required permissions or audit trail behavior. Agents cannot reason about authorization or compliance.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 60 | 2026-07-28+ | v2 |
File the run's final structured reviewer findings as bugs, exactly like the desktop action. Bugs retain review provenance and are attributed to this MCP operator.
The light path out of review: add tasks for a small change WITHOUT the redesign cycle. An architect amends the plan (1-3 tasks, wired to existing spec sections where they cover it; uncovered tasks wear spec-debt). If the change alters what the product IS — its requirements — the amendment comes back empty: write a brief via stage_start intake instead. The proposal pauses for the human's accept.
Read or edit canonical roster seats. get resolves provenance; set replaces ordered ducklings; unpin restores Global inheritance.
One run's full result: status, verdict, failure, spend, the diff it produced, and `next` — the legal actions. The verdict is the gate's, not yours and not negotiable; your decision is whether to accept the work.
Build a task WITHOUT the test-first discipline — an exception, not the ordinary path. When the human says to run, start or build a task, they mean test_build (the TDD chain); use run_start only when they explicitly ask to skip the test. Mode defaults to the project's habit; solo|pair|tournament|split.
Erase spec-debt: a spec revision documents, as built, the tasks no section covers. The engine assembles the prompt from the debt itself — no text needed. On the human's accept, Covers: fields wire the plan and the markers come off. Use when task_li
Run a document stage: intake (brief or adopt), spec, plan. adopt=true surveys an existing codebase into the requirements it already satisfies.
What needs a decision and what is running, across every project. Start here. Each pending run carries `next`: the ONLY actions you may take on it. Each project carries `next_steps` — the engine's own guidance, the same the desktop's rail shows. When the human asks what to do, answer FROM next_steps: it already knows that a triaged bug wants promoting and which task is buildable.
Declare a task completed by a commit already reachable from the default branch. The commit must name the exact task id unless confirm_task explicitly attests the association. Records an accepted external build run with actor and reason provenance.
The project's tasks: a status summary first, then one compact line per task (id, status, title, blocked reason when blocked, next). Answer "anything pending?" from the summary. Bodies are omitted — read one task's brief via the run you start, or artifact_get the plan.
Retire an unstarted superseded task from the plan. The engine refuses tasks with accepted or open runs.
Error handling lacks recovery guidance. No tool description explains what to do if a call fails (e.g., 'If run_id is invalid, call status() to list valid runs'). Agents have no fallback strategy.
spec_settle description is truncated ('Use when task_li...'). Incomplete documentation prevents LLMs from understanding when to invoke this tool.