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-mcpping"
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.
budget-mcp
MCP server for budget tooling, built on the official MCP Python SDK.
Project layout
budget-mcp/
├── pyproject.toml
├── budget.db # SQLite db, created by init_db.py (gitignored)
├── src/
│ └── budget_mcp/
│ ├── __init__.py
│ ├── server.py # MCPServer instance + tools
│ ├── db.py # schema DDL + connection helper
│ ├── init_db.py # resets budget.db and seeds example rows
│ ├── money.py # dollars <-> integer-cents conversion
│ ├── dates.py # date validation + period resolution
│ ├── categorizer.py # LLM-based transaction categorizer
│ └── eval_categorizer.py # accuracy check against a labeled set
├── tests/
│ ├── conftest.py # puts src/ on sys.path for test collection
│ └── test_tools.py # end-to-end tool tests, see "Tests" below
└── .venv/ # local virtualenv (gitignored)Related MCP server: Hello World MCP Server
Requirements
Python 3.10+ (this project was set up with Python 3.12 via Homebrew:
brew install python@3.12)
Setup
cd budget-mcp
/opt/homebrew/bin/python3.12 -m venv .venv
.venv/bin/pip install -e ".[dev]"
PYTHONPATH=src .venv/bin/python -m budget_mcp.init_db # creates + seeds budget.dbmacOS + iCloud Drive gotcha: if
~/Desktopis synced via iCloud Drive, the editable install's_editable_impl_budget_mcp.pthfile in.venv/lib/python3.12/site-packages/can end up with the macOS "hidden" file flag set, which makes Python 3.12 skip it — a bareimport budget_mcp(e.g. in a REPL or test) will fail withModuleNotFoundErroreven though the install "succeeded". If that happens, run:chflags nohidden .venv/lib/python3.12/site-packages/_editable_impl_budget_mcp.pthThis doesn't affect running the server or the init script below — both are invoked with
PYTHONPATH=src, which sidesteps the editable-install mechanism entirely.
categorize_transaction calls the Anthropic API, so it needs a key:
export ANTHROPIC_API_KEY=sk-ant-...Add the same variable to the env block in the Claude Desktop config below so
it's available when Claude Desktop launches the server.
Database
Three tables (see src/budget_mcp/db.py for the full DDL):
budgets(category PK, monthly_limit)transactions(id, date, amount, category -> budgets.category, source, note)savings_goals(id, name, target_amount, current_amount, account_type)
All money columns are integer cents (e.g. 50000 == $500.00) to avoid
float rounding — SQLite has no real DECIMAL type. transactions.amount is
signed: negative = expense, positive = income.
Re-run PYTHONPATH=src .venv/bin/python -m budget_mcp.init_db any time to
wipe budget.db and reset it to the seed data.
Tools
ping()— placeholder, returns"pong".add_transaction(date, amount, category, source, note=None)— inserts a transaction and returns it plus the category's running total for that transaction's calendar month.amountis dollars (e.g.-45.67);datemust beYYYY-MM-DD;categorymust already exist inbudgets. Rejects bad dates, zero/non-finite/sub-cent amounts, unknown categories, and emptysourcewith a clear error message (no stack traces).get_spending_summary(period, group_by, start_date=None, end_date=None)— sums expense transactions (amount < 0) overperiod("this_month","last_month", or"custom"withstart_date/end_date), grouped by"category"or"source", and returns each group's total plus % of total spend. Rejects unknownperiod/group_byvalues and missing/invalid custom-range dates.categorize_transaction(description)— classifies a raw statement line (e.g."TESCO STORES 3421 LONDON") into one ofrent,food,transport,savings,business_expense,entertainment,other, via a Claude Haiku 4.5 call with structured JSON output (category,confidence,reasoning). The returned category is checked against the fixed list before being returned — an invalid category from the model surfaces as an error rather than being trusted. RequiresANTHROPIC_API_KEY(see Setup above).
Tests
.venv/bin/pytest tests/ -vEach test spawns a real server subprocess and drives it through the actual
MCP protocol (same path Claude Desktop uses), against a fresh throwaway
SQLite db (via BUDGET_MCP_DB_PATH) — your real budget.db is never
touched. Covers both tools' happy paths (including that running totals and
spend percentages come out exact, not float-drifted) and every validation
rejection (bad dates, zero/non-finite/sub-cent amounts, unknown categories,
empty source, bad period/group_by, missing custom-range dates).
categorize_transaction isn't in this suite — LLM output isn't deterministic,
so it doesn't belong in a pass/fail unit test. Instead, check its accuracy
against 15 hand-labeled realistic statement lines:
PYTHONPATH=src .venv/bin/python -m budget_mcp.eval_categorizerThis calls the live API (needs ANTHROPIC_API_KEY) and prints a pass/fail
per example plus overall accuracy.
Running locally
Run the server directly (it speaks MCP over stdio):
PYTHONPATH=src .venv/bin/python -m budget_mcp.serverIt will sit waiting for an MCP client to talk to it over stdin/stdout — that's expected, it's not meant to be run interactively.
To poke at it with the official inspector UI instead:
PYTHONPATH=src .venv/bin/mcp dev src/budget_mcp/server.pyConnecting to Claude Desktop
Edit ~/Library/Application Support/Claude/claude_desktop_config.json and add
an mcpServers entry:
{
"mcpServers": {
"budget-mcp": {
"command": "/Users/hamza/Desktop/projects/budget-mcp/.venv/bin/python",
"args": ["-m", "budget_mcp.server"],
"env": {
"PYTHONPATH": "/Users/hamza/Desktop/projects/budget-mcp/src",
"ANTHROPIC_API_KEY": "sk-ant-..."
}
}
}
}Then fully quit and reopen Claude Desktop. In a new conversation, the tools
should be available (look for the tools/hammer icon) — try asking Claude to
call ping, then to add a transaction or get a spending summary.
Notes
Uses MCP Python SDK v2 (
mcp.server.MCPServer, formerlyFastMCPin v1.x). Requiresmcp>=1.2.0perpyproject.toml, but what's actually installed here is the current 2.x line.Tool validation errors are raised as
mcp.server.mcpserver.exceptions.ToolError, which the framework returns to the client as a plain error message — never a Python traceback.
Available Tools
4 toolsadd_transactionA
Insert a transaction and return it plus the category's running total for its month.
date: ISO 8601 'YYYY-MM-DD'. amount: dollars, signed (negative = expense, positive = income), precise to the cent. category: must already exist in the budgets table.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | ||
| note | No | ||
| amount | Yes | ||
| source | Yes | ||
| category | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the disclosure burden. It discloses the return value (transaction plus running total), amount sign convention, and the category existence requirement, which is meaningful behavioral context. It does not cover failure modes or side effects beyond insertion.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact: a one-sentence purpose followed by three terse parameter bullets. Every sentence adds information and it is easily scannable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Although the core purpose is clear, the tool is incomplete for a 5-parameter no-annotation, no-output-schema case: 'source' is required but undefined, and there's no guidance on when to use add_transaction versus categorize_transaction. Error or rejection behavior for invalid categories is also unexplored.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description explains date, amount, and category, adding useful meaning beyond the bare schema. However, it omits the required 'source' parameter entirely and also does not explain 'note,' leaving 2 of 5 parameters undocumented despite 0% schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Insert a transaction and return it plus the category's running total for its month,' clearly identifying a create operation with a specific return value. The verb 'Insert' and resource 'transaction' distinguish it from read-only siblings like get_spending_summary and from categorize_transaction.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for creating new transactions but provides no explicit when-to-use guidance or exclusions of alternatives like categorize_transaction. It does state a prerequisite (category must already exist), but does not say when to choose this tool over a sibling.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
categorize_transactionA
Suggest a budget category for a raw transaction description via an LLM classifier.
description: raw text as it might appear on a statement, e.g. "TESCO STORES 3421 LONDON".
Returns category (one of rent/food/transport/savings/business_expense/ entertainment/other), confidence (0-1), and reasoning. The category is checked against the allowed list before being returned - an invalid category from the model surfaces as an error rather than being passed through.
| Name | Required | Description | Default |
|---|---|---|---|
| description | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations available, the description fully carries the burden of behavioral disclosure. It explains that an LLM is used, that the category is validated against a fixed list, that invalid categories surface as errors, and it specifies the return fields (category, confidence, reasoning). This goes beyond basic expectations and provides meaningful transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is appropriately sized and front-loaded with the purpose. The only minor issue is the use of 'description:' on a separate line, which could be slightly confusing because it mirrors the tool's own description field. Otherwise, it is structured logically and contains no wasted content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the lack of output schema and annotations, the description covers all essential context: input format with example, output structure with allowed categories and confidence range, and error behavior. Nothing critical is missing for the agent to invoke and interpret the result correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema provides no description for the single 'description' parameter, so the tool description compensates by defining it as 'raw text as it might appear on a statement' with a concrete example ('TESCO STORES 3421 LONDON'). This gives the agent clear semantic understanding that the schema lacks.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: 'Suggest a budget category for a raw transaction description via an LLM classifier.' This uses a specific verb and resource, and it is distinct from sibling tools like add_transaction or get_spending_summary, leaving no ambiguity about its purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The context strongly implies when to use this tool: whenever a raw transaction description needs a budget category. It includes an example of the expected input and explains the return structure, making the use case clear. However, it does not explicitly mention when not to use it or point to alternatives, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_spending_summaryA
Summarize expense transactions (amount < 0) over a period, grouped by category or source.
period: 'this_month', 'last_month', or 'custom' (requires start_date and end_date). group_by: 'category' or 'source'. start_date/end_date: ISO 8601 'YYYY-MM-DD', inclusive, only used when period='custom'.
| Name | Required | Description | Default |
|---|---|---|---|
| period | Yes | ||
| end_date | No | ||
| group_by | Yes | ||
| start_date | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the transparency burden. It discloses that only transactions with amount < 0 are considered, dates are inclusive, and custom periods require start/end dates. However, it does not state that the operation is read-only, nor does it describe the output structure or any side effects, leaving room for ambiguity.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and well-structured: a one-sentence purpose followed by parameter details. Every sentence contributes value, and the format makes the information easily scannable for an agent.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has 4 parameters, no output schema, and no annotations. The description documents parameters well but does not explain what the summary output looks like (e.g., totals, counts, breakdown structure). An agent may not know how to interpret the returned data, which is a notable gap given the lack of an output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description fully explains all parameters: allowed values for period and group_by, the requirement for start_date/end_date when period='custom', and the ISO 8601 format with inclusive behavior. This adds essential meaning beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the tool as summarizing expense transactions (amount < 0) over a period, grouped by category or source. It distinguishes itself from sibling tools (ping, add_transaction, categorize_transaction) by focusing on aggregate read-only analysis rather than mutations or health checks.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context for when to use the tool (summarizing expenses) and explains the period and grouping options. It does not explicitly name alternatives or state when not to use it, but the sibling context and the explanatory parameter notes make the intended usage clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pingA
Placeholder tool to verify the server is wired up correctly.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden of disclosure. It indicates a non-destructive verification purpose but does not specify what the tool returns, whether it has side effects, or any caveats. For a trivial ping tool, this is acceptable but not richly transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, front-loaded sentence with no filler. Every word contributes to understanding the tool's purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity, the description is largely complete. It doesn't explain the return value, but an output schema exists, so that information is likely covered structurally. The placeholder wording appropriately signals limited utility.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the schema covers everything (100%). According to the rubric, a baseline of 4 applies when there are no parameters, and the description need not add parameter semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states a specific verb and resource: 'verify the server is wired up correctly.' This distinguishes it from sibling tools focused on transaction operations, making its health-check purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'to verify the server is wired up correctly' gives a clear context for when to use this tool. Although it doesn't explicitly mention alternatives or when not to use it, the purpose inherently implies it's for initial connectivity checks, and there are no competing tools for this behavior.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
4 tool updates
v0.1.0- First observed
add_transaction - First observed
categorize_transaction - First observed
get_spending_summary - First observed
ping
TDQS
Scored across 4 tools
Each tool has a clearly distinct purpose: ping for connectivity, add_transaction for inserting data, get_spending_summary for aggregating, and categorize_transaction for classification. There is no functional overlap between any two tools.
The three functional tools follow a consistent verb_noun pattern (add_transaction, get_spending_summary, categorize_transaction). The 'ping' tool breaks the pattern by being a bare verb, but it's a standard placeholder and doesn't cause confusion.
With only 4 tools (one being a placeholder), the server feels under-scoped for a budget application. The count is borderline acceptable, but the lack of essential operations makes it seem thin.
The server lacks core CRUD functionality: no way to list, update, or delete transactions, and no way to manage categories (add_transaction requires an existing category but there's no create_category tool). Also missing budget-setting features, making the surface significantly incomplete.
Maintenance
Related MCP Connectors
MCP server for Codat — companies, connections, invoices, bills and financial statements.
Related MCP Servers
- FlicenseNot gradedqualityNot gradedmaintenanceA simple demonstration MCP server that provides basic greeting functionality and server information. Enables users to generate hello messages and retrieve server details through tools and resources.-
- -licenseCqualityNot gradedmaintenanceA simple boilerplate MCP server that provides a basic greeting tool for demonstration purposes. Serves as a starting template for developers to quickly create and deploy custom MCP servers.16 npm-
- AlicenseCqualityDmaintenanceA simple MCP server that provides a basic greeting tool for saying hello with customizable names. Serves as a boilerplate template for developers to quickly create and deploy new MCP servers.16 npmMIT
- FlicenseNot gradedqualityDmaintenanceA simple demonstration MCP server that provides an echo tool and resource for learning how to build MCP servers. Serves as a starting point and template for creating custom MCP server implementations.1-