Skip to main content
Glama
YNAB MCP Server

YNAB MCP Server

by dgalarza

YNAB MCP Server

MCP server for YNAB (You Need A Budget) integration, enabling AI assistants to help manage your budget.

Setup

  1. Install dependencies with uv:

uv sync
  1. Get your YNAB Personal Access Token:

  2. Create .env file:

cp .env.example .env
  1. Add your token to .env:

YNAB_ACCESS_TOKEN=your_token_here

Related MCP server: YNAB MCP Server

Running the Server

uv run python -m ynab_mcp

Installing in Claude Code

Add to your Claude Code configuration:

claude mcp add ynab -- uv --directory /path/to/ynab-mcp run python -m ynab_mcp

Or add to .claude.json manually in the mcpServers section:

{
  "ynab": {
    "type": "stdio",
    "command": "uv",
    "args": ["--directory", "/home/your-user/Code/ynab-mcp", "run", "python", "-m", "ynab_mcp"],
    "env": {}
  }
}

Available Tools

Health & Diagnostics

  • health_check - Check server health and YNAB API connectivity

Account Management

  • get_accounts - Get all accounts for a budget

Category & Budget Management

  • get_category - Get a single category with full details including goal information

  • get_categories - Get all categories for a budget (lightweight list)

  • get_budget_summary - Get budget summary for a specific month

  • update_category - Update category properties (name, note, group, or goal target)

  • update_category_budget - Update the budgeted amount for a category in a specific month

  • move_category_funds - Move funds from one category to another

Transaction Management

  • get_transaction - Get a single transaction with full details including subtransactions

  • get_transactions - Get transactions with pagination and filtering (date range, account, category, limit, page)

  • search_transactions - Search transactions by text in payee name or memo

  • create_transaction - Create a new transaction

  • update_transaction - Update an existing transaction (⚠️ cannot add/modify splits on existing transactions)

  • get_unapproved_transactions - Get all unapproved transactions that need review

Split Transaction Management

  • create_split_transaction - Create a new transaction split across multiple categories

  • prepare_split_for_matching - Split an existing imported transaction by creating a matching split for manual reconciliation in YNAB UI

Scheduled Transactions

  • get_scheduled_transactions - List all scheduled transactions

  • create_scheduled_transaction - Create future/recurring transactions

  • delete_scheduled_transaction - Delete scheduled transactions

Analytics & Reporting

  • get_category_spending_summary - Get spending summary with optional terminal graph visualization

  • compare_spending_by_year - Year-over-year spending comparison with optional graph

Features

Robust Error Handling

  • Custom exception classes for different error types

  • Automatic retry logic with exponential backoff

  • Rate limit detection and handling (respects Retry-After headers)

  • Comprehensive logging (configurable via LOG_LEVEL environment variable)

Performance & Reliability

  • HTTP connection pooling for better performance

  • Input validation on all parameters

  • Timeout configuration (30s default)

  • Milliunits conversion handled automatically

Split Transaction Support

Split transactions allow you to allocate a single transaction across multiple categories (e.g., splitting a grocery store purchase into "Groceries" and "Household Items").

Creating New Split Transactions:

create_split_transaction(
  budget_id="last-used",
  account_id="account-id",
  date="2025-10-06",
  amount=-80.00,
  subtransactions='[{"amount": -50.00, "category_id": "groceries-id", "memo": "Food"}, {"amount": -30.00, "category_id": "household-id", "memo": "Supplies"}]'
)

Splitting Existing Imported Transactions: Due to YNAB API limitations, you cannot directly modify an existing transaction to add splits. Instead, use prepare_split_for_matching:

  1. Call prepare_split_for_matching with the existing transaction ID and desired splits

  2. The tool fetches the original transaction details and creates a new unapproved split transaction

  3. Go to YNAB (web or mobile) and manually match the two transactions

  4. YNAB merges them into one split transaction, preserving the bank import connection

Important Limitations:

  • Cannot add or update subtransactions on existing transactions via the API

  • Cannot convert a regular transaction into a split transaction directly

  • Once created, subtransactions cannot be modified via the API

  • Split transaction dates and amounts cannot be changed after creation

Analytics & Visualization

  • Server-side spending aggregation to reduce context usage

  • Optional terminal-based graph visualization using termgraph

  • Year-over-year spending comparisons

  • Monthly spending summaries

Configuration

Environment Variables

  • YNAB_ACCESS_TOKEN (required) - Your YNAB Personal Access Token

  • LOG_LEVEL (optional) - Logging level (DEBUG, INFO, WARNING, ERROR, default: INFO)

Troubleshooting

MCP Server Not Connecting

  1. Run the health check tool: health_check

  2. Check that YNAB_ACCESS_TOKEN is set in your .env file

  3. Verify the token is valid at https://app.ynab.com/settings/developer

  4. Check logs with LOG_LEVEL=DEBUG

Rate Limit Errors

The YNAB API has a rate limit of 200 requests per hour. The server automatically:

  • Detects 429 (rate limit) responses

  • Retries with exponential backoff

  • Respects Retry-After headers

If you consistently hit rate limits, consider:

  • Using analytics tools (get_category_spending_summary, compare_spending_by_year) instead of fetching all transactions

  • Reducing the frequency of requests

  • Caching results when possible

Large Response Sizes

For queries spanning long time periods, use:

  • get_category_spending_summary - Returns aggregated summary instead of all transactions

  • compare_spending_by_year - Returns year-over-year totals instead of individual transactions

  • Pagination with get_transactions (use limit and page parameters)

Development

Running Tests

Install dev dependencies:

uv sync --extra dev

Run tests:

uv run pytest tests/ -v

Code Quality

The codebase includes:

  • Input validation on all parameters

  • Custom exception classes for proper error handling

  • Comprehensive logging

  • Type hints with from __future__ import annotations

  • Connection pooling for HTTP requests

  • Automatic retry logic for transient failures

Available Tools

21 tools
compare_spending_by_yearB

Compare spending for a category across multiple years.

Args:
    budget_id: The ID of the budget (use 'last-used' for default budget)
    category_id: The category ID to analyze
    start_year: Starting year (e.g., 2020)
    num_years: Number of years to compare (default: 5)
    include_graph: Include terminal graph visualization (default: True)

Returns:
    JSON string with year-over-year comparison including totals, changes, percentage changes, and optional graph

Inputs: budget_id (required), category_id (required), start_year (required), include_graph, +1 more. Returns: result

create_scheduled_transactionA

Create a scheduled transaction (for future/recurring transactions).

Args:
    budget_id: The ID of the budget (use 'last-used' for default budget)
    account_id: The account ID for this scheduled transaction
    date_first: The first date the transaction should occur (YYYY-MM-DD format)
    frequency: Frequency (never, daily, weekly, everyOtherWeek, twiceAMonth, every4Weeks, monthly, everyOtherMonth, every3Months, every4Months, twiceAYear, yearly, everyOtherYear)
    amount: Transaction amount (positive for inflow, negative for outflow)
    payee_name: Name of the payee (optional)
    category_id: Category ID (optional)
    memo: Transaction memo (optional)
    flag_color: Flag color - red, orange, yellow, green, blue, purple (optional)

Returns:
    JSON string with the created scheduled transaction

Inputs: account_id (required), amount (required), budget_id (required), date_first (required), +5 more. Returns: result

create_split_transactionA

Create a NEW split transaction with multiple category allocations.

This tool creates a brand new transaction that is split across multiple categories.
It CANNOT be used to add splits to an existing transaction - the YNAB API does not support that.

Args:
    budget_id: The ID of the budget (use 'last-used' for default budget)
    account_id: The account ID for this transaction
    date: Transaction date in YYYY-MM-DD format
    amount: Total transaction amount (positive for inflow, negative for outflow)
    subtransactions: JSON string containing array of subtransactions. Each subtransaction should have:
        - amount (required): The subtransaction amount
        - category_id (optional): Category ID for this split
        - payee_id (optional): Payee ID for this split
        - memo (optional): Memo for this split
        Example: '[{"amount": -50.00, "category_id": "cat1", "memo": "Groceries"}, {"amount": -30.00, "category_id": "cat2", "memo": "Gas"}]'
    payee_name: Name of the payee for the main transaction (optional)
    memo: Transaction memo (optional)
    cleared: Cleared status - 'cleared', 'uncleared', or 'reconciled' (default: 'uncleared')
    approved: Whether the transaction is approved (default: False)

Returns:
    JSON string with the created split transaction

Important Notes:
    - This creates a NEW transaction only - cannot modify existing transactions to add splits
    - The sum of subtransaction amounts should equal the total transaction amount
    - Once created, subtransactions cannot be modified via the API (YNAB limitation)
    - To "split" an existing transaction, you must delete it and create a new split transaction

Inputs: account_id (required), amount (required), budget_id (required), date (required), +5 more. Returns: result

create_transactionB

Create a new transaction.

Args:
    budget_id: The ID of the budget (use 'last-used' for default budget)
    account_id: The account ID for this transaction
    date: Transaction date in YYYY-MM-DD format
    amount: Transaction amount (positive for inflow, negative for outflow)
    payee_name: Name of the payee (optional)
    category_id: Category ID (optional)
    memo: Transaction memo (optional)
    cleared: Cleared status - 'cleared', 'uncleared', or 'reconciled' (default: 'uncleared')
    approved: Whether the transaction is approved (default: False)

Returns:
    JSON string with the created transaction

Inputs: account_id (required), amount (required), budget_id (required), date (required), +5 more. Returns: result

delete_scheduled_transactionB

Delete a scheduled transaction.

Args:
    budget_id: The ID of the budget (use 'last-used' for default budget)
    scheduled_transaction_id: The ID of the scheduled transaction to delete

Returns:
    JSON string with confirmation

Inputs: budget_id (required), scheduled_transaction_id (required). Returns: result

get_accountsB

Get all accounts for a budget.

Args:
    budget_id: The ID of the budget (use 'last-used' for default budget)

Returns:
    JSON string with list of accounts

Inputs: budget_id (required). Returns: result

get_budget_summaryA

Get budget summary for a specific month.

Args:
    budget_id: The ID of the budget (use 'last-used' for default budget)
    month: Month in YYYY-MM-DD format (e.g., 2025-01-01 for January 2025)

Returns:
    JSON string with budget summary including income, budgeted amounts, and category details

Inputs: budget_id (required), month (required). Returns: result

get_categoriesA

Get all categories for a budget.

Args:
    budget_id: The ID of the budget (use 'last-used' for default budget)
    include_hidden: Include hidden categories and groups (default: False)

Returns:
    JSON string with category groups and categories

Inputs: budget_id (required), include_hidden. Returns: result

get_categoryA

Get a single category with full details including goal information.

Args:
    budget_id: The ID of the budget (use 'last-used' for default budget)
    category_id: The category ID

Returns:
    JSON string with category details including goals, budgeted amounts, activity, and balance

Inputs: budget_id (required), category_id (required). Returns: result

get_category_spending_summaryA

Get spending summary for a category over a date range.

Args:
    budget_id: The ID of the budget (use 'last-used' for default budget)
    category_id: The category ID to analyze
    since_date: Start date (YYYY-MM-DD format)
    until_date: End date (YYYY-MM-DD format)
    include_graph: Include terminal graph visualization (default: True)

Returns:
    JSON string with summary including total spent, average per month, transaction count, monthly breakdown, and optional graph

Inputs: budget_id (required), category_id (required), since_date (required), until_date (required), +1 more. Returns: result

get_scheduled_transactionsB

Get all scheduled transactions.

Args:
    budget_id: The ID of the budget (use 'last-used' for default budget)

Returns:
    JSON string with list of scheduled transactions

Inputs: budget_id (required). Returns: result

get_transactionA

Get a single transaction with all details including subtransactions.

Args:
    budget_id: The ID of the budget (use 'last-used' for default budget)
    transaction_id: The ID of the transaction to retrieve

Returns:
    JSON string with the transaction details including subtransactions if it's a split transaction

Inputs: budget_id (required), transaction_id (required). Returns: result

get_transactionsA

Get transactions with optional filtering and pagination.

Args:
    budget_id: The ID of the budget (use 'last-used' for default budget)
    since_date: Only return transactions on or after this date (YYYY-MM-DD format)
    until_date: Only return transactions on or before this date (YYYY-MM-DD format)
    account_id: Filter by account ID (optional)
    category_id: Filter by category ID (optional)
    limit: Number of transactions per page (default: 100, max: 500)
    page: Page number for pagination (1-indexed, default: 1)

Returns:
    JSON string with transactions array and pagination metadata

Note:
    For large date ranges (>1 year), use get_category_spending_summary or
    compare_spending_by_year instead to avoid timeouts and reduce context usage.

Inputs: budget_id (required), account_id, category_id, limit, +3 more. Returns: result

get_unapproved_transactionsA

Get all unapproved transactions that need review.

Args:
    budget_id: The ID of the budget (use 'last-used' for default budget)

Returns:
    JSON string with list of unapproved transactions

Inputs: budget_id (required). Returns: result

health_checkA

Check server health and YNAB API connectivity.

This tool performs a lightweight API call to verify that:
- The MCP server is running
- The YNAB access token is valid
- The YNAB API is reachable

Returns:
    JSON string with health status and connection info

Inputs: no named parameters. Returns: result

move_category_fundsA

Move funds from one category to another in a specific month.

Args:
    budget_id: The ID of the budget (use 'last-used' for default budget)
    month: Month in YYYY-MM-DD format (e.g., 2025-01-01 for January 2025)
    from_category_id: Source category ID to move funds from
    to_category_id: Destination category ID to move funds to
    amount: Amount to move (positive value)

Returns:
    JSON string with updated from and to categories

Inputs: amount (required), budget_id (required), from_category_id (required), month (required), +1 more. Returns: result

prepare_split_for_matchingA

Prepare a split transaction to match with an existing imported transaction.

This tool fetches an existing transaction's details and creates a new UNAPPROVED split
transaction with the same date, amount, account, and payee. You can then manually match
them together in the YNAB web or mobile UI.

Use this when you want to split an imported bank transaction - the new split will be
created as unapproved so you can match it with the original in YNAB's UI.

Args:
    budget_id: The ID of the budget (use 'last-used' for default budget)
    transaction_id: The ID of the existing transaction to split
    subtransactions: JSON string containing array of subtransactions. Each subtransaction should have:
        - amount (required): The subtransaction amount
        - category_id (optional): Category ID for this split
        - payee_id (optional): Payee ID for this split
        - memo (optional): Memo for this split
        Example: '[{"amount": -50.00, "category_id": "cat1", "memo": "Groceries"}, {"amount": -30.00, "category_id": "cat2", "memo": "Gas"}]'

Returns:
    JSON string with original transaction details, new split transaction details, and instructions

Workflow:
    1. This tool fetches the existing transaction details
    2. Creates a new unapproved split transaction with those details
    3. You manually match them in the YNAB UI
    4. YNAB merges them into one split transaction

Note:
    - The new split is created as UNAPPROVED for manual matching
    - The sum of subtransaction amounts should equal the original transaction amount
    - After matching in YNAB UI, the original transaction will become a split transaction

Inputs: budget_id (required), subtransactions (required), transaction_id (required). Returns: result

search_transactionsA

Search for transactions by text in payee name or memo.

Args:
    budget_id: The ID of the budget (use 'last-used' for default budget)
    search_term: Text to search for in payee name or memo (case-insensitive)
    since_date: Only search transactions on or after this date (YYYY-MM-DD format)
    until_date: Only search transactions on or before this date (YYYY-MM-DD format)
    limit: Maximum number of transactions to return (default: 100, max: 500)

Returns:
    JSON string with matching transactions and count

Inputs: budget_id (required), search_term (required), limit, since_date, +1 more. Returns: result

update_categoryA

Update a category's properties (rename, change note, move to different group, or update goal target).

Args:
    budget_id: The ID of the budget (use 'last-used' for default budget)
    category_id: The category ID to update
    name: New name for the category (optional)
    note: New note for the category (optional)
    category_group_id: Move to a different category group ID (optional)
    goal_target: New goal target amount - only works if category already has a goal configured (optional)

Returns:
    JSON string with the updated category

Inputs: budget_id (required), category_id (required), category_group_id, goal_target, +2 more. Returns: result

update_category_budgetA

Update the budgeted amount for a category in a specific month.

Args:
    budget_id: The ID of the budget (use 'last-used' for default budget)
    month: Month in YYYY-MM-DD format (e.g., 2025-01-01 for January 2025)
    category_id: The category ID to update
    budgeted: The budgeted amount to set

Returns:
    JSON string with the updated category

Inputs: budget_id (required), budgeted (required), category_id (required), month (required). Returns: result

update_transactionA

Update an existing transaction.

Args:
    budget_id: The ID of the budget (use 'last-used' for default budget)
    transaction_id: The ID of the transaction to update
    account_id: The account ID (optional - keeps existing if not provided)
    date: Transaction date in YYYY-MM-DD format (optional)
    amount: Transaction amount (optional)
    payee_name: Name of the payee (optional)
    category_id: Category ID (optional)
    memo: Transaction memo (optional)
    cleared: Cleared status - 'cleared', 'uncleared', or 'reconciled' (optional)
    approved: Whether the transaction is approved (optional)

Returns:
    JSON string with the updated transaction

Important Limitations:
    - Cannot add or update subtransactions on existing transactions
    - Cannot convert a regular transaction into a split transaction
    - If the transaction is already a split, its category_id cannot be changed
    - Split transaction dates and amounts cannot be modified
    - To create a split transaction, use create_split_transaction instead

Inputs: budget_id (required), transaction_id (required), account_id, amount, +6 more. Returns: result

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.8/5.0

    Scored across 21 tools

    Disambiguation4/5

    Most tools have distinct purposes with clear boundaries, such as create_transaction vs. create_split_transaction or get_transactions vs. search_transactions. However, some overlap exists between get_category and get_categories, and between get_transaction and get_transactions, which could cause minor confusion for agents, but descriptions help differentiate them.

    Naming Consistency5/5

    Tool names follow a highly consistent verb_noun pattern throughout, such as create_transaction, get_accounts, update_category, and delete_scheduled_transaction. This predictable naming scheme makes it easy for agents to understand and select tools based on their actions and targets.

    Tool Count3/5

    With 21 tools, the count is on the higher side for a budget management server, bordering on heavy but still manageable. It covers extensive functionality, but some tools might be consolidated or omitted to streamline the set without losing core capabilities.

    Completeness5/5

    The tool set provides comprehensive coverage for YNAB's domain, including full CRUD operations for transactions, scheduled transactions, and categories, along with advanced features like spending analysis, fund moving, and health checks. There are no obvious gaps, and agents can handle typical budgeting workflows effectively.

    Maintenance

    ActivityInactive
    ResponsivenessOutdated data

    Related MCP Connectors

    Related MCP Servers

    • F
      license
      Not graded
      quality
      D
      maintenance
      Enables AI assistants to interact with YNAB budgets through natural language. Supports managing accounts, categories, transactions, and budget months with 21 tools for comprehensive budget operations.
      -
    • A
      license
      A
      quality
      D
      maintenance
      Enables interaction with You Need A Budget (YNAB) through their API, allowing users to manage budgets, accounts, categories, transactions, payees, and scheduled transactions through natural language.
      12
      23 npm
      2
      GPL 3.0
    • F
      license
      A
      quality
      C
      maintenance
      Enables users to manage budgets, accounts, categories, and transactions on You Need A Budget (YNAB) through Claude. It supports both core daily budget management and extended operations like bulk transaction creation and historical trend analysis.
      15
      2
      -
    • A
      license
      B
      quality
      A
      maintenance
      Enables AI assistants to interact with YNAB budgets, performing read-only queries by default and optional write operations like creating transactions and managing categories through natural language.
      45
      485 npm
      46
      MIT