arunselvarajdb/ynab-mcp-server
If you are the rightful owner of ynab-mcp-server and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to dayong@mcphub.com.
YNAB MCP Server is a read-only Model Context Protocol server for interacting with YNAB budgets, providing tools and resources for querying and analyzing budget data.
YNAB MCP Server
A read-only Model Context Protocol (MCP) server for interacting with YNAB (You Need A Budget) budgets. This server provides tools and resources for querying budgets, accounts, transactions, categories, and generating spending insights.
Features
Core Features
- Read-Only Access: Safe, non-destructive access to your YNAB data
- Comprehensive Tools: Get budgets, accounts, transactions, categories, and payees
- Spending Analysis: Analyze spending patterns with insights and statistics
- MCP Resources: Formatted budget summaries, account balances, and category spending
- Secure: API tokens via environment variables, input validation, and error handling
- Well-Tested: Comprehensive unit tests with >60% code coverage
Development Tools
- Task Runner: Unified command interface with Taskfile.yml
- Pre-commit Hooks: Automatic code quality checks on every commit
- Security Scanning: Code analysis with Bandit, dependency auditing with pip-audit
- Type Safety: Full type checking with MyPy
- Code Quality: Linting and formatting with Ruff
- Secret Detection: Prevent accidental credential commits
Prerequisites
- Python 3.11 or higher
- uv package manager
- YNAB Personal Access Token
Quick Start
1. Install Task Runner (Optional but Recommended)
# macOS
brew install go-task
# Or visit: https://taskfile.dev/installation/
2. Complete Setup
Using Task (recommended):
task setup
Or manually:
# Install dependencies
uv sync --all-extras
# Copy environment file
cp .env.example .env
# Install pre-commit hooks
uv run pre-commit install
3. Configure Environment Variables
Edit .env and add your YNAB Personal Access Token:
# Required: Your YNAB Personal Access Token
YNAB_API_TOKEN=your_token_here
# Optional: Default budget ID
DEFAULT_BUDGET_ID=
# Optional: Log level
LOG_LEVEL=INFO
4. Get Your YNAB API Token
- Log in to your YNAB account
- Go to Account Settings → Developer Settings
- Click New Token under "Personal Access Tokens"
- Enter your password to generate the token
- Copy the token to your
.envfile
Security Warning: Never commit your .env file or share your API token!
Usage
Testing with MCP Inspector
Test the server interactively using the MCP Inspector:
Using Task:
task run:inspect
Or directly:
./inspect-server.sh
# or
npx @modelcontextprotocol/inspector uv run ynab-mcp-server
Note: The MCP Inspector is a Node.js tool, so you need Node.js and npm/npx installed.
The inspector provides:
- Interactive tool testing with parameter input
- Real-time response viewing
- Resource browsing
- Request/response logging
Available Task Commands
Run task --list to see all available commands, including:
Setup & Installation:
task setup- Complete project setup (install deps, create .env, install hooks)task install- Install all dependencies including dev toolstask setup:hooks- Install pre-commit hooks
Code Quality:
task check- Run all quality checks (format, lint, security, typecheck, test)task fmt- Format code with rufftask lint- Lint code with rufftask typecheck- Type check with mypy
Security:
task security- Run all security scanstask security:bandit- Python code security lintingtask security:deps- Dependency vulnerability scanning
Testing:
task test- Run tests with coveragetask test:verbose- Run tests with verbose outputtask test:coverage- Generate HTML coverage report
Running:
task run- Run server in stdio modetask run:http- Run server in HTTP modetask run:http:debug- Run with debug loggingtask run:inspect- Run MCP Inspector
Pre-commit:
task pre-commit- Run all pre-commit hooks manuallytask pre-commit:update- Update hooks to latest versions
Running the MCP Server
The server supports two transport modes:
1. stdio Mode (Default)
For use with MCP clients like Claude Desktop or the inspector:
Using Task:
task run
Or directly:
uv run ynab-mcp-server
# or
python -m ynab_mcp_server
2. HTTP/SSE Mode
For HTTP-based access with Server-Sent Events:
Using Task:
task run:http # Run on port 8000
task run:http:debug # Run with debug logging
Or directly:
./run-http-server.sh
# or
uv run ynab-mcp-server --transport sse --port 8000
The HTTP server will be available at http://localhost:8000 (or your chosen port).
Command-line Options:
--transport {stdio|sse}- Choose transport type (default: stdio)--port PORT- HTTP server port (default: 8000, only for SSE)--host HOST- HTTP server host (default: localhost, only for SSE)
Available Tools
The MCP server provides the following tools:
get_budgets()
Get list of all budgets for the authenticated user.
{
"budgets": [
{
"id": "budget-123",
"name": "My Budget",
"currency_format": {
"iso_code": "USD",
"currency_symbol": "$"
}
}
]
}
get_accounts(budget_id: str)
Get all accounts for a specific budget.
{
"budget_id": "budget-123",
"accounts": [
{
"id": "account-1",
"name": "Checking Account",
"type": "checking",
"balance": 1500.00,
"cleared_balance": 1400.00
}
]
}
get_transactions(budget_id: str, since_date?: str, transaction_type?: str, account_id?: str)
Get transactions with optional filters.
Parameters:
budget_id(required): The budget UUIDsince_date(optional): ISO date (YYYY-MM-DD) to retrieve transactions fromtransaction_type(optional): Filter by type - 'uncategorized' or 'unapproved'account_id(optional): Filter by specific account UUID
Examples:
# Get all transactions
get_transactions("budget-123")
# Get transactions since specific date
get_transactions("budget-123", since_date="2025-01-01")
# Get unapproved transactions
get_transactions("budget-123", transaction_type="unapproved")
# Get transactions for specific account
get_transactions("budget-123", account_id="account-456")
get_categories(budget_id: str)
Get all categories organized by category groups.
{
"budget_id": "budget-123",
"category_groups": [
{
"id": "group-1",
"name": "Monthly Bills",
"categories": [
{
"id": "cat-1",
"name": "Rent",
"budgeted": 1000.00,
"activity": -1000.00,
"balance": 0.00
}
]
}
]
}
get_payees(budget_id: str)
Get all payees for a budget.
analyze_spending(budget_id: str, category_id?: str, since_date?: str, account_id?: str)
Analyze spending patterns with insights and statistics.
Parameters:
budget_id(required): The budget UUIDcategory_id(optional): Filter to specific categorysince_date(optional): Start date for analysis (defaults to 30 days ago)account_id(optional): Filter to specific account
Returns:
{
"summary": {
"total_spent": 750.50,
"transaction_count": 15,
"average_transaction": 50.03,
"daily_average": 25.02
},
"top_payees": [
{"payee": "Whole Foods", "amount": 200.00},
{"payee": "Shell", "amount": 150.00}
]
}
Available Resources
MCP resources provide formatted, read-only data:
ynab://budgets/{budget_id}/summary
Comprehensive budget summary with accounts and categories.
ynab://budgets/{budget_id}/accounts
Formatted account balances.
ynab://budgets/{budget_id}/categories
Category spending overview with usage percentages.
Development
Development Workflow
Using Task (recommended):
# Run all quality checks (format, lint, security, typecheck, test)
task check
# Run specific checks
task fmt # Format code
task lint # Lint code
task security # Run security scans
task typecheck # Type check with mypy
task test # Run tests with coverage
# Run pre-commit hooks manually
task pre-commit
# See all available tasks
task --list
Or using uv directly:
# Run tests
uv run pytest
uv run pytest --cov # With coverage
uv run pytest tests/test_tools.py # Specific file
# Code quality
uv run ruff format src/
uv run ruff check src/
uv run mypy src/
# Security
uv run bandit -r src/ -ll
uv run pip-audit
Pre-commit Hooks
Pre-commit hooks automatically run on every commit:
- Ruff - Format and lint code
- Bandit - Security checks
- MyPy - Type checking
- detect-secrets - Secret detection
- File quality checks (trailing whitespace, YAML syntax, etc.)
To run manually:
task pre-commit
# or
uv run pre-commit run --all-files
Project Structure
ynab-mcp-server/
src/
ynab_mcp_server/
__init__.py # Package initialization
__main__.py # Entry point
config.py # Configuration management
ynab_client.py # YNAB API wrapper
server.py # MCP server with tools & resources
tests/
conftest.py # Pytest fixtures
test_tools.py # Tool tests
test_resources.py # Resource tests
.env.example # Example environment variables
.gitignore # Git ignore rules
pyproject.toml # Project configuration
README.md # This file
Security Best Practices
API Token Security
- Never hardcode tokens - Always use environment variables
- Use
.envfiles for local development (already in.gitignore) - Rotate tokens regularly - Every 60-90 days recommended
- Monitor token usage - Check YNAB developer settings for unusual activity
- Use separate tokens - Different tokens for development/production
Configuration Validation
The server validates configuration at startup:
- Checks for required
YNAB_API_TOKEN - Rejects placeholder values like "your_token_here"
- Validates log level is a valid option
- Fails fast with clear error messages
Error Handling
- API tokens are never exposed in error messages
- Authentication errors are logged without token details
- Generic errors returned to users, detailed logs for debugging
- All API calls wrapped in try-catch blocks
Input Validation
- Budget IDs, account IDs, and dates are validated
- Pydantic models ensure type safety
- SQL injection not applicable (uses YNAB REST API)
- XSS not applicable (no web interface)
API Rate Limits
YNAB API has rate limits:
- 200 requests per hour per access token
- Rate limit resets hourly
- Server handles 429 responses gracefully
- Consider caching for production use
Troubleshooting
"Invalid YNAB API token" Error
- Check your token in
.envmatches the one from YNAB Developer Settings - Ensure token hasn't been revoked
- Try generating a new token
"Budget not found" Error
- Verify the budget_id is correct (get it from
get_budgets()tool) - Ensure your token has access to the budget
- Check budget hasn't been deleted
Tests Failing
# Reinstall dependencies
uv sync --all-extras
# Clear pytest cache
rm -rf .pytest_cache
# Run with verbose output
uv run pytest -vvs
Import Errors
# Reinstall in editable mode
uv pip install -e .
Contributing
This is a personal project, but suggestions and feedback are welcome!
Development Workflow
- Setup:
task setup- Install dependencies and pre-commit hooks - Develop: Make your changes
- Quality Checks:
task check- Run all quality checks - Test: Ensure all tests pass
- Commit: Pre-commit hooks will automatically run
- Update Docs: Update README for new features
Before Submitting
# Run all quality checks
task check
# This runs:
# - Code formatting (ruff format)
# - Linting (ruff check)
# - Security scans (bandit, pip-audit)
# - Type checking (mypy)
# - Tests with coverage (pytest)
Pre-commit hooks will automatically enforce these checks on commit.
Security
For security concerns and vulnerability reporting, please see our .
Quick Security Checklist:
- ✅ Keep YNAB API tokens in
.env(never commit) - ✅ Run
task securityto scan for vulnerabilities - ✅ Update dependencies regularly with
uv sync --upgrade - ✅ Review pre-commit hooks are working:
task pre-commit
Report security vulnerabilities privately to: mit.arun07@gmail.com
License
MIT License - see LICENSE file for details.
Resources
Changelog
v0.1.0 (2025-11-22)
- Initial release
- Read-only tools for budgets, accounts, transactions, categories, and payees
- Spending analysis with top payees and statistics
- MCP resources for formatted budget data
- Comprehensive test coverage
- Security best practices implementation