Minimal production-ready MCP server template in TypeScript — example todo manager, stdio transport, persistent storage
Server has clear tool naming (verb_noun pattern) and basic schemas with type definitions. Descriptions are present but generic (avg 60 chars, below 194-char baseline). Parameter descriptions exist but lack detail on constraints, formats, and error recovery. No output schema documentation. Error handling returns text but lacks actionable guidance or categorization. Missing tool annotations (readOnlyHint, destructiveHint). Composition is sound, each tool has one responsibility, but descriptions don't explain when to use each tool vs. alternatives.
Add a new todo item. Returns the created todo with its id.
Mark a todo as completed by id.
List todo items. Filter by 'all' (default), 'active', or 'completed'.
Delete a todo by id. Returns true if removed, false if not found.
Descriptions lack actionable context. 'Mark a todo as completed by id' (40 chars) does not explain when to use this vs. remove_todo, what happens on retry, or what the response contains. Baseline is 194 chars with WHAT/WHEN/RETURN guidance.
No output schema documented. Callers cannot know what fields to expect (e.g., does add_todo return {id, text, completed, createdAt}?). LLMs must guess or parse unstructured text.
Parameter 'id' lacks format/constraint description. Is it a UUID, timestamp-based, or opaque string? No guidance on what to do if the ID is invalid or not found.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 63 | 2026-07-28+ | v2 |
Error handling returns plain text ('Error in {name}: {message}') with no recovery guidance. Per pattern:recovery-guide, errors should suggest next steps: 'Todo not found. Call list_todos() to see available IDs.'
No tool annotations. remove_todo is destructive but lacks destructiveHint. list_todos is read-only but lacks readOnlyHint. Agents cannot distinguish safe from risky operations.