An MCP server for managing expense tracking with SQLite database backend
ExpenseTracker has basic tool definitions with consistent naming (all action verbs), clear descriptions (100-150 chars), and complete input schemas with type definitions. However, output schemas are not documented, error handling is minimal, and several parameter descriptions lack specificity about format/constraints. The tools follow a single-resource pattern with CRUD operations properly named, but lack guidance on date formats, validation ranges, and recovery paths for common errors. No parameter descriptions specify expected date format (ISO 8601, MM/DD/YYYY, etc.), and error responses would likely be generic SQLite errors rather than actionable guidance.
Add a new expense entry to the database.
Delete an expense entry by its ID.
List expense entries within an inclusive date range.
Summarize expenses by category within an inclusive date range.
Update an existing expense entry.
Output schemas not documented. LLMs cannot predict response structure or chain tools. The list_expenses and summarize tools return dicts/lists, but no schema is declared for what fields appear in each expense record.
Date parameter format not specified. Descriptions say 'Date of the expense' without stating whether ISO 8601 (2024-01-15), MM/DD/YYYY, or other format is expected. LLMs may pass inconsistent formats, causing silent failures or invalid entries.
No error handling guidance. Tool implementations will throw SQLite errors (constraint violations, type mismatches) with no recovery path for the LLM. E.g., invalid date format will fail silently; expense_id that doesn't exist in delete_expense/update_expense returns success but modifies nothing.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 57 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 38 | - | v1 |
Numeric parameters lack bounds. 'amount' accepts any number with no validation for negative values, currency precision (cents vs. arbitrary decimals), or reasonableness limits. LLMs could pass $999,999,999.99 or negative amounts unintentionally.
Category/subcategory values unconstrained. The summarize tool accepts optional 'category' filter, but no enum or validation is documented. LLMs may invent categories that don't exist, causing silent filtering failures (returns empty instead of error).
No destructive tool confirmation. delete_expense irreversibly removes records, but descriptions do not warn of this or suggest a dry-run pattern. Agents could delete data without user confirmation.
list_expenses and summarize lack pagination/limit. Returning all expenses in a large database will bloat response size and waste tokens. No limit or offset parameters offered.
update_expense and delete_expense do not confirm row was found/modified. A DELETE or UPDATE with a non-existent ID silently succeeds (SQLite executes but modifies 0 rows). No way for LLM to detect if the operation actually did anything.