MCP server for Budgetsco - provides tools for managing transactions, categories, recurring transactions, currency preferences, and budget targets
The server has 16 well-structured tools with explicit registration, input schemas, descriptions, and tool annotations (readOnlyHint, destructiveHint, idempotentHint). However, several critical gaps reduce overall quality: (1) Most parameter descriptions are minimal or generic (e.g., 'Amount of the transaction' lacks format/constraints); (2) Output schemas are NOT documented, the code returns JSON.stringify(response.data) with no typed response definition visible; (3) Error handling is basic (throwing generic Error objects) with no recovery guidance; (4) Several tools lack clarity on what data they return and how to chain results; (5) Some parameter names and schemas have inconsistencies (e.g., 'amount' has no type declaration visible in schema; 'transactionId' is described the same way across three different tools despite different contexts). Tools like getTransactions and createTransaction have reasonable schemas but descriptions could be more action-focused. The code quality is good (Zod validation, proper API calls), but the tool interface design lacks the LLM-optimization needed for production agent use.
Create new custom categories for transactions.
Create a recurring transaction
Create new transaction.
Delete custom categories
Delete a recurring transaction permanently
Delete transaction permanently.
Edit a recurring transaction
Output schemas are completely undocumented. Code returns JSON.stringify(response.data) but no TypeScript interfaces or JSON Schema definitions are visible for what each tool returns. LLMs cannot predict the response structure, making tool chaining and field extraction error-prone.
Parameter 'amount' lacks type declaration in schemas (visible as just a description field with no type:number). This violates the JSON Schema contract and prevents clients from validating input before calling the tool.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 56 | 2026-07-28+ | v2 |
| 2026-03-09 | D | 58 | - | v1 |
Edit an existing transaction.
Retrieve all categories of a specific type. Always use this tool to get categories before creating a transaction. If no categories match, create a new category.
Get the current currency preference
Retrieve all custom categories created by the user
Retrieve recurring transactions
Retrieve a list of transactions
Mark a recurring transaction as done for the current period
Set currency preference
Skip a recurring transaction for the current period
Error handling is minimal. The codebase throws generic Error() with no recovery hints. For example, invalid input just throws 'Invalid custom category input' without telling the LLM what values are valid or what to try next. No error classification (retryable vs fatal).
Parameter descriptions are generic and lack actionable constraints. For example, 'interval' is described as 'Interval for the recurrence, for example, 1 for every day, 2 for every two months, etc.' but this mixes two concepts and does not clarify that interval=1 means 'every 1 day' vs 'every 1 occurrence'. The relationship between 'interval' and 'occurrence' enum is underdocumented.
Three tools (markRecurringTransactionDone, skipRecurringTransaction, deleteRecurringTransaction) all accept the same 'transactionId' parameter with the same description, but have different semantic consequences. Descriptions should clarify: 'Mark as complete (skippable later)' vs 'Skip this period (can resume)' vs 'Delete permanently (irreversible)'.
No pagination or result limits documented for tools that return lists. getTransactions, getCategoriesByType, getCustomCategories, and getRecurringTransactions may return large result sets without documented caps or limit/offset parameters visible in the provided schema.
getTransactions has 'paymentModes' parameter typed as a single string enum, not an array, despite plural naming. Schema shows type:string with enum, but the description says 'Filter by payment modes' (plural). This is a critical ambiguity, does it filter to one mode or multiple?
Tool descriptions do not document interdependencies. For example, createTransaction mentions 'Always use getCategoriesByType first' in getCategoriesByType's description, but createTransaction itself should state 'Call getCategoriesByType first to validate the category exists' to guide multi-step planning.
Destructive tools (deleteCustomCategories, deleteRecurringTransaction, deleteTransaction) have no confirmation step or dry-run capability. An agent could permanently delete data without validation. No error message hints at what was deleted or how to recover.
createTransaction and editTransaction both accept 'isNewCustomCategory' boolean with description 'Is this a new custom category?' but the relationship to the 'category' string parameter is unclear. Does this parameter auto-create a category if it does not exist? This dependency is underdocumented.