MCP YNAB Server
The MCP YNAB Server provides access to YNAB (You Need A Budget) functionality through the Model Context Protocol, allowing you to:
View financial data: Check account balances and list transactions
Manage transactions: Create new transactions and find ones needing attention (uncategorized/unapproved)
Work with budgets: List all budgets, set a preferred budget, and access categories
Access detailed information: Retrieve specific transactions by ID and view transaction details including subtransactions
Use MCP integration: Access YNAB data via standardized resources like
ynab://accountsandynab://transactions/{account_id}
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., "@MCP YNAB Server show me my checking account balance"
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.
mcp-ynab
A Model Context Protocol server for the YNAB (You Need A Budget) API. Lets MCP clients (Claude Desktop, Claude Code, custom agents) read your budgets, accounts, and transactions, and create or recategorize transactions through structured tools.
Install
The project is managed with uv and
Task. All Python commands in this repo go through
uv run.
uv sync # install dependencies
task install # install the mcp-ynab CLI into the venvRelated MCP server: ynab-mcp
Configure
Set your YNAB Personal Access Token in the environment (or in a .env file at
the repo root):
export YNAB_API_KEY=your-personal-access-tokenGet a token at https://app.ynab.com/settings/developer.
Quickstart
1. Set your API key
Code Mode is the default surface — it requires your YNAB API key:
export YNAB_API_KEY="your-key-here"Or store it in your OS keychain (the server reads it automatically).
2. Use Code Mode
By default the server exposes two tools: search (discover available operations) and execute (run a snippet against the live YNAB API).
Discover tools:
# In the search tool:
return [t for t in spec if "transaction" in t["name"]]Execute a query:
# In the execute tool:
return await ynab.read.get_budgets()3. Restore the full tool surface (optional)
To access all ~34 direct YNAB tools, set the escape-hatch preference:
set_preference: code_mode_replace_tools = falseRun the server
mcp-ynab # production
task dev # dev mode + MCP Inspector in the browserTools and resources
By default, the public MCP tool surface is intentionally small:
Tool | Purpose |
| Discover available YNAB operations without live API access |
| Run a short Python snippet against the live YNAB API |
| Health check the server |
| Inspect server preferences |
| Update preferences such as mutation or escape-hatch settings |
| Store a YNAB API key in the OS keychain |
| Remove the stored YNAB API key |
| Cache a preferred budget ID for default-targeted calls |
Use search to discover operations:
return [
{"name": tool["name"], "description": tool["description"]}
for tool in spec
if "category" in tool["name"]
]Then call the operation through execute:
categories = await ynab.read.get_categories()
return [
{"name": category.name, "balance": category.balance}
for group in categories
for category in group.categories[:LIMIT]
]Mutating operations live under ynab.write.* and require
code_mode_mutations_enabled=true:
result = await ynab.write.bulk_categorize(assignments=assignments)
return resultThe underlying direct tools still exist in the internal FastMCP registry so
Code Mode can dispatch through ynab.read.*, generate stubs, and build the
search catalog. They are hidden from the public tool list by default. Set
code_mode_replace_tools=false to restore the full direct-tool surface as an
escape hatch.
Representative internal direct tools include:
Read-only internal tools
Tool | Purpose |
| List all budgets in markdown |
| List accounts in a budget, grouped by type with summary |
| Return a single account's current balance in dollars |
| Recent transactions for an account; optional |
| Filter for uncategorized / unapproved transactions |
| All categories in a budget grouped by category group |
Mutating internal tools
Tool | Purpose |
| Create a new transaction in YNAB |
| Assign a category to an existing transaction |
| Cache a preferred budget ID for default-targeted tools |
| Cache a budget's category list locally |
For account transfers and credit-card payments, use the destination account's
transfer payee ID as payee_id when creating or updating a transaction. The
get_payees tool lists transfer payees with their Transfer Account ID.
Do not pass a Transfer : ... value as payee_name; YNAB rejects or treats
that as a regular payee instead of creating a linked transfer.
Resources
ynab://preferences/budget_id— currently preferred budget IDynab://categories/{budget_id}— cached categories for a budgetynab://code-mode/stubs— generated Python stubs for Code Modeynab://code-mode/examples— curated Code Mode snippets
Code Mode
Code Mode exposes execute, a Python execution tool for multi-step YNAB
workflows. It is enabled by default and controlled through the preferences
code_mode_enabled, code_mode_mutations_enabled, and code_mode_replace_tools.
See src/mcp_ynab/code_mode/README.md for usage, wiring instructions, and runner limits.
Development
task fmt # ruff format + check --fix
task lint # ruff check + format --check (no auto-fix)
task typecheck # mypy
task docstrings # interrogate (fails under 80%)
task test # unit tests only (default; integration excluded)
task coverage # unit tests with coverage reportIntegration tests
Integration tests are gated behind pytest.mark.integration and excluded from
the default task test run. They make real calls to your YNAB account, so they
require YNAB_API_KEY.
YNAB_API_KEY=your-token task test:integrationThe default integration suite is read-only. Tests that mutate data (create_transaction, categorize_transaction) require an additional opt-in:
YNAB_API_KEY=your-token YNAB_INTEGRATION_ALLOW_WRITES=1 \
task test:integrationLicense
MIT
Available Tools
8 toolsclear_api_keyAIdempotent
Remove the stored YNAB API key from the OS keychain (env var unaffected).
Inputs: no named parameters. Returns: result
executeADestructive
Execute a Python snippet against the gated ynab.read/ynab.write Code Mode API.
Enabled by default. Mutating calls require ``code_mode_mutations_enabled`` preference
and must use ``ynab.write.*``; eval dry-run mode is the explicit exception. The snippet
is treated as the body of an async function:
``await ynab.read.get_budgets()``, ``return`` directly.
Inputs: code (required), timeout.
get_preferencesARead-onlyIdempotent
Return the current YNAB MCP preferences as a markdown table.
Reads the in-memory ``ynab_resources.preferences`` (which already reflects
the env > preferences.json > defaults source order). The same content is
available as a resource at ``ynab://preferences`` for clients that prefer
to read it that way.
Inputs: no named parameters. Returns: result
pingARead-onlyIdempotent
Verify YNAB API auth by fetching the current user's id.
Useful for confirming that ``YNAB_API_KEY`` is set and valid without
touching budget data.
Inputs: no named parameters. Returns: result
searchARead-onlyIdempotent
Discover available YNAB tools by running a Python snippet against the tool catalog.
The snippet runs in a sandboxed environment with a ``spec`` variable — a list of dicts,
each with keys ``name``, ``namespace`` (``"read"`` or ``"write"``), ``signature``,
``doc``, and ``returns``. Filter or map ``spec`` and return the subset you need.
Example: ``return [t for t in spec if "transaction" in t["name"]]``
No live YNAB API access. Returns the same CodeModeResult shape as execute.
Inputs: code (required).
set_api_keyAIdempotent
Store a YNAB personal access token in the OS keychain.
The token is persisted in the platform keychain (macOS Keychain,
Windows Credential Locker, or Linux Secret Service) under
service=``mcp-ynab`` user=``YNAB_API_KEY``. After this returns, future
requests in this process and future runs will pick the key up via
``_resolve_api_key`` — though the ``YNAB_API_KEY`` env var still wins
if it is set.
Inputs: api_key (required). Returns: result
set_preferenceAIdempotent
Set a single preference and persist it to preferences.json.
``name`` must be one of the ``Preferences`` model fields:
``default_budget_id``, ``category_cache_ttl_minutes``, or
``confirm_before_post``. Bool values accept any of
``1/0/true/false/yes/no/on/off`` (case-insensitive). The empty string is
the documented way to clear ``default_budget_id`` (stored as ``None``);
on a non-Optional field it surfaces as a coercion error.
Note: changes to ``default_budget_id`` here are equivalent to calling
``set_preferred_budget_id``; both write the same field.
Inputs: name (required), value (required). Returns: result
set_preferred_budget_idAIdempotent
Set the preferred YNAB budget ID.
Inputs: budget_id (required). Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 8 tools
Most tools are distinct, but set_preferred_budget_id and set_preference overlap directly, with the description explicitly noting both write the same default_budget_id field. execute and search are also similar in form, though their targets are clearly differentiated by the descriptions.
Tool names consistently use lowercase snake_case with imperative verbs like set, get, clear, and ping. Minor inconsistency exists between get_preferences (plural) and set_preference (singular), but the overall pattern is predictable.
Eight tools is a well-scoped count for this server. Each tool covers a clear concern: auth, key management, preferences, discovery, and dynamic YNAB API execution.
The server covers its configuration and auth lifecycle thoroughly, and execute provides broad access to the YNAB Code Mode API while search enables discovery. The main limitation is that direct YNAB operations are not exposed as first-class tools, requiring agents to construct snippets.
Maintenance
Related MCP Connectors
An MCP server that provides read access to your cloud storage providers, bank accounts and more.
Query your real net worth, spending, transactions, budgets and portfolio from any MCP client.
Hosted remote MCP server for YNAB on Cloudflare Workers with OAuth
The Mercado Pago MCP Server implements the Model Context Protocol to provide AI agents and LLMs with access to Mercado Pago's APIs and tools within compatible development environments. It acts as an intermediary that translates Mercado Pago resources into executable functions (tools) that AI applications can invoke to perform actions and automate flows. The server simplifies integration, enables using documentation to implement or improve code, and optimizes operations through natural language interactions without manual implementations.
Related MCP Servers
- AlicenseAqualityAmaintenanceA Model Context Protocol server that enables AI-powered interaction with YNAB (You Need A Budget) data, allowing users to query their budgets through conversational interfaces.22527 npm168MIT
- AlicenseNot gradedqualityDmaintenanceA Model Context Protocol (MCP) server for interacting with YNAB (You Need A Budget). Provides tools for accessing budget data through MCP-enabled clients like Claude Desktop.4MIT
- AlicenseNot gradedqualityDmaintenanceA Model Context Protocol server that enables interaction with You Need A Budget (YNAB) via their API, allowing users to manage budgets, accounts, categories, and transactions through natural language.2MIT
- FlicenseAqualityBmaintenanceAn MCP server that provides Large Language Models with access to YNAB (You Need A Budget) budgets, allowing them to fetch budget data including accounts, categories, and category groups.326-