# YNAB MCP Server API Reference This document provides comprehensive documentation for all tools available in the YNAB MCP Server, including parameters, examples, and error handling. ## Table of Contents - [Overview](#overview) - [Authentication](#authentication) - [Data Formats](#data-formats) - [MCP Resources](#mcp-resources) - [MCP Client Features](#mcp-client-features) - [Budget Management Tools](#budget-management-tools) - [Account Management Tools](#account-management-tools) - [Transaction Management Tools](#transaction-management-tools) - [Category Management Tools](#category-management-tools) - [Payee Management Tools](#payee-management-tools) - [Monthly Data Tools](#monthly-data-tools) - [Utility Tools](#utility-tools) - [Diagnostic Tools](#diagnostic-tools) - [Error Handling](#error-handling) ## Overview The YNAB MCP Server provides 29 tools that enable AI assistants to interact with YNAB data. All tools follow consistent patterns for parameters, responses, and error handling. ### Tool Naming Convention All tools follow a simple naming pattern with an action and resource: - `list_budgets` - List operation on budgets - `get_budget` - Get operation on a specific budget - `create_transaction` - Create operation for transactions ## Authentication All tools require authentication via a YNAB Personal Access Token set in the `YNAB_ACCESS_TOKEN` environment variable. ```bash YNAB_ACCESS_TOKEN=your_personal_access_token_here ``` ## Data Formats ### Monetary Amounts **šŸ“¢ New in v0.7.0**: Monetary values in responses are automatically converted to standard dollar format for human readability. The server automatically converts YNAB's internal milliunits to dollars in all responses: - Account balances: `-1924.37` (instead of `-1924370` milliunits) - Transaction amounts: `50.25` (instead of `50250` milliunits) - Budget amounts: `150.00` (instead of `150000` milliunits) **Input formats**: - Some user-facing helpers accept decimal dollars, such as `create_account.balance`, `create_receipt_split_transaction` receipt amounts, and `reconcile_account.statement_balance` - Direct mutation APIs such as `create_transaction.amount`, `create_transaction.subtransactions[].amount`, `update_transaction.amount`, and `update_category.budgeted` require **integer milliunits** (for example, `$50.25` = `50250`) **Note**: YNAB's internal representation uses milliunits (1/1000th of a currency unit). Responses are rendered in dollars, but write-tool inputs must follow the per-tool contract below. ### Dates All dates use ISO 8601 format: `YYYY-MM-DD` - Example: `2024-01-15` - Time zones are handled by YNAB based on your account settings ### IDs All YNAB IDs are UUID strings: - Budget ID: `12345678-1234-1234-1234-123456789012` - Account ID: `87654321-4321-4321-4321-210987654321` ## MCP Resources **šŸ“¢ New in v0.16.0**: The YNAB MCP Server now supports MCP resource templates, enabling AI assistants to discover and access YNAB data through standardized URI patterns. ### What are MCP Resources? MCP resources provide a standardized way for AI assistants to access structured data using URI patterns. Unlike tools (which perform actions), resources are read-only data endpoints that can be discovered and accessed dynamically. ### Available Resources #### Static Resources | URI | Description | Returns | |-----|-------------|---------| | `ynab://budgets` | List all available budgets | Array of budget summaries with IDs, names, and metadata | | `ynab://user` | Current user information | User ID and basic profile data | #### Resource Templates (Dynamic URIs) | URI Template | Parameters | Description | Returns | |--------------|------------|-------------|---------| | `ynab://budgets/{budget_id}` | `budget_id` (UUID) | Detailed budget information | Complete budget object with accounts, categories, months, and settings | | `ynab://budgets/{budget_id}/accounts` | `budget_id` (UUID) | List accounts for a budget | Array of all accounts in the specified budget | | `ynab://budgets/{budget_id}/accounts/{account_id}` | `budget_id` (UUID)
`account_id` (UUID) | Detailed account information | Complete account object with balance, type, and metadata | ### Usage Examples #### Listing Budgets ``` URI: ynab://budgets ``` **Response:** ```json { "budgets": [ { "id": "12345678-1234-1234-1234-123456789012", "name": "My Budget 2025", "last_modified_on": "2025-12-01T10:30:00Z", "first_month": "2025-01-01", "last_month": "2025-12-01", "currency_format": { "iso_code": "USD", "example_format": "$123.45", "decimal_digits": 2, "decimal_separator": ".", "symbol_first": true, "group_separator": ",", "currency_symbol": "$", "display_symbol": true } } ] } ``` #### Getting Budget Details ``` URI: ynab://budgets/12345678-1234-1234-1234-123456789012 ``` **Response:** ```json { "id": "12345678-1234-1234-1234-123456789012", "name": "My Budget 2025", "accounts": [...], "categories": [...], "months": [...], "date_format": {"format": "DD/MM/YYYY"}, "currency_format": {...} } ``` #### Listing Budget Accounts ``` URI: ynab://budgets/12345678-1234-1234-1234-123456789012/accounts ``` **Response:** ```json [ { "id": "87654321-4321-4321-4321-210987654321", "name": "Checking Account", "type": "checking", "balance": -1924.37, "cleared_balance": -1850.00, "uncleared_balance": -74.37, "on_budget": true, "closed": false } ] ``` #### Getting Account Details ``` URI: ynab://budgets/12345678-1234-1234-1234-123456789012/accounts/87654321-4321-4321-4321-210987654321 ``` **Response:** ```json { "id": "87654321-4321-4321-4321-210987654321", "name": "Checking Account", "type": "checking", "balance": -1924.37, "cleared_balance": -1850.00, "uncleared_balance": -74.37, "on_budget": true, "closed": false, "note": null, "transfer_payee_id": "..." } ``` ### Caching All MCP resources are cached for optimal performance: - **Budgets**: 10 minutes TTL (rarely change) - **Accounts**: 5 minutes TTL (balances update periodically) - **User info**: 30 minutes TTL (static data) ### Resource vs Tool: When to Use What **Use MCP Resources when:** - You need to **read** structured data - You want to **discover** available budgets or accounts - You're building a UI that needs to **list** items - You need **cached** data for performance **Use Tools when:** - You need to **create**, **update**, or **delete** data - You need advanced filtering or querying (e.g., transactions since date) - You need to perform **actions** (e.g., reconcile, export) - You need the latest **real-time** data **Example:** - Get list of budgets: Use `ynab://budgets` resource āœ… - Get transactions for an account: Use `list_transactions` tool āœ… - Create a new transaction: Use `create_transaction` tool āœ… ## MCP Client Features These features depend on MCP client support. If your client doesn't surface them, tool calls still work normally. ### Completions (Autocomplete) The server provides MCP completions for common arguments: - `budget_id` - `account_id` - `account_name` - `category` - `category_id` - `payee` - `payee_id` Clients can use these completions to suggest IDs or names while composing tool calls. ### Progress Notifications When a client provides a `progressToken` in tool requests, the server emits `notifications/progress` events. Progress updates are most useful for long-running operations such as `reconcile_account`, which can create, update, or unclear large batches of transactions. ## Budget Management Tools ### list_budgets Lists all budgets associated with the user's account. **Parameters:** None **Example Request:** ```json { "name": "list_budgets", "arguments": {} } ``` **Example Response:** ```json { "content": [ { "type": "text", "text": "{\n \"budgets\": [\n {\n \"id\": \"12345678-1234-1234-1234-123456789012\",\n \"name\": \"My Budget\",\n \"last_modified_on\": \"2024-01-15T10:30:00.000Z\",\n \"first_month\": \"2024-01-01\",\n \"last_month\": \"2024-12-01\",\n \"date_format\": {\n \"format\": \"MM/DD/YYYY\"\n },\n \"currency_format\": {\n \"iso_code\": \"USD\",\n \"example_format\": \"123,456.78\",\n \"decimal_digits\": 2,\n \"decimal_separator\": \".\",\n \"symbol_first\": true,\n \"group_separator\": \",\",\n \"currency_symbol\": \"$\",\n \"display_symbol\": true\n }\n }\n ]\n}" } ] } ``` ### get_budget Gets detailed information for a specific budget. **Parameters:** - `budget_id` (string, required): The ID of the budget to retrieve **Example Request:** ```json { "name": "get_budget", "arguments": { "budget_id": "12345678-1234-1234-1234-123456789012" } } ``` **Example Response:** ```json { "content": [ { "type": "text", "text": "{\n \"budget\": {\n \"id\": \"12345678-1234-1234-1234-123456789012\",\n \"name\": \"My Budget\",\n \"last_modified_on\": \"2024-01-15T10:30:00.000Z\",\n \"first_month\": \"2024-01-01\",\n \"last_month\": \"2024-12-01\",\n \"accounts\": [...],\n \"payees\": [...],\n \"payee_locations\": [...],\n \"category_groups\": [...],\n \"categories\": [...],\n \"months\": [...],\n \"transactions\": [...],\n \"subtransactions\": [...],\n \"scheduled_transactions\": [...],\n \"scheduled_subtransactions\": [...]\n }\n}" } ] } ``` ## Account Management Tools ### list_accounts Lists all accounts for a specific budget. **Parameters:** - `budget_id` (string, optional): The ID of the budget. Omit to use the default budget **Example Request:** ```json { "name": "list_accounts", "arguments": { "budget_id": "12345678-1234-1234-1234-123456789012" } } ``` **Example Response:** ```json { "content": [ { "type": "text", "text": "{\n \"accounts\": [\n {\n \"id\": \"87654321-4321-4321-4321-210987654321\",\n \"name\": \"Checking Account\",\n \"type\": \"checking\",\n \"on_budget\": true,\n \"closed\": false,\n \"note\": null,\n \"balance\": 150.0,\n \"cleared_balance\": 145.0,\n \"uncleared_balance\": 5.0,\n \"transfer_payee_id\": \"transfer-payee-id\",\n \"direct_import_linked\": false,\n \"direct_import_in_error\": false,\n \"last_reconciled_at\": null,\n \"debt_original_balance\": null,\n \"debt_interest_rates\": {},\n \"debt_minimum_payments\": {},\n \"debt_escrow_amounts\": {}\n }\n ]\n}" } ] } ``` ### get_account Gets detailed information for a specific account. **Parameters:** - `budget_id` (string, optional): The ID of the budget. Omit to use the default budget - `account_id` (string, required): The ID of the account **Example Request:** ```json { "name": "get_account", "arguments": { "budget_id": "12345678-1234-1234-1234-123456789012", "account_id": "87654321-4321-4321-4321-210987654321" } } ``` ### create_account Creates a new account in the specified budget. **Parameters:** - `budget_id` (string, optional): The ID of the budget. Omit to use the default budget - `name` (string, required): The name of the new account - `type` (string, required): The account type. Valid values: - `checking` - Checking account - `savings` - Savings account - `creditCard` - Credit card account - `cash` - Cash account - `lineOfCredit` - Line of credit - `otherAsset` - Other asset account - `otherLiability` - Other liability account - `balance` (number, optional): Initial balance in dollars - `dry_run` (boolean, optional): Validate and return simulated result; no API call **Example Request:** ```json { "name": "create_account", "arguments": { "budget_id": "12345678-1234-1234-1234-123456789012", "name": "New Savings Account", "type": "savings", "balance": 100.0 } } ``` **Example Response:** ```json { "content": [ { "type": "text", "text": "{\n \"account\": {\n \"id\": \"new-account-id\",\n \"name\": \"New Savings Account\",\n \"type\": \"savings\",\n \"on_budget\": true,\n \"closed\": false,\n \"balance\": 100.0,\n \"cleared_balance\": 100.0,\n \"uncleared_balance\": 0\n }\n}" } ] } ``` ## Transaction Management Tools ### list_transactions Lists transactions for a budget with optional filtering. **Parameters:** - `budget_id` (string, optional): The ID of the budget. Omit to use the default budget - `account_id` (string, optional): Filter by account ID - `category_id` (string, optional): Filter by category ID - `since_date` (string, optional): Only return transactions on or after this date (YYYY-MM-DD) - `type` (string, optional): Filter by transaction type (`uncategorized` or `unapproved`) **Example Request:** ```json { "name": "list_transactions", "arguments": { "budget_id": "12345678-1234-1234-1234-123456789012", "account_id": "87654321-4321-4321-4321-210987654321", "since_date": "2024-01-01" } } ``` **Example Response:** ```json { "content": [ { "type": "text", "text": "{\n \"transactions\": [\n {\n \"id\": \"transaction-id\",\n \"date\": \"2024-01-15\",\n \"amount\": -5.0,\n \"memo\": \"Coffee shop\",\n \"cleared\": \"cleared\",\n \"approved\": true,\n \"flag_color\": null,\n \"account_id\": \"87654321-4321-4321-4321-210987654321\",\n \"payee_id\": \"payee-id\",\n \"category_id\": \"category-id\",\n \"transfer_account_id\": null,\n \"transfer_transaction_id\": null,\n \"matched_transaction_id\": null,\n \"import_id\": null,\n \"import_payee_name\": null,\n \"import_payee_name_original\": null,\n \"debt_transaction_type\": null,\n \"deleted\": false\n }\n ]\n}" } ] } ``` ### export_transactions Exports all transactions to a JSON file with descriptive filename and platform-specific default paths. This tool bypasses MCP response size limits by saving data to a file instead of returning it in the response. **Parameters:** - `budget_id` (string, optional): The ID of the budget. Omit to use the default budget - `account_id` (string, optional): Filter by account ID - `category_id` (string, optional): Filter by category ID - `since_date` (string, optional): Only export transactions on or after this date (YYYY-MM-DD) - `type` (string, optional): Filter by transaction type (`uncategorized` or `unapproved`) - `filename` (string, optional): Custom filename (auto-generated if not provided) - `minimal` (boolean, optional): Export only essential fields for smaller files (default: true) **Example Request:** ```json { "name": "export_transactions", "arguments": { "budget_id": "12345678-1234-1234-1234-123456789012", "since_date": "2024-01-01" } } ``` **Example Response:** ```json { "content": [ { "type": "text", "text": "{\n \"message\": \"Successfully exported 1247 transactions\",\n \"filename\": \"ynab_since_2024-01-01_1247items_2024-09-10_14-30-15.json\",\n \"full_path\": \"C:\\\\Users\\\\YourName\\\\Downloads\\\\ynab_since_2024-01-01_1247items_2024-09-10_14-30-15.json\",\n \"export_directory\": \"C:\\\\Users\\\\YourName\\\\Downloads\",\n \"filename_explanation\": \"Filename format: ynab_{filters}_{count}items_{timestamp}.json - identifies what data was exported, when, and how many transactions\",\n \"preview_count\": 10,\n \"total_count\": 1247,\n \"preview_transactions\": [\n {\n \"id\": \"transaction-id\",\n \"date\": \"2024-01-15\",\n \"amount\": -5.0,\n \"memo\": \"Coffee shop\",\n \"payee_name\": \"Starbucks\",\n \"category_name\": \"Dining Out\"\n }\n ]\n}" } ] } ``` **Export File Structure:** The exported JSON file contains: - `export_info`: Metadata about the export (timestamp, filters, count, minimal flag) - `transactions`: Array of transaction objects - **Minimal mode (default)**: `id`, `date`, `amount`, `payee_name`, `cleared` - **Full mode**: All available transaction fields **Platform-Specific Default Paths:** - Windows/Mac: `~/Downloads` - Linux/Unix: `~/Documents` (or `$XDG_DOCUMENTS_DIR`) - Configurable via `YNAB_EXPORT_PATH` environment variable ### compare_transactions Compares bank transactions from CSV files with YNAB transactions to identify missing entries in either direction. This tool helps with bank statement reconciliation by finding transactions that exist in your bank statement but not in YNAB (need to import) or vice versa (double-check for duplicates). **Parameters:** - `budget_id` (string, optional): The ID of the budget to compare against. Omit to use the default budget - `account_id` (string, required): The ID of the account to compare transactions for - `csv_file_path` (string, optional): Path to CSV file containing bank transactions - `csv_data` (string, optional): CSV data as string (alternative to csv_file_path) - `amount_tolerance` (number, optional): Amount difference tolerance as decimal (0.01 = 1%, default: 0.01) - `date_tolerance_days` (number, optional): Date difference tolerance in days (default: 5) - `csv_format` (object, optional): CSV format configuration - `date_column` (string): Column name for transaction date when `has_header: true`, or column index as string when `has_header: false` (default: "Date") - `amount_column` (string): Column name for transaction amount when `has_header: true`, or column index as string when `has_header: false` (default: "Amount") - `description_column` (string): Column name for transaction description when `has_header: true`, or column index as string when `has_header: false` (default: "Description") - `date_format` (string): Date format pattern (default: "MM/DD/YYYY") - `has_header` (boolean): Whether CSV has header row (default: true) - `delimiter` (string): CSV delimiter character (default: ",") **Example Request (CSV data):** ```json { "name": "compare_transactions", "arguments": { "budget_id": "12345678-1234-1234-1234-123456789012", "account_id": "87654321-4321-4321-4321-210987654321", "csv_data": "Date,Amount,Description\n2024-01-01,100.00,Coffee Shop\n2024-01-02,-50.25,Gas Station\n2024-01-03,25.00,ATM Withdrawal" } } ``` **Example Request (CSV file with custom format):** ```json { "name": "compare_transactions", "arguments": { "budget_id": "12345678-1234-1234-1234-123456789012", "account_id": "87654321-4321-4321-4321-210987654321", "csv_file_path": "/path/to/bank-statement.csv", "csv_format": { "date_column": "Transaction Date", "amount_column": "Dollar Amount", "description_column": "Description", "date_format": "DD/MM/YYYY", "delimiter": ";", "has_header": true }, "amount_tolerance": 0.02, "date_tolerance_days": 3 } } ``` **Example Request (CSV without headers using column indices):** ```json { "name": "compare_transactions", "arguments": { "budget_id": "12345678-1234-1234-1234-123456789012", "account_id": "87654321-4321-4321-4321-210987654321", "csv_data": "2024-01-01,100.00,Coffee Shop\n2024-01-02,-15.50,ATM Fee\n2024-01-03,250.00,Paycheck", "csv_format": { "date_column": "0", "amount_column": "1", "description_column": "2", "date_format": "YYYY-MM-DD", "has_header": false, "delimiter": "," } } } ``` **Example Response:** ```json { "content": [ { "type": "text", "text": "{\n \"summary\": {\n \"bank_transactions_count\": 15,\n \"ynab_transactions_count\": 12,\n \"matches_found\": 10,\n \"missing_in_ynab\": 5,\n \"missing_in_bank\": 2,\n \"date_range\": {\n \"start\": \"2024-01-01\",\n \"end\": \"2024-01-15\"\n },\n \"parameters\": {\n \"amount_tolerance\": 0.01,\n \"date_tolerance_days\": 5\n }\n },\n \"matches\": [\n {\n \"bank_date\": \"2024-01-01\",\n \"bank_amount\": \"100.00\",\n \"bank_description\": \"Coffee Shop\",\n \"ynab_date\": \"2024-01-01\",\n \"ynab_amount\": \"100.00\",\n \"ynab_payee\": \"Starbucks\",\n \"match_score\": 90,\n \"match_reasons\": [\"Exact date match\", \"Exact amount match\"]\n }\n ],\n \"missing_in_ynab\": [\n {\n \"date\": \"2024-01-03\",\n \"amount\": \"25.00\",\n \"description\": \"ATM Withdrawal\",\n \"row_number\": 4\n }\n ],\n \"missing_in_bank\": [\n {\n \"id\": \"transaction-xyz\",\n \"date\": \"2024-01-02\",\n \"amount\": \"-15.50\",\n \"payee_name\": \"Coffee Bean\",\n \"memo\": \"Morning coffee\",\n \"cleared\": \"cleared\"\n }\n ]\n}" } ] } ``` **Matching Algorithm:** - **Date matching** (40 points max): Exact dates get full points, nearby dates get partial points - **Amount matching** (50 points max): Exact amounts get full points, close amounts within tolerance get partial points - **Description matching** (10 points max): Similarity between bank description and YNAB payee/memo - **Smart Duplicate Handling**: Multiple transactions with identical amounts are matched using chronological order with chronology bonus (+15 points for same day, +10 for within 3 days) - **Minimum match score**: 30 points required for a valid match **Supported Date Formats:** - `MM/DD/YYYY` or `M/D/YYYY` (default) - `DD/MM/YYYY` or `D/M/YYYY` - `YYYY-MM-DD` (ISO format) - `MM-DD-YYYY` **Use Cases:** - **Bank reconciliation**: Find transactions missing from YNAB that need to be imported - **Duplicate detection**: Identify YNAB transactions that don't appear in bank statements - **Import verification**: Verify that imported transactions match your bank statement exactly - **Data cleanup**: Find and resolve discrepancies between bank and YNAB data ### reconcile_account Performs comprehensive account reconciliation with bank statement data. The tool returns **two content entries**: a human-readable narrative for assistants and a structured JSON payload (`version: "2.0"`) that encodes MoneyValue objects, insights, and optional execution results. **Parameters (selected):** - `budget_id` (string, optional): Budget UUID. Omit to use the default budget - `account_id` (string, required) - `csv_file_path` or `csv_data` (one required) - `statement_balance` (number, required) – ending cleared balance from the statement in dollars - `statement_start_date`, `statement_end_date`, `statement_date` (string, optional) - Matching controls: `date_tolerance_days` (default 7), `auto_match_threshold` (default 85), `suggestion_threshold` (default 60). Amounts must match exactly (no tolerance parameter) - Execution controls (optional): - `auto_create_transactions` (default `false`) - `auto_update_cleared_status` (default `false`) - `auto_unclear_missing` (default `false`) - `auto_adjust_dates` (default `false`) - `dry_run` (default `true`) - Other legacy options remain accepted for compatibility (`expected_bank_balance`, `require_exact_match`, etc.). **Example Request:** ```json { "name": "reconcile_account", "arguments": { "budget_id": "12345678-1234-1234-1234-123456789012", "account_id": "87654321-4321-4321-4321-210987654321", "csv_data": "Date,Description,Amount\n2025-10-20,Amazon,-23.47\n2025-10-22,Coffee Shop,-4.50\n2025-10-23,Grocery Store,-67.89", "statement_balance": -560.38, "statement_start_date": "2025-10-01", "statement_end_date": "2025-10-31", "auto_create_transactions": true, "dry_run": true } } ``` **Example Response (truncated):** ```json { "content": [ { "type": "text", "text": "šŸ“Š Checking Account Reconciliation Report\nStatement Range: 2025-10-01 to 2025-10-31\n\n• YNAB Cleared Balance: -$899.02\n• Statement Balance: -$921.24\nāŒ Discrepancy: $22.22 (Statement shows more owed than YNAB)\n\nMatches: 5 auto, 1 suggested, 1 unmatched bank, 0 unmatched YNAB\n\nInsights:\n• [WARNING] 1 unmatched transaction at $22.22\n\nNext Steps:\n• Review 5 auto-matched transactions for approval\n• Add missing bank transaction\n\nDry run only — no YNAB changes were applied." }, { "type": "text", "text": "{\n \"version\": \"2.0\",\n \"schema_url\": \"https://raw.githubusercontent.com/dizzlkheinz/ynab-mcp-mcpb/master/docs/schemas/reconciliation-v2.json\",\n \"summary\": {\n \"bank_transactions_count\": 7,\n \"auto_matched\": 5,\n \"current_cleared_balance\": {\n \"value_milliunits\": -899020,\n \"value_display\": \"-$899.02\",\n \"currency\": \"USD\",\n \"direction\": \"debit\"\n },\n \"discrepancy\": {\n \"value_display\": \"$22.22\"\n }\n },\n \"balance\": {\n \"discrepancy_direction\": \"bank_higher\"\n },\n \"csv_format\": {\n \"delimiter\": \",\",\n \"decimal_separator\": \".\",\n \"thousands_separator\": null,\n \"date_format\": \"MM/DD/YYYY\",\n \"header_row\": true,\n \"date_column\": \"Date\",\n \"amount_column\": \"Amount\",\n \"payee_column\": \"Description\"\n },\n \"insights\": [ { \"id\": \"repeat-22.22\", \"type\": \"repeat_amount\" } ],\n \"matches\": { ... },\n \"unmatched\": { ... },\n \"execution\": {\n \"summary\": {\n \"matches_found\": 6,\n \"transactions_created\": 1,\n \"transactions_updated\": 2,\n \"dry_run\": false\n },\n \"account_balance\": {\n \"before\": { \"cleared_balance\": { \"value_display\": \"-$899.02\" }, ... },\n \"after\": { \"cleared_balance\": { \"value_display\": \"-$921.24\" }, ... }\n },\n \"recommendations\": [\"Review EvoCarShare discrepancy\"]\n }\n}" } ] } ``` When execution flags are enabled and `dry_run` is `false`, the structured payload includes an `execution` block with created/updated transactions, recommendations, and MoneyValue snapshots. The human narrative also summarizes applied actions. **Key Output Sections:** - `summary` – counts and MoneyValue balances for the statement window - `balance` – MoneyValue snapshots plus discrepancy direction (`bank_higher`, `ynab_higher`, or `balanced`) - `insights` – repeat-amount, near-match, and anomaly callouts with evidence - `next_steps` – ordered suggestions for assistants to surface - `matches`, `unmatched` – detailed transaction lists with MoneyValue fields for amounts - `execution` (optional) – action totals, recommendations, and balance reconciliation metrics (MoneyValue) - `recommendations` (optional) – actionable suggestions with complete parameters for executing YNAB tool calls ### Recommendations Field The `reconcile_account_v2` tool now includes an optional `recommendations` array with actionable suggestions for resolving discrepancies. #### Recommendation Types **Create Transaction** ```json { "id": "rec-123", "action_type": "create_transaction", "priority": "high", "confidence": 0.95, "message": "Create transaction for EvoCarShare", "reason": "This transaction exactly matches your $22.22 discrepancy", "estimated_impact": { "value": 22.22, "value_display": "$22.22", "currency": "USD" }, "account_id": "abc123", "parameters": { "account_id": "abc123", "date": "2024-01-15", "amount": 22.22, "payee_name": "EvoCarShare", "memo": "Car rental", "cleared": "cleared", "approved": true } } ``` **Update Cleared Status** ```json { "id": "rec-456", "action_type": "update_cleared", "priority": "low", "confidence": 0.6, "message": "Mark transaction as cleared", "parameters": { "transaction_id": "ynab-txn-789", "cleared": "cleared" } } ``` **Review Duplicate** ```json { "id": "rec-789", "action_type": "review_duplicate", "priority": "medium", "confidence": 0.7, "message": "Review possible duplicate", "parameters": { "candidate_ids": ["ynab-1", "ynab-2"], "suggested_match_id": "ynab-1" } } ``` #### Executing Recommendations Recommendations include complete parameters for YNAB MCP tool calls: **CRITICAL**: Recommendation `parameters.amount` values are already in **milliunits** (YNAB's internal format where 1 dollar = 1000 milliunits). Pass them through directly when calling `create_transaction`. `estimated_impact.value` remains in decimal dollars for human readability. ```typescript // For create_transaction recommendations: // Note: Recommendation amounts are already in milliunits const rec = recommendations.find(r => r.action_type === 'create_transaction'); if (rec) { await create_transaction({ budget_id: 'your-budget-id', ...rec.parameters }); } // For update_cleared recommendations: const updateRec = recommendations.find(r => r.action_type === 'update_cleared'); if (updateRec) { await update_transaction({ budget_id: 'your-budget-id', transaction_id: updateRec.parameters.transaction_id, transaction: { cleared: updateRec.parameters.cleared } }); } ``` #### Recommendation Priority - **High**: Exact matches with 90%+ confidence, resolve immediately - **Medium**: Likely matches with 60-89% confidence, review before executing - **Low**: Suggestions requiring manual review, investigate further #### Best Practices for Executing Recommendations **Execution Order** Process recommendations in the order they're returned (already sorted by priority and confidence): ```typescript for (const rec of recommendations) { // High confidence (>0.9) can often be auto-executed if (rec.confidence > 0.9 && rec.action_type === 'create_transaction') { await executeRecommendation(rec); } else { // Lower confidence should be reviewed await reviewAndExecute(rec); } } ``` **Batch Execution** For multiple recommendations, execute in batches with review checkpoints: ```typescript // Group by action type const groups = { create: recommendations.filter(r => r.action_type === 'create_transaction'), update: recommendations.filter(r => r.action_type === 'update_cleared'), review: recommendations.filter(r => r.action_type === 'manual_review'), }; // Execute high-confidence creates first for (const rec of groups.create.filter(r => r.confidence > 0.9)) { await create_transaction({ budget_id: budgetId, ...rec.parameters }); } // Review checkpoint: verify balance improvement const updatedAnalysis = await reconcile_account_v2({ ... }); console.log('Balance after creates:', updatedAnalysis.balance_info.discrepancy); ``` **Error Handling and Rollback** Track executed recommendations for potential rollback: ```typescript const executionLog = []; try { for (const rec of recommendations) { if (rec.action_type === 'create_transaction') { const result = await create_transaction({ budget_id: budgetId, ...rec.parameters }); executionLog.push({ recommendation_id: rec.id, transaction_id: result.transaction.id, action: 'create_transaction' }); } } } catch (error) { // Rollback: delete created transactions for (const log of executionLog.reverse()) { if (log.action === 'create_transaction') { await delete_transaction({ budget_id: budgetId, transaction_id: log.transaction_id }); } } throw error; } ``` **Verification After Execution** Always re-run reconciliation after executing recommendations to verify balance improvement: ```typescript // Execute recommendations await executeRecommendations(recommendations); // Verify discrepancy resolved const verifyAnalysis = await reconcile_account_v2({ budget_id: budgetId, account_id: accountId, csv_data: csvData, statement_balance: statementBalance, statement_date: statementDate }); const beforeDiscrepancy = originalAnalysis.balance_info.discrepancy.value; const afterDiscrepancy = verifyAnalysis.balance_info.discrepancy.value; if (Math.abs(afterDiscrepancy) >= Math.abs(beforeDiscrepancy)) { console.warn('Discrepancy not improved - review executed recommendations'); } ``` **Handling Manual Review Recommendations** Manual review recommendations require investigation before action: ```typescript for (const rec of recommendations.filter(r => r.action_type === 'manual_review')) { console.log(`\n=== ${rec.message} ===`); console.log(`Reason: ${rec.reason}`); console.log(`Issue type: ${rec.parameters.issue_type}`); if (rec.parameters.related_transactions) { console.log('\nRelated transactions:'); for (const txn of rec.parameters.related_transactions) { console.log(` - [${txn.source}] ${txn.description} (ID: ${txn.id})`); } } // Fetch full details for investigation for (const txn of rec.parameters.related_transactions || []) { if (txn.source === 'ynab') { const details = await get_transaction({ budget_id: budgetId, transaction_id: txn.id }); console.log(` Details:`, JSON.stringify(details, null, 2)); } } } ``` **Progressive Execution Strategy** For large discrepancies with many recommendations: 1. **Execute high-confidence creates** (confidence > 0.9, action_type = create_transaction) 2. **Re-run reconciliation** to verify progress 3. **Review remaining discrepancy** and adjust strategy 4. **Process medium-confidence items** with manual review 5. **Final verification** before marking account as reconciled ### get_transaction Gets detailed information for a specific transaction. **Parameters:** - `budget_id` (string, optional): The ID of the budget. Omit to use the default budget - `transaction_id` (string, required): The ID of the transaction **Example Request:** ```json { "name": "get_transaction", "arguments": { "budget_id": "12345678-1234-1234-1234-123456789012", "transaction_id": "transaction-id" } } ``` ### create_transaction Creates a new transaction in the specified budget and account. **Parameters:** - `budget_id` (string, optional): The ID of the budget. Omit to use the default budget - `account_id` (string, required): The ID of the account - `amount` (number, required): Transaction amount in integer milliunits (negative for outflows) - `date` (string, required): Transaction date in ISO format (YYYY-MM-DD) - `payee_name` (string, optional): The payee name - `payee_id` (string, optional): The payee ID - `category_id` (string, optional): The category ID - `memo` (string, optional): Transaction memo - `cleared` (string, optional): Transaction cleared status (`cleared`, `uncleared`, `reconciled`) - `approved` (boolean, optional): Whether the transaction is approved - `flag_color` (string, optional): Transaction flag color (`red`, `orange`, `yellow`, `green`, `blue`, `purple`) - `dry_run` (boolean, optional): Validate and return simulated result; no API call - `subtransactions` (array, optional): Split line items; each entry accepts `amount` (integer milliunits), plus optional `memo`, `category_id`, `payee_id`, and `payee_name` When `subtransactions` are supplied, their `amount` values must sum to the parent `amount` in milliunits, matching YNAB API requirements. Use `subtransactions` for manual split transactions. Use `create_receipt_split_transaction` when you have itemized receipt data and want proportional tax allocation handled automatically. Advanced: `import_id` is supported, but it is intentionally not part of normal guidance. Usually omit it if you want the transaction to remain eligible for later bank-import matching. **Example Request:** ```json { "name": "create_transaction", "arguments": { "budget_id": "12345678-1234-1234-1234-123456789012", "account_id": "87654321-4321-4321-4321-210987654321", "amount": -5000, "date": "2024-01-15", "payee_name": "Coffee Shop", "category_id": "category-id", "memo": "Morning coffee", "cleared": "cleared", "approved": true } } ``` **Split Transaction Example:** ```json { "name": "create_transaction", "arguments": { "budget_id": "12345678-1234-1234-1234-123456789012", "account_id": "87654321-4321-4321-4321-210987654321", "amount": -125000, "date": "2024-02-01", "memo": "Rent and utilities", "subtransactions": [ { "amount": -100000, "category_id": "rent-category", "memo": "Rent" }, { "amount": -25000, "category_id": "utilities-category", "memo": "Utilities" } ] } } ``` ### create_receipt_split_transaction Creates a split transaction from categorized receipt data and allocates taxes proportionally across the selected categories. Use this helper after the user has confirmed the receipt breakdown and category assignments. For generic manual splits without receipt-tax logic, use `create_transaction` with `subtransactions`. **Parameters:** - `budget_id` (string, optional): The ID of the budget. Omit to use the default budget - `account_id` (string, required): The ID of the account - `payee_name` (string, required): Payee to assign to the transaction (e.g., the store name) - `date` (string, optional): Transaction date in ISO format (defaults to today when omitted) - `memo` (string, optional): Memo applied to the parent transaction - `receipt_subtotal` (number, optional): Pre-tax subtotal for validation (calculated automatically if omitted) - `receipt_tax` (number, required): Total tax collected on the receipt - `receipt_total` (number, required): Final total including tax - `categories` (array, required): Categorized line items. Each entry accepts: - `category_id` (string, required) - `category_name` (string, optional, used for tax memo labels) - `items` (array, required): Each item includes `name` (string), `amount` (number), optional `quantity` (number), and optional `memo` (string) - `cleared` (string, optional): Cleared status (`cleared`, `uncleared`, `reconciled`). Defaults to `uncleared` - `approved` (boolean, optional): Whether the transaction should be marked approved - `flag_color` (string, optional): Flag color (`red`, `orange`, `yellow`, `green`, `blue`, `purple`) - `dry_run` (boolean, optional): When true, returns a preview without calling YNAB **Example Request:** ```json { "name": "create_receipt_split_transaction", "arguments": { "budget_id": "12345678-1234-1234-1234-123456789012", "account_id": "87654321-4321-4321-4321-210987654321", "payee_name": "IKEA", "date": "2025-10-13", "memo": "Receipt import", "receipt_subtotal": 112.34, "receipt_tax": 11.84, "receipt_total": 124.18, "categories": [ { "category_id": "baby-stuff", "category_name": "Baby Stuff", "items": [ { "name": "Crib pillow", "amount": 12.99 }, { "name": "Bed linen", "amount": 24.99 } ] }, { "category_id": "home-maintenance", "category_name": "Home Maintenance", "items": [ { "name": "Teapot", "amount": 19.99 }, { "name": "Toothbrush holder", "amount": 3.99 } ] } ] } } ``` **Example Response:** ```json { "transaction": { "id": "new-transaction-456", "amount": -124.18, "payee_name": "IKEA", "cleared": "uncleared", "subtransactions": [ { "memo": "Crib pillow", "amount": -12.99, "category_id": "baby-stuff" }, { "memo": "Bed linen", "amount": -24.99, "category_id": "baby-stuff" }, { "memo": "Tax - Baby Stuff", "amount": -6.11, "category_id": "baby-stuff" }, { "memo": "Teapot", "amount": -19.99, "category_id": "home-maintenance" }, { "memo": "Toothbrush holder", "amount": -3.99, "category_id": "home-maintenance" }, { "memo": "Tax - Home Maintenance", "amount": -5.99, "category_id": "home-maintenance" } ], "account_balance": 2534.87, "account_cleared_balance": 2450.22 }, "receipt_summary": { "subtotal": 112.34, "tax": 11.84, "total": 124.18, "categories": [ { "category_id": "baby-stuff", "category_name": "Baby Stuff", "subtotal": 37.98, "tax": 6.11, "total": 44.09 }, { "category_id": "home-maintenance", "category_name": "Home Maintenance", "subtotal": 74.36, "tax": 5.73, "total": 80.09 } ] } } ``` ### update_transaction Updates an existing transaction. **Parameters:** - `budget_id` (string, optional): The ID of the budget. Omit to use the default budget - `transaction_id` (string, required): The ID of the transaction to update - `account_id` (string, optional): Update the account ID - `amount` (number, optional): Update the amount in integer milliunits - `date` (string, optional): Update the date (YYYY-MM-DD) - `payee_name` (string, optional): Update the payee name - `payee_id` (string, optional): Update the payee ID - `category_id` (string, optional): Update the category ID - `memo` (string, optional): Update the memo - `cleared` (string, optional): Update the cleared status - `approved` (boolean, optional): Update the approved status - `flag_color` (string, optional): Update the flag color - `dry_run` (boolean, optional): Validate and return simulated result; no API call **Example Request:** ```json { "name": "update_transaction", "arguments": { "budget_id": "12345678-1234-1234-1234-123456789012", "transaction_id": "transaction-id", "amount": -6000, "memo": "Updated memo", "flag_color": "red" } } ``` ### delete_transaction Deletes a transaction from the specified budget. **Parameters:** - `budget_id` (string, optional): The ID of the budget. Omit to use the default budget - `transaction_id` (string, required): The ID of the transaction to delete - `dry_run` (boolean, optional): Validate and return simulated result; no API call **Example Request:** ```json { "name": "delete_transaction", "arguments": { "budget_id": "12345678-1234-1234-1234-123456789012", "transaction_id": "transaction-id" } } ``` ## Category Management Tools ### list_categories Lists all categories for a specific budget. **Parameters:** - `budget_id` (string, optional): The ID of the budget. Omit to use the default budget **Example Request:** ```json { "name": "list_categories", "arguments": { "budget_id": "12345678-1234-1234-1234-123456789012" } } ``` **Example Response:** ```json { "content": [ { "type": "text", "text": "{\n \"category_groups\": [\n {\n \"id\": \"group-id\",\n \"name\": \"Monthly Bills\",\n \"hidden\": false,\n \"deleted\": false,\n \"categories\": [\n {\n \"id\": \"category-id\",\n \"category_group_id\": \"group-id\",\n \"name\": \"Rent/Mortgage\",\n \"hidden\": false,\n \"original_category_group_id\": null,\n \"note\": null,\n \"budgeted\": 150.0,\n \"activity\": -150.0,\n \"balance\": 0,\n \"goal_type\": null,\n \"goal_creation_month\": null,\n \"goal_target\": null,\n \"goal_target_month\": null,\n \"goal_percentage_complete\": null,\n \"goal_months_to_budget\": null,\n \"goal_under_funded\": null,\n \"goal_overall_funded\": null,\n \"goal_overall_left\": null,\n \"deleted\": false\n }\n ]\n }\n ]\n}" } ] } ``` ### get_category Gets detailed information for a specific category. **Parameters:** - `budget_id` (string, optional): The ID of the budget. Omit to use the default budget - `category_id` (string, required): The ID of the category ### update_category Updates the budgeted amount for a category in the current month. **Parameters:** - `budget_id` (string, optional): The ID of the budget. Omit to use the default budget - `category_id` (string, required): The ID of the category - `budgeted` (number, required): The budgeted amount in integer milliunits - `dry_run` (boolean, optional): Validate and return simulated result; no API call **Example Request:** ```json { "name": "update_category", "arguments": { "budget_id": "12345678-1234-1234-1234-123456789012", "category_id": "category-id", "budgeted": 50000 } } ``` ## Payee Management Tools ### list_payees Lists all payees for a specific budget. **Parameters:** - `budget_id` (string, optional): The ID of the budget. Omit to use the default budget **Example Request:** ```json { "name": "list_payees", "arguments": { "budget_id": "12345678-1234-1234-1234-123456789012" } } ``` ### get_payee Gets detailed information for a specific payee. **Parameters:** - `budget_id` (string, optional): The ID of the budget. Omit to use the default budget - `payee_id` (string, required): The ID of the payee ## Monthly Data Tools ### get_month Gets budget data for a specific month. **Parameters:** - `budget_id` (string, optional): The ID of the budget. Omit to use the default budget - `month` (string, required): The month in ISO format (YYYY-MM-DD, typically first day of month) **Example Request:** ```json { "name": "get_month", "arguments": { "budget_id": "12345678-1234-1234-1234-123456789012", "month": "2024-01-01" } } ``` ### list_months Lists all months summary data for a budget. **Parameters:** - `budget_id` (string, optional): The ID of the budget. Omit to use the default budget ## Utility Tools ### get_user Gets information about the authenticated user. **Parameters:** None **Example Request:** ```json { "name": "get_user", "arguments": {} } ``` **Example Response:** ```json { "content": [ { "type": "text", "text": "{\n \"user\": {\n \"id\": \"user-id\",\n \"email\": \"user@example.com\",\n \"trial_expires_on\": null,\n \"subscription\": {\n \"trial_expires_on\": null,\n \"cancelled_at\": null,\n \"date_first_current\": \"2020-01-01T00:00:00.000Z\",\n \"frequency\": \"annually\"\n }\n }\n}" } ] } ``` ## Diagnostic Tools These tools help inspect the server, environment, and performance. They do not modify YNAB data. ### diagnostic_info Returns comprehensive diagnostic information about the MCP server with flexible parameter control. **Parameters:** - `include_memory` (boolean, optional): Include memory usage statistics (default: true) - `include_environment` (boolean, optional): Include environment and token status (default: true) - `include_server` (boolean, optional): Include server version and runtime info (default: true) - `include_security` (boolean, optional): Include security and rate limiting stats (default: true) - `include_cache` (boolean, optional): Include cache statistics (default: true) **Example Request (all sections):** ```json { "name": "diagnostic_info", "arguments": {} } ``` **Example Request (selective sections):** ```json { "name": "diagnostic_info", "arguments": { "include_memory": true, "include_server": true, "include_security": false, "include_cache": false, "include_environment": false } } ``` **Example Response:** ```json { "content": [ { "type": "text", "text": "{\n \"timestamp\": \"2024-01-15T10:30:00.000Z\",\n \"server\": {\n \"name\": \"ynab-mcp-server\",\n \"version\": \"0.6.0\",\n \"node_version\": \"v20.10.0\",\n \"platform\": \"win32\",\n \"arch\": \"x64\",\n \"pid\": 12345,\n \"uptime_ms\": 3600000,\n \"uptime_readable\": \"1h 0m 0s\",\n \"env\": {\n \"node_env\": \"development\",\n }\n },\n \"memory\": {\n \"rss_mb\": 45.2,\n \"heap_used_mb\": 32.1,\n \"heap_total_mb\": 40.5,\n \"external_mb\": 2.1,\n \"array_buffers_mb\": 0.5,\n \"description\": {\n \"rss\": \"Resident Set Size - total memory allocated for the process\",\n \"heap_used\": \"Used heap memory (objects, closures, etc.)\",\n \"heap_total\": \"Total heap memory allocated\",\n \"external\": \"Memory used by C++ objects bound to JavaScript objects\",\n \"array_buffers\": \"Memory allocated for ArrayBuffer and SharedArrayBuffer\"\n }\n },\n \"environment\": {\n \"token_present\": true,\n \"token_length\": 64,\n \"token_preview\": \"abcd...xyz\",\n \"ynab_env_keys_present\": [\"YNAB_ACCESS_TOKEN\"],\n \"working_directory\": \"/path/to/project\"\n },\n \"security\": {\n \"requests_processed\": 1250,\n \"rate_limit_hits\": 0,\n \"errors_logged\": 2\n },\n \"cache\": {\n \"entries\": 15,\n \"estimated_size_kb\": 128,\n \"keys\": [\"budget_123\", \"account_456\"]\n }\n}" } ] } ``` ### clear_cache Clears the in-memory cache. Safe; does not modify YNAB data. **Parameters:** None Example Request: ```json { "name": "clear_cache", "arguments": {} } ``` ## Error Handling All tools implement comprehensive error handling with consistent error response formats. ### Error Response Format ```json { "content": [ { "type": "text", "text": "{\n \"error\": {\n \"code\": \"ERROR_CODE\",\n \"message\": \"Human-readable error message\",\n \"tool\": \"tool_name\",\n \"operation\": \"operation_description\"\n }\n}" } ] } ``` ### Common Error Types #### Authentication Errors (401) **Cause**: Invalid or expired YNAB access token **Example Response:** ```json { "error": { "code": "AUTHENTICATION_ERROR", "message": "Invalid or expired YNAB access token. Please check your YNAB_ACCESS_TOKEN environment variable.", "tool": "list_budgets", "operation": "listing budgets" } } ``` **Solutions:** - Verify the `YNAB_ACCESS_TOKEN` environment variable is set correctly - Check if the token has expired in YNAB Developer Settings - Generate a new token if necessary #### Authorization Errors (403) **Cause**: Insufficient permissions for the requested operation **Example Response:** ```json { "error": { "code": "AUTHORIZATION_ERROR", "message": "Insufficient permissions to access this resource.", "tool": "get_budget", "operation": "retrieving budget details" } } ``` #### Resource Not Found (404) **Cause**: Invalid budget_id, account_id, transaction_id, etc. **Example Response:** ```json { "error": { "code": "RESOURCE_NOT_FOUND", "message": "The requested resource was not found. Please verify the ID is correct.", "tool": "get_account", "operation": "retrieving account details" } } ``` **Solutions:** - Verify the ID is correct and exists - Use list operations to find valid IDs - Check if the resource has been deleted #### Rate Limiting (429) **Cause**: Too many requests to YNAB API **Example Response:** ```json { "error": { "code": "RATE_LIMIT_EXCEEDED", "message": "Rate limit exceeded. Please wait before making more requests.", "tool": "list_transactions", "operation": "listing transactions" } } ``` **Solutions:** - Wait before making additional requests - Implement exponential backoff in your client - Reduce the frequency of API calls #### Validation Errors **Cause**: Invalid parameters provided to tools **Example Response:** ```json { "error": { "code": "VALIDATION_ERROR", "message": "Invalid parameters: date must be in ISO format (YYYY-MM-DD)", "tool": "create_transaction", "operation": "creating transaction" } } ``` **Solutions:** - Check parameter formats and types - Refer to the tool documentation for valid values - Ensure required parameters are provided #### Server Errors (500) **Cause**: YNAB service issues or internal server errors **Example Response:** ```json { "error": { "code": "SERVER_ERROR", "message": "An internal server error occurred. Please try again later.", "tool": "get_budget", "operation": "retrieving budget details" } } ``` **Solutions:** - Retry the request after a short delay - Check YNAB service status - Contact support if the issue persists ## Best Practices ### 1. Error Handling Always handle errors gracefully in your client applications: ```javascript try { const result = await mcpClient.callTool('list_budgets', {}); // Process successful result } catch (error) { // Handle error based on error code if (error.code === 'AUTHENTICATION_ERROR') { // Prompt user to update token } else if (error.code === 'RATE_LIMIT_EXCEEDED') { // Implement retry with backoff } } ``` ### 2. Parameter Validation Validate parameters before making tool calls: ```javascript // Validate date format const dateRegex = /^\d{4}-\d{2}-\d{2}$/; if (!dateRegex.test(date)) { throw new Error('Date must be in YYYY-MM-DD format'); } // Validate a create_transaction amount is in integer milliunits if (!Number.isInteger(amount)) { throw new Error('Amount must be an integer in milliunits'); } ``` ### 3. Efficient Data Retrieval Use filtering parameters to reduce data transfer: ```javascript // Instead of getting all transactions and filtering client-side const allTransactions = await mcpClient.callTool('list_transactions', { budget_id: budgetId }); // Use server-side filtering const recentTransactions = await mcpClient.callTool('list_transactions', { budget_id: budgetId, since_date: '2024-01-01', account_id: specificAccountId }); ``` ### 4. Amount Handling Responses are returned in dollars, but some write-tool inputs must be sent in milliunits: ```javascript // All returned amounts are in dollars - no conversion needed const accounts = await mcpClient.callTool('list_accounts', { budget_id: budgetId }); console.log(`Balance: $${accounts.accounts[0].balance}`); // Balance: $1234.56 // When creating transactions, provide amounts in integer milliunits await mcpClient.callTool('create_transaction', { budget_id: budgetId, account_id: accountId, amount: -50250, // Negative for outflows date: '2024-01-15', payee_name: 'Coffee Shop' }); ``` ### 5. Caching Strategies Cache relatively static data to improve performance: ```javascript // Cache budget and account information const budgets = await mcpClient.callTool('list_budgets', {}); // Cache for 1 hour const accounts = await mcpClient.callTool('list_accounts', { budget_id: budgetId }); // Cache for 30 minutes // Don't cache frequently changing data like transactions const transactions = await mcpClient.callTool('list_transactions', { budget_id: budgetId, since_date: today }); // Always fetch fresh ``` This API reference provides comprehensive documentation for all available tools. For additional information, see the [Developer Guide](DEVELOPER.md) for best practices and common usage patterns.