A NestJS-based MCP server for managing todos, tags, and users with GraphQL and REST APIs
Server defines 15 tools with consistent naming (verb_noun pattern) and reasonable descriptions. All tools have input schemas with type definitions and parameter descriptions. However, descriptions are generic and lack LLM-optimized guidance on WHEN to use each tool vs. alternatives. Output schemas are not documented, responses are JSON-stringified text blocks rather than structured objects. Error handling returns isError flags but lacks recovery guidance or actionable next steps. No tool annotations (readOnlyHint, destructiveHint, idempotentHint) despite clear risk levels. Parameter descriptions mention constraints (minLength, maxLength, regex patterns) but do not always restate them in human-readable form for LLM parsing.
Creates a new tag with a name and optional color. Example usage: - Create a simple tag: {"name": "Work"} - Create a colored tag: {"name": "Important", "color": "#FF0000"}
Creates a new todo item with all available fields. Example usage: - Create a simple todo: {"title": "Buy groceries", "userId": "123e4567-e89b-12d3-a456-426614174000"} - Create a detailed todo: { "title": "Write report", "description": "Complete the quarterly report", "completed": false, "priority": "HIGH", "startDate": "2024-03-20T09:00:00Z", "dueDate": "2024-03-25T17:00:00Z", "userId": "123e4567-e89b-12d3-a456-426614174000", "tagIds": ["tag-uuid-1", "tag-uuid-2"] }
Creates a new user with an email and optional name. Example usage: - Create a simple user: {"email": "[email protected]"} - Create a user with name: {"email": "[email protected]", "name": "John Doe"}
Deletes a tag by its unique identifier. Example usage: - Delete a tag: {"id": "123"}
Deletes a todo item by its unique identifier. Example usage: - Delete a todo: {"id": "123"}
Output schemas not documented. Tools return JSON-stringified text blocks (e.g., `{type: 'text', text: JSON.stringify(tag)}`) instead of structured objects. LLMs cannot parse field names or plan downstream tool calls without explicit output schema documentation.
Error handling lacks recovery guidance. Errors return `{isError: true, content: [{type: 'text', text: 'Failed to...'}]}` with no actionable next steps. LLMs cannot determine if the error is retryable, user-fixable, or fatal.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 53 | <=2025-11-25 | v2 |
Deletes a user by their unique identifier. Example usage: - Delete a user: {"id": "123"}
Retrieves a tag by its unique identifier. Example usage: - Get a tag: {"id": "123"}
Retrieves a todo item by its unique identifier. Example usage: - Get a todo: {"id": "123"}
Retrieves a user by their unique identifier. Example usage: - Get a user: {"id": "123"}
Retrieves all tags in the system. Example usage: - List all tags: {}
Retrieves all todo items in the system. Example usage: - List all todos: {}
Retrieves all users in the system. Example usage: - List all users: {}
Updates an existing tag with new values. Example usage: - Update name: {"id": "123", "name": "Updated name"} - Update color: {"id": "123", "color": "#00FF00"} - Update both: {"id": "123", "name": "New name", "color": "#0000FF"}
Updates an existing todo item with new values. Example usage: - Update title: {"id": "123", "title": "Updated title"} - Mark as completed: {"id": "123", "completed": true} - Update multiple fields: { "id": "123", "title": "New title", "description": "New description", "completed": true, "priority": "HIGH", "startDate": "2024-03-20T09:00:00Z", "dueDate": "2024-03-25T17:00:00Z", "tagIds": ["tag-uuid-1", "tag-uuid-2"] }
Updates an existing user with new values. Example usage: - Update email: {"id": "123", "email": "[email protected]"} - Update name: {"id": "123", "name": "Jane Doe"} - Update both: {"id": "123", "email": "[email protected]", "name": "Jane Doe"}
No tool annotations despite clear risk levels. Tools marked DESTRUCTIVE (delete-tag, delete-todo, delete-user) and WRITE (create-*, update-*) lack destructiveHint and idempotentHint annotations. LLMs cannot distinguish safe from risky operations.
Descriptions are generic and lack LLM-optimized guidance. Most descriptions (55 - 70 chars) state WHAT the tool does but not WHEN to use it vs. similar tools. E.g., list-tags and list-todos lack context on pagination, filtering, or when to call them vs. get-*.
No pagination support on list tools. list-tags, list-todos, list-users return all results without limit, offset, or cursor parameters. Large datasets will blow context windows and degrade LLM reasoning.