YNAB MCP Server
Provides comprehensive integration with YNAB (You Need A Budget) for managing personal finances, including tools for budget management, transaction operations, category organization, split transactions, scheduled transactions, and spending analytics with visualization capabilities.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@YNAB MCP Server show me my unapproved transactions for this month"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
YNAB MCP Server
MCP server for YNAB (You Need A Budget) integration, enabling AI assistants to help manage your budget.
Setup
Install dependencies with
uv:
uv syncGet your YNAB Personal Access Token:
Create a new Personal Access Token
Copy the token
Create
.envfile:
cp .env.example .envAdd your token to
.env:
YNAB_ACCESS_TOKEN=your_token_hereRelated MCP server: YNAB MCP Server
Running the Server
uv run python -m ynab_mcpInstalling in Claude Code
Add to your Claude Code configuration:
claude mcp add ynab -- uv --directory /path/to/ynab-mcp run python -m ynab_mcpOr 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 informationget_categories- Get all categories for a budget (lightweight list)get_budget_summary- Get budget summary for a specific monthupdate_category- Update category properties (name, note, group, or goal target)update_category_budget- Update the budgeted amount for a category in a specific monthmove_category_funds- Move funds from one category to another
Transaction Management
get_transaction- Get a single transaction with full details including subtransactionsget_transactions- Get transactions with pagination and filtering (date range, account, category, limit, page)search_transactions- Search transactions by text in payee name or memocreate_transaction- Create a new transactionupdate_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 categoriesprepare_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 transactionscreate_scheduled_transaction- Create future/recurring transactionsdelete_scheduled_transaction- Delete scheduled transactions
Analytics & Reporting
get_category_spending_summary- Get spending summary with optional terminal graph visualizationcompare_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_LEVELenvironment 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:
Call
prepare_split_for_matchingwith the existing transaction ID and desired splitsThe tool fetches the original transaction details and creates a new unapproved split transaction
Go to YNAB (web or mobile) and manually match the two transactions
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 TokenLOG_LEVEL(optional) - Logging level (DEBUG, INFO, WARNING, ERROR, default: INFO)
Troubleshooting
MCP Server Not Connecting
Run the health check tool:
health_checkCheck that
YNAB_ACCESS_TOKENis set in your.envfileVerify the token is valid at https://app.ynab.com/settings/developer
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-Afterheaders
If you consistently hit rate limits, consider:
Using analytics tools (
get_category_spending_summary,compare_spending_by_year) instead of fetching all transactionsReducing 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 transactionscompare_spending_by_year- Returns year-over-year totals instead of individual transactionsPagination with
get_transactions(uselimitandpageparameters)
Development
Running Tests
Install dev dependencies:
uv sync --extra devRun tests:
uv run pytest tests/ -vCode Quality
The codebase includes:
Input validation on all parameters
Custom exception classes for proper error handling
Comprehensive logging
Type hints with
from __future__ import annotationsConnection pooling for HTTP requests
Automatic retry logic for transient failures
Available Tools
21 toolscompare_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
Scored across 21 tools
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.
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.
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.
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
Related MCP Connectors
Personal finance for AI agents: accounts, budgets, goals, 9-strategy debt payoff, reports. OAuth 2.1
The budget app your AI agent can use. Check budgets and log spending, with no bank logins.
Log, query, and edit expenses, budgets, and accounts in Manilo (formerly Ledgy) from any MCP-compatible AI assistant.
Multi-currency budgeting: read and update your accounts, transactions, categories and budgets.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables 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.-
- AlicenseAqualityDmaintenanceEnables 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.1223 npm2GPL 3.0
- FlicenseAqualityCmaintenanceEnables 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.152-
- AlicenseBqualityAmaintenanceEnables 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.45485 npm46MIT