todo-mcp has 4 clearly defined tools with basic schemas and descriptions. Naming follows verb_noun convention (add_task, complete_task, delete_task, list_tasks) which is good. All tools have input schemas using Zod validation and descriptions are present. However, descriptions are minimal (10-30 chars), parameter descriptions are sparse, error handling lacks recovery guidance, and output schemas are not formally documented. The server does not implement tool annotations (readOnlyHint, destructiveHint) despite having clear READ_ONLY, WRITE, and DESTRUCTIVE risk classifications. list_tasks has zero input parameters but still requires a schema object. Overall, the tooling is functional but lacks the depth and LLM-optimization expected of production-grade definitions.
Add a new task to the todo list
Mark a task as done
Delete a task by ID
List all tasks
Descriptions are under 30 characters for 3 of 4 tools (complete_task, delete_task, list_tasks). Current descriptions ('Mark a task as done', 'Delete a task by ID', 'List all tasks') lack context about WHEN to use each tool or its prerequisites.
Tool annotations missing: destructive tools (delete_task) and read-only tools (list_tasks) do not declare readOnlyHint or destructiveHint. This prevents the LLM and clients from reasoning about idempotency, retry safety, and blast radius. Risk classifications exist in metadata but are not exposed via the MCP protocol.
Output schema not documented: tools return plain text responses (e.g. 'Task added: [UUID] title (priority)') without a formal schema declaration. LLMs cannot extract structured fields like task_id, task_title, or task_priority from unstructured text. This forces post-hoc parsing and prevents downstream tool chaining (e.g., passing the newly created task_id to complete_task).
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | F | 47 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 47 | - | v1 |
Error handling lacks recovery guidance: McpError throws on 'Task not found' with message 'Task not found: {id}' but does not suggest next steps (e.g. 'Try calling list_tasks() to see available tasks'). Per pattern:recovery-guide, errors should tell the LLM what to do next.
list_tasks has empty inputSchema (no parameters). The schema object is present but contains no 'type' or 'properties' fields. Pagination is missing, if task count grows large, returning all tasks will exhaust the context window. No limit, offset, or cursor parameters.
Parameter descriptions are generic or missing context. 'Task ID' for complete_task and delete_task does not explain format (UUID vs integer), whether it comes from list_tasks output, or how the LLM should obtain it. 'Task title' lacks minLength guidance. 'Priority' description is minimal.
No confirmation or dry-run for destructive operation: delete_task is irreversible but has no confirmation step, warning, or dry-run capability. Agents are prone to mistakes, a user asking 'clean up old tasks' could trigger cascading deletes without explicit approval.