Local-first kanban for AI-agent workflows. SQLite, FastAPI, no auth, no cloud.
agent-kanban has 14 well-named tools with clear verb-noun patterns (kanban_list, kanban_create, kanban_move). Descriptions are present and reasonably detailed (avg ~150 chars), explaining WHAT and WHEN. Input schemas are visible with type declarations. However, several critical gaps: (1) parameter descriptions are often generic or missing detail on constraints (e.g., kanban_list 'status' param lists values in description but not as enum); (2) output schemas are documented in docstrings but not formally in JSON Schema; (3) error handling is basic (returns {ok:false, error:msg} but no recovery guidance or categorization); (4) no tool annotations (readOnlyHint, destructiveHint) despite clear read/write distinction; (5) some parameters lack descriptions entirely (e.g., kanban_blockers 'blocker_ids' has minimal guidance on format/validation). Composition is strong, tools chain well (list → get → move/comment). Security: no secrets in params, but no audit logging visible.
Set blocker tasks for a given task.
Compact overview of a project board: counts + first 5 tasks per column. Perfect for a quick "what's in progress?" answer without enumerating all 100+ tasks. Args: project_id: project slug (see kanban_projects).
Describe every kanban column and who moves cards in/out of it. Call this at the start of a session to understand the current status model.
Add a comment to the task's history. Useful for recording the plan once the task lands in Analyst, or for capturing a test result.
Create a new card. Defaults to Backlog; for immediate work pass status='in_progress'. Args: title: a short single-line title. description: markdown with the details. acceptance: acceptance criteria (what counts as "done"). priority: high / normal / low. size: S (<30 min) / M (<2 h) / L (>2 h). project_id: project slug; None = default (see KANBAN_DEFAULT_PROJECT_ID or KANBAN_PROJECT_ID env).
Parameter constraints not formalized as enums. kanban_list 'status' param lists valid values in description text ('backlog/approved/analyst/...') but not as JSON Schema enum. LLMs cannot parse text constraints reliably and may hallucinate invalid values.
Output schemas documented in docstrings but not formally declared. kanban_get, kanban_list, kanban_board return structured data but no JSON Schema definition visible in tool registration. LLMs cannot reliably extract fields from undocumented responses.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint). Tools clearly marked as READ_ONLY or WRITE in metadata but not exposed via MCP tool annotations. Agents cannot distinguish safe vs destructive operations without reading descriptions.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 57 | 2026-07-28+ | v2 |
Full task card: description, acceptance, links, history.
Add a link (memory / file / pr / url) to a task.
List tasks with optional filters. Args: status: one of backlog/approved/analyst/in_progress/testing/uat/done/blocked/cancelled, or None for all. assignee: claude / agent:<name> / user, or None for all. project_id: project slug (see kanban_projects); None = all projects. Returns: {"ok": true, "data": {"tasks": [{...short fields}], "count": N}}
Move a task to a new status. Args: task_id: T-XXX to_status: target status (see kanban_columns). comment: optional comment, recorded in history. actor: claude / agent:<name>; defaults to claude.
Active tasks for the given assignee — in analyst/in_progress/testing. Perfect as the first query of a session: "what am I working on right now?" Args: assignee: claude (default), agent:<name>, user, ... project_id: project slug; None = all projects.
List projects with task counts per column. Call this at the start of a session to learn which projects exist. Returns: {"ok": true, "data": {"projects": [ {"id": "finops", "name": "FinOps", "color": "#F10D30", "path": "/abs/path", "task_counts": {"backlog": 5, ...}, "total_tasks": 33, "archived": false} ]}}
Atomically "claim a task" from Approved → Analyst. Conditions: the task must be in status ``approved`` AND its assignee must be either None or equal to ``assignee``. If another agent has already taken it, you get an error — try a different task. project_id is taken from the task itself, so you do not need to provide it.
Search tasks by substring in title/description (case-insensitive). Args: query: search term; rejected if shorter than 2 characters. project_id: limit the search to one project; None = all.
Update task fields (title, description, acceptance, priority, size, external_blocker).
Error handling lacks recovery guidance. All errors return {ok:false, error:msg} with generic messages. No categorization (retryable vs user-fixable vs fatal), no suggestions for next steps, no invalid-value echoing for self-correction.
kanban_get description is minimal ('Full task card: description, acceptance, links, history.'). Does not explain when to call it vs kanban_list, what fields are returned, or expected response size. Agents may not know when this tool is necessary.