budget-mcp
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., "@budget-mcp Add a $35 expense for lunch under Dining"
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.
๐ฐ Personal Budget MCP Server
Track personal finances by talking to an LLM. An MCP server that gives any MCP-compatible client typed tools to log transactions, manage a category library, and analyse spending โ plus interactive dashboards rendered directly in the chat client.
Built with Python, FastMCP, SQLAlchemy, SQLite and PostgreSQL.
Why this exists
Chat is a good interface for expense logging. "Spent ยฃ42 at Tesco and ยฃ8 on coffee" is faster than opening an app and filling in two forms, and an LLM can categorise it for you.
The problem is that an LLM with no tools will happily tell you it logged your transaction. Getting this to work means the model must be unable to confuse "I recorded this" with "I described recording this" โ so the tools have to return unambiguous success or failure, reject bad input rather than coercing it, and expose enough query surface that the agent reads real state instead of reconstructing it from conversation history.
That design problem is the actual point of this repo. The budgeting is the excuse.
Related MCP server: Personal Finance Tracker
๐ธ Screenshots
Budget dashboard | Spending trends |
|
|
๐ง Design notes: making agent calls trustworthy
Explicit failure over silent coercion. Tools validate input and return a structured error naming what was wrong, rather than guessing at intent. An invalid type, a malformed date, or a category_id that doesn't exist fails loudly, so the agent can correct itself and report accurately to the user instead of inventing a confirmation.
Batch-first write tools. add_transaction, update_transaction, delete_transaction and add_category all accept either a single item or an items list. Agents naturally handle several things at once ("log these five expenses"), and forcing them into one call per record multiplies both latency and the number of places a partial failure can hide.
Referential integrity at the tool boundary. delete_category takes an optional reassign_to_category_id, so removing a category can't silently orphan its transactions. The integrity decision is surfaced as a parameter the agent must reason about rather than a side effect it discovers later.
Read surface sized for multi-turn use. get_summary, get_transactions and get_uncategorized_transactions cover aggregate, detail and triage reads with consistent filter arguments across all three. get_uncategorized_transactions returns results sorted by description specifically so an agent can categorise bulk imports in coherent groups instead of one row at a time.
Idempotent schema bootstrap. Tables and 15 default categories are created on first startup, so a fresh clone or a new cloud deployment is immediately usable and there's no partially-initialised state for a tool call to land in.
โจ Features
Local or cloud storage โ zero-setup SQLite (in-memory or
data/budget.db), or PostgreSQL via any provider such as Neon.Interactive dashboards in-client โ category pie charts and searchable transaction tables rendered via
prefab-ui, returned as MCP UI apps rather than plain text.Spending trends โ continuous category line chart with month/week/day granularity toggle, date-range slider and searchable table.
Batch operations โ single-item or bulk write across transactions and categories.
Reproducible environment โ
uvfor fast, locked dependency resolution.Broad client support โ Claude Desktop, Claude Code, Cursor, Goose, Open WebUI, and any other MCP host.
๐ Quickstart
git clone https://github.com/PedroLiu1999/budget-mcp.git
cd budget-mcp
uv sync
uv run pytest # confirm the install works
uv run server.py # start the server (in-memory SQLite by default)Then register it with your client โ Claude Code is the one-liner:
claude mcp add budget -- uv run --directory "/absolute/path/to/budget-mcp" server.pyTo persist data, set DATABASE_URL in a .env file first (see Database configuration).
๐ Available tools
Tool | Description | Arguments |
| Interactive UI app: category breakdown chart and searchable transaction table. |
|
| Interactive UI app: spending over time with category line chart, granularity toggle, date-range slider and searchable table. |
|
| Logs one or many income/expense transactions. |
|
| Aggregated summary: income, expense, net balance, optional category breakdown. |
|
| Detailed transaction records by filter. |
|
| Uncategorised transactions sorted by description, for bulk categorisation. |
|
| Updates one or many transactions. |
|
| Removes one or many transactions by ID. |
|
| Lists active categories. |
|
| Adds one or many categories. |
|
| Updates a category's properties. |
|
| Removes one or many categories, optionally reassigning their transactions. |
|
โ๏ธ Database configuration
Set via the DATABASE_URL environment variable in a .env file. Keep .env out of version control.
Local SQLite โ in-memory (default if DATABASE_URL is unset):
DATABASE_URL=sqlite:///:memory:Local SQLite file โ persists between restarts:
DATABASE_URL=sqlite:///data/budget.dbPostgreSQL / Neon:
DATABASE_URL=postgresql://<user>:<password>@<hostname>/<dbname>?sslmode=requireTables and 15 default category seeds are created automatically on first startup.
๐ Client setup
Claude Code (CLI)
claude mcp add budget -- uv run --directory "/absolute/path/to/budget-mcp" server.pyClaude Desktop
Add to claude_desktop_config.json:
{
"mcpServers": {
"personal-budget": {
"command": "uv",
"args": ["run", "--directory", "/absolute/path/to/budget-mcp", "server.py"]
}
}
}Cursor IDE
Settings โ Features โ MCP โ Add New MCP Server
Type:
commandName:
budget-mcpCommand:
uv run --directory "/absolute/path/to/budget-mcp" server.py
Open WebUI
Bridge the stdio server over HTTP with mcpo:
uvx mcpo --port 8000 -- uv run server.pyThen in Admin Panel โ Settings โ External Tools, add the OpenAPI connection URL http://localhost:8000 (or http://host.docker.internal:8000 from Docker).
โ๏ธ Cloud deployment
For remote hosts, Docker, or platforms such as Horizon:
Set
DATABASE_URLto a cloud PostgreSQL connection string in the deployment environment โ in-memory SQLite will not persist across restarts.Point the runner at the ASGI app:
fastmcp run server.py:mcp
Schema tables and default categories initialise on import, so no migration step is needed on first boot.
๐งช Testing
uv run pytestInspect tools interactively with the FastMCP Inspector:
uv run fastmcp dev inspector server.py:mcpOr preview interactive UI applications directly in the browser:
uv run fastmcp dev apps server.py:mcp๐ License
MIT โ see LICENSE.
Available Tools
12 toolsadd_categoryA
Create one or more categories in the category library.
Supports single category parameters OR a batch list/dict of items in items.
items: Optional list of dicts. Each dict can contain: {"name": str, "type": "expense"|"income", "description": str}.
name: Unique category name (used if items is omitted).
type: Category type ('expense' or 'income', defaults to 'expense').
description: Optional description explaining what belongs in this category.
Inputs: name, type, items, description. Returns: result
add_transactionA
Add one or more income or expense transactions to the budget.
Supports single transaction parameters OR a batch list/dict of items in items.
Bulk Import Workflow:
You can bulk import transactions without categories (
category_idis optional).After bulk logging, use
get_uncategorized_transactionsto review uncategorized transactions sorted by description.Then use
update_transactionto systematically assign category IDs to matching descriptions in bulk.
Arguments:
items: Optional list of dicts (or single dict) for batch insertion. Each dict can contain: {"amount": float, "category_id": int (optional), "description": str, "type": "expense"|"income", "date": "YYYY-MM-DD"}.
amount: Transaction monetary value (used if items is omitted).
category_id: Optional integer category ID from list_categories (omitting logs as 'Uncategorized').
description: Details or description of transaction (used if items is omitted).
type: Must be either 'expense' or 'income' (defaults to 'expense').
date: Optional transaction date formatted as YYYY-MM-DD or ISO string.
Inputs: date, type, items, amount, +2 more. Returns: result
budget_dashboardC
Browse the interactive budget dashboard with a category breakdown chart and transaction data table.
Inputs: type, limit, month.
delete_categoryA
Delete one or more categories from the library.
Supports a single category ID/name or a list of category IDs/names in category_ids_or_names.
category_ids_or_names: ID/name or list of IDs/names to delete.
category_id_or_name: Alias for single category deletion.
reassign_to_category_id: Target category ID to reassign linked transactions to.
Inputs: category_id_or_name, category_ids_or_names, reassign_to_category_id. Returns: result
delete_transactionB
Delete one or more transactions by ID.
Supports a single integer ID or a list of integer IDs in transaction_ids.
transaction_ids: Integer ID or list of integer IDs to delete.
transaction_id: Alias for single ID deletion.
Inputs: transaction_id, transaction_ids. Returns: result
get_summaryA
Get a summary of expenses, income, and net balance with flexible filtering and optional category breakdown.
month: Filter by month (YYYY-MM).
start_date: Filter starting from date (YYYY-MM-DD).
end_date: Filter ending at date (YYYY-MM-DD).
category_id: Optional integer category ID filter from list_categories.
type: Filter by transaction type ('expense' or 'income').
by_category: Set to True to include detailed category breakdown.
Inputs: type, month, end_date, start_date, +2 more. Returns: result
get_transactionsA
Get transactions based on specified filter criteria.
category_id: Optional integer filter by category ID.
type: Filter by type ('income' or 'expense').
month: Filter by month formatted as YYYY-MM.
start_date: Filter transactions on or after YYYY-MM-DD.
end_date: Filter transactions on or before YYYY-MM-DD.
min_amount: Filter transactions with amount >= min_amount.
max_amount: Filter transactions with amount <= max_amount.
search: Keyword search matching description or category.
limit: Maximum number of records to return (default 50).
Inputs: type, limit, month, search, +5 more. Returns: result
get_uncategorized_transactionsA
Get all uncategorized transactions sorted alphabetically by description.
Designed for systematic categorization after bulk import: Use this tool to retrieve transactions imported without categories.
Because results are sorted by description, similar merchant/expense descriptions are grouped together, enabling fast and consistent bulk updates via update_transaction.
Arguments:
type: Optional filter by transaction type ('income' or 'expense').
search: Optional keyword search filter for description.
limit: Maximum number of records to return (default 100).
Inputs: type, limit, search. Returns: result
list_categoriesA
List established categories available for transactions.
type: Optional filter by 'expense' or 'income'. Use this tool to see standard existing categories before creating new ones.
Inputs: type. Returns: result
spending_trendsB
Browse spending trends over time grouped by year-month with a line chart and transaction data table.
Inputs: type, limit, end_date, start_date.
update_categoryA
Update an existing category's name, type, or description.
category_id_or_name: ID or current name of the category to update (required).
new_name: Optional new category name.
type: Optional new type ('expense' or 'income').
description: Optional new description string.
Inputs: category_id_or_name (required), type, new_name, description. Returns: result
update_transactionA
Update one or more existing transactions by ID.
Supports single transaction updates OR a batch list/dict of update items in items.
Use this tool to assign category_id, amount, description, type, or date.
Systematic Categorization Workflow:
Pass a batch list in
itemscontaining{"transaction_id": id, "category_id": cat_id}to categorize multiple transactions at once.
Arguments:
items: Optional list of update dicts. Each dict must include "transaction_id" and optional update fields.
transaction_id: ID of transaction to update (used if items is omitted).
category_id: Integer category ID from list_categories to assign a category.
amount: Optional new monetary amount.
description: Optional new description.
type: Optional new type ('expense' or 'income').
date: Optional new date (YYYY-MM-DD).
Inputs: date, type, items, amount, +3 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 12 tools
Most tools are clearly distinct in purpose - categories, transactions, summaries, trends, and dashboard each have a unique role. There's minor potential confusion between get_summary and spending_trends (both aggregate data), and list_categories vs add_category are distinct enough. Overall boundaries are clear.
The naming mostly follows a consistent verb_noun pattern: list_categories, add_transaction, get_summary, update_transaction, delete_category. Minor deviations exist: 'budget_dashboard' and 'spending_trends' use noun-phrase naming instead of the verb-first convention, breaking the pattern slightly.
12 tools is well-scoped for a budget management server covering full lifecycle operations on both transactions and categories, plus reporting/visualization tools. Each tool earns its place without redundancy or bloat.
The surface provides full CRUD for transactions (add, get, update, delete) and categories (add, update, delete, list), plus specialized workflows like bulk import/categorization (get_uncategorized_transactions), and reporting (get_summary, spending_trends, budget_dashboard). No significant gaps in the budget domain.
Maintenance
Related MCP Connectors
Personal finance for AI agents โ onboard, import statements, categorize & budget over MCP.
Log, query, and edit expenses, budgets, and accounts in Manilo from any MCP-compatible AI assistant.
Read-only finance MCP server. Connects your banks, cards, payment apps, books and payroll into one ledger for your AI. Can't move money. Open source (AGPL-3.0), free during beta.
Track budgets from your AI chat: envelopes, monthly limits, variance reports. All data is local.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceA lightweight server built with FastMCP and SQLite for managing personal finances. It allows users to add, list, and summarize expenses by category through MCP-compatible clients.-
- AlicenseNot gradedqualityDmaintenanceA lightweight MCP server for tracking personal expenses, income, and budget summaries using SQLite.4Martin Birgmeier
- FlicenseNot gradedqualityDmaintenanceA lightweight MCP server that lets LLM clients track, query, and summarize personal expenses using a local SQLite database.-
- FlicenseBqualityDmaintenanceA lightweight local MCP server that enables users to add, list, edit, and delete expenses via SQLite database through natural language in MCP-compatible clients.41-

