Remote MCP server for tracking and managing expenses with SQLite database backend
This server has structural deficiencies in definition quality that prevent it from being production-ready. While the tool names follow verb_noun conventions (add_expense, list_expenses, delete_expense, summarize_expenses, export_database), most descriptions are either missing context or dangerously vague. The summarize_expenses tool accepts raw SQL strings with no validation, creating a critical SQL injection vulnerability. Parameters lack sufficient detail in descriptions, and error handling is absent, there is no guidance for LLMs on what to do when operations fail. Schema definitions exist and are partially structured (via Pydantic models), but output schemas are not documented. The server uses HTTP transport (fastmcp with http runner), which is current, but protocol adherence gaps remain.
Add a new expense to the database
Delete an expense by ID
Export the SQLite database as base64
Retrieve all expenses from the database
This function summarizes expenses based on user columns. The function takes only select clause
summarize_expenses accepts raw SQL strings with no input validation or sanitization. This is a direct SQL injection vulnerability. An LLM could be tricked into passing `'; DROP TABLE expenses; --` which would execute against the database.
No error handling or recovery guidance in any tool. When delete_expense fails (e.g. ID not found), it returns {"status": "success", "message": "..."} regardless of actual success. LLMs receive no signal that the operation failed and no guidance on what to do next.
Tool descriptions are either absent or incomplete. list_expenses has a 22-character description (just the action, no context). summarize_expenses description is confusing ('takes only select clause', what does this mean? why is this useful?). Export_database description lacks context on when to use it.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 54 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 38 | - | v1 |
Output schemas are not documented. list_expenses and summarize_expenses return lists of dicts but the structure (field names, types, meaning) is not declared. Downstream tools and the LLM cannot plan reliable chaining without knowing what fields are returned.
delete_expense lacks confirmation or dry-run capability. An LLM in a loop could accidentally delete multiple expenses without warning. Irreversible operations should support a confirmation step.
Parameter descriptions are generic or absent. expense_id in delete_expense has description 'The ID of the expense to delete' but no guidance on how to obtain it (e.g. 'Call list_expenses() first'). summarize_sql has description 'SQL SELECT statement' which is trivial, LLMs need format guidance (must be SELECT only, table name is 'expenses', etc).
Destructive operation (delete_expense) risk marked DESTRUCTIVE but no permission gate or audit trail. No evidence of logging who deleted what, when, or why.
list_expenses returns all expenses with no pagination, limit, or offset parameters. If the database grows to thousands of rows, this will blow the LLM context window and waste tokens.