Skip to main content
Glama
anjudevchaudhary0

Expense Tracker MCP

README.md
# Expense Tracker MCP

A local [MCP](https://modelcontextprotocol.io) server that lets an LLM (Claude Desktop, the FastMCP Inspector, or any MCP client) track your expenses and credits in a SQLite database on your machine.

Built with [FastMCP](https://gofastmcp.com).

## Features

- Add, list, update, and delete expenses
- Track credits (money received) separately from expenses
- Category / subcategory enforcement — the LLM can only use categories and subcategories you've defined, so entries stay clean and consistent
- Per-category expense summary
- Running balance (`total credited − total spent`)
- All data stored locally in SQLite — nothing leaves your machine

## Project structure

```
expence-tracker-mcp/
├── server.py                              # entry point used by Claude Desktop / fastmcp CLI
├── src/expence_tracker_mcp/
│   ├── __init__.py                        # server: tools, resource, DB logic
│   ├── category.json                      # editable category → subcategory map
│   └── expenses.db                        # SQLite DB (auto-created on first run, gitignored)
├── pyproject.toml
└── uv.lock
```

## Requirements

- Python >= 3.13
- [uv](https://docs.astral.sh/uv/)

## Setup

```bash
git clone <this-repo>
cd expence-tracker-mcp
uv sync
```

`uv sync` creates a `.venv` and installs `fastmcp` and its dependencies.

## Running the server standalone

```bash
uv run server.py
```

## Running the MCP Inspector (debugger)

Use this to interactively call the tools/resource in a browser before wiring it up to an LLM client.

```bash
uv run fastmcp dev inspector server.py
```

This prints a local URL (with an auth token) — open it in your browser, click **Connect**, then try the tools from the **Tools** tab.

## Connecting to Claude Desktop

Add an entry to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):

```json
{
  "mcpServers": {
    "ExpenseTracker": {
      "command": "uv",
      "args": [
        "run",
        "--directory",
        "/absolute/path/to/expence-tracker-mcp",
        "fastmcp",
        "run",
        "server.py"
      ]
    }
  }
}
```

Replace the path with the absolute path to this project on your machine, then fully quit and reopen Claude Desktop (Cmd+Q, not just close the window) to pick up the change.

## Tools

| Tool | Description |
|---|---|
| `add_expense(date, amount, category, subcategory, note="")` | Add a new expense. `category` and `subcategory` are **required** and must come from `category.json` (see below). |
| `list_expenses(category="", start_date="", end_date="")` | List expenses, optionally filtered by category and/or date range (`YYYY-MM-DD`). |
| `update_expense(id, date="", amount=None, category="", subcategory="", note="")` | Update an existing expense. Only the fields you pass are changed. |
| `delete_expense(id)` | Delete an expense by id. |
| `add_credit(date, amount, source="", note="")` | Add credit (money received) to the tracker. |
| `list_credits(start_date="", end_date="")` | List credits, optionally filtered by date range. |
| `summarize_expenses(start_date="", end_date="")` | Totals grouped by category, plus overall `total_spent`. |
| `get_balance()` | Returns `{ total_credited, total_spent, balance }`. |

Every write tool returns `{"status": "ok", ...}` on success or `{"status": "error", "message": "..."}` on failure (e.g. invalid category, record not found) instead of raising — so the calling LLM can see what went wrong and retry.

## Resource

| Resource | Description |
|---|---|
| `data://categories` | The full category → subcategory map from `category.json`. The LLM is instructed (via the resource description) to always pick category/subcategory from here. |

## Customizing categories

Edit `src/expence_tracker_mcp/category.json` — it's read fresh on every tool call, so changes take effect immediately without restarting the server:

```json
{
  "food": ["dining out", "snacks"],
  "travel": ["cab", "flight", "train", "fuel"],
  "rent": ["house rent", "office rent"],
  "groceries": []
}
```

- A category **must** be a top-level key in this file, or `add_expense` / `update_expense` will reject it.
- `subcategory` is required on `add_expense`.
- If a category's subcategory list is **non-empty**, the subcategory must be one of those exact values.
- If a category's subcategory list is **empty** (e.g. `"groceries": []`), any non-blank subcategory text is accepted — useful for categories too varied to enumerate.

This enforcement happens server-side in `add_expense`/`update_expense`, so invalid entries are rejected even if the LLM ignores the `data://categories` resource.

## Database

SQLite database at `src/expence_tracker_mcp/expenses.db`, auto-created on first run with two tables:

```sql
CREATE TABLE expenses(
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    date TEXT NOT NULL,
    amount REAL NOT NULL,
    category TEXT NOT NULL,
    subcategory TEXT DEFAULT '',
    note TEXT DEFAULT ''
);

CREATE TABLE credits(
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    date TEXT NOT NULL,
    amount REAL NOT NULL,
    source TEXT DEFAULT '',
    note TEXT DEFAULT ''
);
```

The `.db` file is gitignored — each machine gets its own local data.

## Inspecting the server

Check tool/resource counts without starting a full client:

```bash
uv run fastmcp inspect server.py
```

TDQS

A3.7/5.0

Scored across 8 tools

Disambiguation5/5

Each tool targets a distinct resource and action: expenses have add/list/update/delete, credits have add/list, and summarize/get_balance provide reporting. There is no meaningful overlap or ambiguity between tools.

Naming Consistency5/5

All tools follow a clear verb_noun snake_case pattern. List operations use plural nouns (list_expenses, list_credits) while singular entity operations use singular nouns, which is a predictable and consistent convention.

Tool Count5/5

Eight tools is well-scoped for an expense tracker: full CRUD for expenses, credit tracking, and balance/summary reporting. Each tool earns its place without redundancy or bloat.

Completeness4/5

Expenses have complete CRUD coverage and reporting is solid, but credits only support add and list with no update or delete. This is a minor gap that agents can work around by re-adding corrected credits, but it is a slight lifecycle gap.

Maintenance

ActivityMaintained
ResponsivenessNo issues