Skip to main content
Glama
ayush-patel-29

Expense Tracker MCP

README.md
# Expense Tracker MCP

A simple Model Context Protocol (MCP) server for tracking expenses in a local SQLite database. It exposes tools for adding, reading, updating, deleting, and summarizing expenses, plus a JSON resource containing supported categories and subcategories.

## Features

- Add expenses with amount, date, category, subcategory, and note fields
- List all saved expenses
- Query expenses by start and end date
- Update existing expenses by ID
- Delete expenses by ID
- Summarize spending by category over a date range
- Read predefined expense categories from `categories.json`
- Store data locally in `expenses.db`

## Requirements

- Python 3.13 or newer
- `uv` for dependency management, or another Python package manager

## Installation

Clone the project and install dependencies:

```bash
uv sync
```

The main dependency is `fastmcp`, defined in `pyproject.toml`.

## Running The Server

Start the MCP server:

```bash
uv run python main.py
```

By default, the server runs over HTTP on:

```text
http://0.0.0.0:8000
```

The SQLite database is initialized automatically when the server starts. If `expenses.db` does not already contain the required table, it will be created.

## MCP Tools

### `add_expense`

Adds a new expense.

Parameters:

- `amount` (`float`): Expense amount
- `date` (`str`): Expense date, preferably in `YYYY-MM-DD` format
- `category` (`str`): Main expense category
- `subcategory` (`str`, optional): More specific category
- `note` (`str`, optional): Additional details

Example:

```json
{
  "amount": 250.75,
  "date": "2026-07-08",
  "category": "food",
  "subcategory": "groceries",
  "note": "Weekly grocery run"
}
```

### `get_expenses`

Returns all expenses stored in the database.

### `get_expense_by_start_end_date`

Returns expenses between two dates.

Parameters:

- `start_date` (`str`): Start date
- `end_date` (`str`): End date

Example:

```json
{
  "start_date": "2026-07-01",
  "end_date": "2026-07-31"
}
```

### `update_expense`

Updates an existing expense by ID. Only fields provided in the request are updated.

Parameters:

- `expense_id` (`int`): Expense ID
- `amount` (`float`, optional): Updated amount
- `date` (`str`, optional): Updated date
- `category` (`str`, optional): Updated category
- `subcategory` (`str`, optional): Updated subcategory
- `note` (`str`, optional): Updated note

Example:

```json
{
  "expense_id": 1,
  "amount": 300,
  "note": "Updated grocery total"
}
```

### `delete_expense`

Deletes an expense by ID.

Parameters:

- `expense_id` (`int`): Expense ID to delete

### `summarize`

Summarizes expenses by category for a date range.

Parameters:

- `start_date` (`str`): Start date
- `end_date` (`str`): End date
- `category` (`str`, optional): Filter summary to one category

Example:

```json
{
  "start_date": "2026-07-01",
  "end_date": "2026-07-31",
  "category": "food"
}
```

## MCP Resources

### `expenses://categories`

Returns the contents of `categories.json`, which maps supported categories to their subcategories.

Example categories include:

- `food`
- `transport`
- `housing`
- `utilities`
- `health`
- `education`
- `business`
- `travel`
- `investments`
- `misc`

## Data Model

Expenses are stored in the `expenses` SQLite table:

| Column | Type | Description |
| --- | --- | --- |
| `id` | `INTEGER` | Auto-incrementing primary key |
| `amount` | `REAL` | Expense amount |
| `date` | `TEXT` | Expense date |
| `category` | `TEXT` | Main category |
| `subcategory` | `TEXT` | Optional subcategory |
| `note` | `TEXT` | Optional note |

## Project Structure

```text
.
├── main.py           # FastMCP server and tool definitions
├── categories.json   # Category and subcategory definitions
├── expenses.db       # Local SQLite database
├── pyproject.toml    # Project metadata and dependencies
├── uv.lock           # Locked dependency versions
└── README.md
```

## Notes

- Date values are stored as text. Use a consistent format such as `YYYY-MM-DD` so date-range queries work correctly.
- The database file is local to this project directory.
- The current implementation does not validate category names against `categories.json`; clients should use the categories resource to choose valid values.