Expense Tracker MCP
# Expense Tracker MCP
A Model Context Protocol (MCP) server for tracking and managing personal expenses. Built with Python and FastMCP, this server provides tools for adding, viewing, filtering, and summarizing expenses stored in a SQLite database.
## Features
- **Add Expenses** - Record expenses with name, price, category, sub-category, and date
- **View All Expenses** - Retrieve complete expense history
- **Filter by Category** - Get expenses for a specific category
- **Summarize by Date Range** - Calculate total spending between two dates
- **SQLite Storage** - Persistent, efficient data storage
## Requirements
- Python 3.10 or higher
- [uv](https://github.com/astral-sh/uv) package manager (recommended)
## Installation
1. Clone or navigate to the project directory:
```bash
cd expense-tracker-mcp
```
2. Install dependencies using uv:
```bash
uv sync
```
## Usage
### Running the Server
The server uses stdio transport for MCP communication:
```bash
uv run python server.py
```
### Available Tools
#### 1. `add_expense`
Add a new expense to the tracker.
**Parameters:**
| Name | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `name` | string | Yes | - | Name/description of the expense |
| `price` | integer | Yes | - | Price amount (in smallest currency unit) |
| `category` | string | Yes | - | Main category (e.g., "Food", "Clothing") |
| `sub_category` | string | No | `""` | Sub-category (e.g., "Beverages", "Men's Wear") |
| `date_added` | string | No | auto | ISO format date (e.g., "2026-03-14T19:30:00") |
**Example:**
```python
add_expense("Grocery Shopping", 5000, "Food", "Groceries")
add_expense("Movie Ticket", 1200, "Entertainment", "Movies", "2026-03-10T18:00:00")
```
---
#### 2. `read_expenses`
Retrieve all recorded expenses.
**Parameters:** None
**Returns:** List of expense objects
**Example Response:**
```json
[
{
"Name": "Grocery Shopping",
"Price": 5000,
"Category": "Food",
"SubCategory": "Groceries",
"DateAdded": "2026-03-14T19:30:00"
},
{
"Name": "Movie Ticket",
"Price": 1200,
"Category": "Entertainment",
"SubCategory": "Movies",
"DateAdded": "2026-03-10T18:00:00"
}
]
```
---
#### 3. `filter_by_category`
Get all expenses belonging to a specific category.
**Parameters:**
| Name | Type | Description |
|------|------|-------------|
| `category` | string | Category name to filter by |
**Example:**
```python
filter_by_category("Food")
```
**Example Response:**
```json
[
{
"Name": "Grocery Shopping",
"Price": 5000,
"Category": "Food",
"SubCategory": "Groceries",
"DateAdded": "2026-03-14T19:30:00"
}
]
```
---
#### 4. `summarize_expenses`
Calculate total expenses within a date range.
**Parameters:**
| Name | Type | Description |
|------|------|-------------|
| `start_date` | string | Start date in ISO format (e.g., "2026-03-01") |
| `end_date` | string | End date in ISO format (e.g., "2026-03-31") |
**Example:**
```python
summarize_expenses("2026-03-01", "2026-03-31")
```
**Example Response:**
```json
{
"StartDate": "2026-03-01",
"EndDate": "2026-03-31",
"TotalExpenses": 6200,
"ExpenseCount": 2
}
```
---
## Database Schema
Expenses are stored in a SQLite database (`expense_data.db`) with the following schema:
```sql
CREATE TABLE expenses (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
price INTEGER NOT NULL,
category TEXT NOT NULL,
sub_category TEXT,
date_added TEXT NOT NULL
);
```
## Project Structure
```
expense-tracker-mcp/
├── server.py # Main MCP server implementation
├── expense_data.db # SQLite database (auto-created)
├── expense_data.json # Legacy JSON file (not used)
├── pyproject.toml # Project configuration
├── uv.lock # Dependency lock file
├── .python-version # Python version (3.10)
└── README.md # This file
```
## Configuration
### pyproject.toml
```toml
[project]
name = "expense-tracker-mcp"
version = "0.1.0"
requires-python = ">=3.10"
dependencies = [
"fastmcp>=3.1.0",
]
```
## MCP Integration
This server is designed to work with MCP-compatible clients. Configure your MCP client to connect to this server:
**Example Claude Desktop Config:**
```json
{
"mcpServers": {
"expense-tracker": {
"command": "uv",
"args": ["run", "python", "server.py"],
"cwd": "/path/to/expense-tracker-mcp"
}
}
}
```
## Development
### Running Tests
Manual testing can be done using Python:
```bash
uv run python -c "
from server import add_expense, read_expenses, filter_by_category, summarize_expenses
# Test adding expenses
add_expense('Test Item', 100, 'Test Category')
# View all expenses
print(read_expenses())
# Filter by category
print(filter_by_category('Test Category'))
# Summarize expenses
print(summarize_expenses('2026-01-01', '2026-12-31'))
"
```
### Adding New Tools
To add new tools to the server:
1. Define a new function with the `@server.tool` decorator
2. Include type hints for all parameters
3. Add a descriptive docstring
4. Use parameterized SQL queries to prevent injection
**Example:**
```python
@server.tool
def my_new_tool(param1: str, param2: int) -> dict:
"""Description of what this tool does"""
conn = get_connection()
# ... implementation ...
conn.close()
return result
```
## License
MIT
## Contributing
1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Submit a pull request
TDQS
Scored across 4 tools
The tools are largely distinct: read_expenses returns all expenses, add_expense creates a new one, summarize_expenses aggregates by date range, and filter_by_category filters by category. There is minor overlap between read_expenses and filter_by_category, as the latter could be seen as a subset, but the descriptions clearly differentiate their purposes.
All tool names follow a consistent snake_case convention with a verb prefix (read_, add_, summarize_, filter_). The only slight deviation is 'filter_by_category' which uses a preposition, but it still aligns with the overall verb_noun style.
With 4 tools, the server is well-scoped for a basic expense tracker. Each tool serves a clear purpose, though the set feels slightly minimal for a domain that could benefit from update and delete operations.
The core operations of reading and adding expenses are covered, along with useful summaries and category filtering. However, there are notable gaps: no update or delete expense functionality, and filtering is only by category, not by date range (only totals via summarize). These omissions may limit agents that need full lifecycle management.