Skip to main content
Glama

YNAB Assistant

by franccesco
CLAUDE.md5.38 kB
# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview YNAB Assistant is a FastMCP (Model Context Protocol) server that provides AI-accessible tools for interacting with the YNAB (You Need A Budget) API. The server exposes 21 tools via HTTP transport for managing budgets, accounts, categories, months, and transactions. ## Development Commands ### Running the Server ```bash uv run python main.py ``` Server runs on HTTP transport at `http://localhost:8000/mcp` ### Linting and Type Checking **CRITICAL**: Always run both linters iteratively until all issues are resolved: ```bash ruff check --fix && basedpyright ``` Continue running this command in a loop, fixing issues each iteration, until both pass cleanly. ### Environment Setup Required environment variable: ```bash export YNAB_ACCESS_TOKEN="your_token_here" ``` Use `.envrc` with direnv for local development. ## Architecture ### Modular Structure The codebase follows a **DRY (Don't Repeat Yourself)** principle with shared authentication: ``` main.py # FastMCP server setup, tool registration ├── auth.py # Shared authentication helpers (get_api_configuration, get_api_client) ├── accounts.py # Account discovery tools (2 tools) ├── categories.py # Category management tools (5 tools) ├── months.py # Month management tools (2 tools) └── transactions.py # Transaction management tools (11 tools) ``` ### Tool Registration Pattern All tools from module files are imported and registered in `main.py` using: ```python from accounts import get_accounts, get_account_by_id mcp.tool(get_accounts) mcp.tool(get_account_by_id) ``` ### Authentication Flow All API interactions follow this pattern: 1. Call `get_api_configuration()` from `auth.py` (reads YNAB_ACCESS_TOKEN) 2. Call `get_api_client(configuration)` to get authenticated client 3. Use client in context manager (`with` statement) 4. Return data via `model_dump()` for consistent dict responses ### YNAB SDK Type Issues The `ynab-sdk-python` package has incomplete type definitions. Common patterns: **User/Transaction objects lack field definitions:** ```python user = api_response.data.user # type: ignore[attr-defined] user_dict = user.model_dump() # type: ignore[attr-defined] ``` **Date parameters accept strings at runtime but typed as `date`:** ```python since_date=since_date # type: ignore[arg-type] ``` **Wrapper objects accept dicts but typed for specific models:** ```python wrapper = ynab.PostTransactionsWrapper(transaction=transaction_data) # type: ignore[arg-type] ``` These `# type: ignore` comments are necessary and correct. ### Default Parameters Convention All tools that require a `budget_id` default to `"last-used"`: ```python def get_transactions(budget_id: str = "last-used", ...): ``` This uses YNAB's "last-used" budget feature for convenience. ### Amount Representation YNAB uses **milliunits** for all monetary amounts: - `-50000` = -$50.00 - `125000` = $125.00 ## Tool Categories ### User Tools (1) - `get_user()` - Get authenticated user info ### Account Tools (2) - `get_accounts()` - List all accounts (use this to discover account IDs) - `get_account_by_id(account_id)` ### Category Tools (5) **Read operations (3):** - `get_categories(budget_id, last_knowledge_of_server)` - List all categories grouped by category group - `get_category_by_id(category_id, budget_id)` - Get single category with current month amounts - `get_month_category_by_id(category_id, month, budget_id)` - Get category for specific month **Write operations (2):** - `update_category(category_id, budget_id, note, budgeted)` - Update category note and/or budgeted amount - `update_month_category(category_id, month, budgeted, budget_id)` - Update budgeted amount for specific month ### Month Tools (2) **Read operations (2):** - `get_budget_months(budget_id, last_knowledge_of_server)` - List all budget months - `get_budget_month(month, budget_id)` - Get single budget month with categories and category groups ### Transaction Tools (11) **Read operations (6):** - `get_transaction_by_id(transaction_id)` - `get_transactions(budget_id, since_date)` - `get_transactions_by_account(account_id, budget_id, since_date)` - `get_transactions_by_category(category_id, budget_id, since_date)` - `get_transactions_by_month(month, budget_id)` - month: "2024-12-01" or "current" - `get_transactions_by_payee(payee_id, budget_id, since_date)` **Write operations (5):** - `create_transaction(account_id, date, amount, ...)` - `create_transactions(transactions, budget_id)` - bulk create - `update_transaction(transaction_id, ...)` - `update_transactions(transactions, budget_id)` - bulk update - `delete_transaction(transaction_id)` ## Code Quality Standards ### Linting Configuration Ruff is configured with strict rules including: - E/W (pycodestyle), F (pyflakes), I (isort) - B (bugbear), UP (pyupgrade), SIM (simplify) - DOC (pydoclint), D (pydocstyle) - PERF (performance), ARG (unused args) **Max cyclomatic complexity: 10** ### Type Checking Pyright runs in **strict mode** (`typeCheckingMode = "strict"`). All functions must have: - Full type hints for parameters - Return type annotations - Proper docstrings with Args, Returns, and Raises sections ### Python Version Requires Python 3.14+

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/franccesco/ynab-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server