MCP server for YNAB (You Need A Budget) API integration, providing tools to query and manage budgets, accounts, categories, transactions, and monthly data.
YNAB MCP demonstrates solid definition quality with comprehensive tool coverage, consistent naming, and clear descriptions. All 10 tools follow verb_noun conventions (list_budgets, get_budget, create_transaction, etc.). Descriptions are present and contextual (average ~120 chars, within 10-1024 baseline). Input schemas are well-defined with proper types and required flags. However, critical gaps exist: (1) Output schemas are undocumented, no schema for what list_budgets, get_budget, get_accounts, etc. actually return. LLMs cannot plan downstream calls without knowing the response structure. (2) Parameters lack detailed constraints and dependencies, e.g., 'amount' in create_transaction says 'in milliunits' but provides no bounds or validation guidance. (3) Error handling is minimal, handlers return generic errors without recovery guidance. (4) No tool annotations (readOnlyHint/destructiveHint) despite clear risk differentiation (READ_ONLY vs WRITE). Per-tool scores range 60-82; the average lands at 72.
Create a new transaction in a budget. Amount is in milliunits (1000 = $1.00, use negative for outflows).
Create multiple transactions in a budget in a single request. Each transaction amount is in milliunits (1000 = $1.00, use negative for outflows).
List all accounts in a budget with their balances.
Get detailed information about a specific budget including accounts, categories, and category groups.
Get a single budget month with category breakdowns. Returns income, budgeted, activity, to-be-budgeted, and per-category details.
List all budget months for a budget. Returns monthly summaries with income, budgeted, activity, and to-be-budgeted amounts.
Output schemas completely undocumented. LLMs cannot determine what fields list_budgets, get_budget, get_accounts, get_categories return. No pagination hints, field types, or nesting structure documented. Agents cannot chain tools without guessing response structure.
Tool annotations missing. Handlers define tools with READ_ONLY vs WRITE risk classifications in comments, but no readOnlyHint or destructiveHint annotations are passed to mcp.NewTool(). LLMs cannot automatically distinguish safe vs dangerous operations.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 59 | 2026-07-28+ | v2 |
| 2026-03-09 | D | 58 | - | v1 |
List all category groups and categories in a budget with their budgeted amounts, activity, and balances.
Get transactions for a budget. Optionally filter by date. Amounts are in milliunits (1000 = $1.00).
List all budgets in the YNAB account. Returns budget IDs and names. Use this first to discover available budget IDs.
Update an existing transaction in a budget. Amount is in milliunits (1000 = $1.00, use negative for outflows).
Parameter constraints underspecified. 'amount' field in create_transaction and update_transaction accepts number type but lacks min/max bounds, valid range documentation, or rounding rules. No guidance on negative values despite memo saying 'use negative for outflows'. LLMs will pass arbitrary values.
Error handling provides no recovery guidance. Handlers return mcp.NewToolResultError(err.Error()) which passes raw API errors to LLM. No actionable next steps, no categorization (retryable vs user-fixable), no suggestions for alternatives.
No pagination support. Handlers return full results from API without limit, offset, or cursor parameters. get_transactions, get_budget_months could return hundreds of items, bloating context window and degrading LLM reasoning.
Parameter dependencies undocumented. create_transaction has optional category_id, but no description explains when/whether it must match the account's budget or whether NULL is valid. LLMs will guess incorrectly.
Idempotency unclear. create_transaction and create_transactions lack documentation on idempotency. Can they be retried safely? Do duplicate calls create duplicate transactions or upsert? Agents will not know whether to retry on failure.