Expense MCP Server
A production-ready MCP server for managing personal expenses with 8 tools for CRUD operations and summaries, deployable locally, in Docker, or on Render.
README
πΈ Expense MCP Server
A production-ready Model Context Protocol (MCP) server for managing personal expenses β built with FastMCP, SQLAlchemy, and Pydantic. Deploys as a Docker container on Render with PostgreSQL, and connects to Claude Desktop, Cursor, VS Code, or any MCP-compatible client.
Status
β Live on Render β Docker Β· PostgreSQL Β· Streamable HTTP
| Transport | Streamable HTTP |
| Database | PostgreSQL (Render managed) |
| Health endpoint | /health |
| MCP endpoint | /mcp |
Architecture
Claude Desktop / Cursor / VS Code MCP
β
β MCP over Streamable HTTP
βΌ
βββββββββββββββββββββββ
β Expense MCP Server β Docker Β· Render
β FastMCP + Uvicorn β
ββββββββββ¬βββββββββββββ
β
βΌ
βββββββββββββββββββββββ
β Expense Service β Business logic
ββββββββββ¬βββββββββββββ
β
βΌ
βββββββββββββββββββββββ
β Repository β Data access layer
ββββββββββ¬βββββββββββββ
β
βΌ
βββββββββββββββββββββββ
β SQLAlchemy ORM β
ββββββββββ¬βββββββββββββ
β
βΌ
βββββββββββββββββββββββ
β PostgreSQL / SQLiteβ Prod / Dev
βββββββββββββββββββββββ
API Request Flow
Claude β MCP Tool β FastMCP β Expense Service β Repository β SQLAlchemy β PostgreSQL
β¨ Features
- 8 MCP Tools β add, list, update, delete, search expenses, and get monthly/category/merchant summaries
- Dual transport β STDIO (local Claude Desktop) and Streamable HTTP (remote/Docker/Render)
- Dual database β SQLite for local development, PostgreSQL for production
- Production-ready β structured logging, custom exceptions, connection pooling, non-root Docker user
- 31 tests β full repository, service, and tool coverage with in-memory SQLite isolation
- One-command deploy β
render.yamlBlueprint auto-provisions PostgreSQL + Docker web service
Production Features
| Feature | Detail |
|---|---|
| β Docker multi-stage image | Minimal, hardened runtime layer |
| β PostgreSQL | Render-managed with connection pooling |
| β Render Blueprint | Auto-provisions all infrastructure |
| β Health endpoint | /health for Render and load balancer checks |
| β Remote HTTP MCP | Accessible at /mcp from any MCP client |
| β Connection pooling | pool_size=5, max_overflow=10, pool_recycle=1800 |
| β Structured logging | ISO timestamps, log levels, logger names |
| β Non-root container | appuser with no escalation |
| β Automatic DB provisioning | Tables created on first startup |
Compatible Clients
β
Claude Desktop
β
Cursor
β
VS Code MCP extension
β
Any MCP client supporting Streamable HTTP
Transport Modes
| Transport | When to use |
|---|---|
stdio |
Local Claude Desktop β server runs as a child process |
streamable-http |
Remote deployment, Docker, Render β server listens on HTTP |
π Project Structure
expense-mcp-server/
βββ app/
β βββ config.py # Pydantic Settings (reads from .env)
β βββ exceptions.py # ExpenseNotFoundError, ExpenseValidationError
β βββ logging_config.py # Structured logging setup
β βββ mcp_instance.py # FastMCP instance + /health endpoint
β βββ server.py # Registers all 8 tools
β βββ database/
β β βββ db.py # Engine, SessionLocal, validate_connection()
β β βββ models.py # Expense SQLAlchemy model
β βββ schemas/
β β βββ expense.py # ExpenseCreate, ExpenseUpdate (Pydantic)
β βββ repositories/
β β βββ expense_repository.py
β βββ services/
β β βββ expense_service.py
β βββ tools/
β β βββ add_expense.py
β β βββ list_expenses.py
β β βββ update_expense.py
β β βββ delete_expense.py
β β βββ search_expenses.py
β β βββ monthly_summary.py
β β βββ category_summary.py
β β βββ top_merchants.py
β βββ utils/
β βββ dates.py
β βββ currency.py
βββ tests/
β βββ conftest.py # In-memory SQLite fixtures + monkeypatch
β βββ test_expense.py # 31 tests
βββ run.py # Entry point
βββ requirements.txt
βββ Dockerfile # Multi-stage Docker build
βββ docker-compose.yml # App + PostgreSQL local stack
βββ render.yaml # Render Blueprint (PostgreSQL + Docker web service)
βββ .env # Local environment variables
π MCP Tools
| Tool | Description |
|---|---|
add_expense |
Add a new expense with amount, category, date, merchant, currency |
list_expenses |
List all expenses sorted by date descending |
update_expense |
Update any field of an existing expense by ID |
delete_expense |
Delete an expense by ID |
search_expenses |
Search by category, description, or merchant |
monthly_summary |
Total, count, average, and max for the current month |
category_summary |
Spending totals grouped by category |
top_merchants |
Top merchants by total spending |
βοΈ Environment Variables
| Variable | Default | Description |
|---|---|---|
APP_ENV |
development |
development or production |
LOG_LEVEL |
INFO |
Python log level |
MCP_SERVER_NAME |
Expense Tracker |
Name shown in Claude Desktop |
TRANSPORT |
stdio |
stdio or streamable-http |
HOST |
0.0.0.0 |
Bind host (HTTP mode only) |
PORT |
8000 |
Bind port for local/Docker. Render injects PORT=10000 automatically β no manual configuration needed. |
DATABASE_URL |
sqlite:///./expenses.db |
SQLite or PostgreSQL connection string |
π Getting Started
Option A β Local Development (STDIO + SQLite)
1. Clone and create a virtual environment
git clone https://github.com/your-username/expense-mcp-server.git
cd expense-mcp-server
python -m venv .venv
2. Activate the virtual environment
# Windows
.venv\Scripts\activate
# macOS / Linux
source .venv/bin/activate
3. Install dependencies
pip install -r requirements.txt
4. Configure .env
APP_ENV=development
LOG_LEVEL=INFO
MCP_SERVER_NAME=Expense Tracker
TRANSPORT=stdio
HOST=0.0.0.0
PORT=8000
DATABASE_URL=sqlite:///./expenses.db
5. Run the server
python run.py
The server starts in STDIO mode β ready to be used with Claude Desktop.
Option B β Local Docker + PostgreSQL (HTTP)
1. Start the full stack
docker-compose up --build
This starts:
expense_postgresβ PostgreSQL 16 on port 5432expense_mcpβ MCP server on port 8000 (Streamable HTTP transport)
The app waits for PostgreSQL to pass its health check before starting.
2. Verify it's running
curl http://localhost:8000/health
Option C β Deploy to Render (Docker + PostgreSQL)
The project deploys as a Docker multi-stage image on Render.
1. Push your repo to GitHub
2. Go to render.com β New β Blueprint
3. Connect your GitHub repo β Render auto-detects render.yaml and automatically creates:
- A managed PostgreSQL database
- A Docker web service running
run.py - All required environment variables
- Database connection wired via
fromDatabase.connectionString
4. Your server will be live at:
https://<your-render-service>.onrender.com
Replace
<your-render-service>with your actual Render service name (shown in the dashboard after deployment).
π Health Check
The server exposes /health for Render and load balancer health checks.
curl https://<your-render-service>.onrender.com/health
Response:
{"status": "ok"}
π Verify the MCP Endpoint
GET https://<your-render-service>.onrender.com/mcp
Note: A browser will show
405 Method Not Allowed. This is expected β/mcpspeaks the MCP protocol (not plain HTTP GET). Use an MCP client to connect.
π₯ Claude Desktop Configuration
Add to %APPDATA%\Claude\claude_desktop_config.json (Windows) or
~/Library/Application Support/Claude/claude_desktop_config.json (macOS).
Option A β Local STDIO
{
"mcpServers": {
"expense-tracker": {
"command": "C:\\path\\to\\expense-mcp-server\\.venv\\Scripts\\python.exe",
"args": ["C:\\path\\to\\expense-mcp-server\\run.py"]
}
}
}
Option B β Render (Remote HTTP)
{
"mcpServers": {
"expense-tracker": {
"type": "streamable-http",
"url": "https://<your-render-service>.onrender.com/mcp"
}
}
}
Option C β Docker (Local HTTP)
{
"mcpServers": {
"expense-tracker": {
"type": "streamable-http",
"url": "http://localhost:8000/mcp"
}
}
}
You can include all three entries simultaneously β just give each a unique key.
π§ͺ Running Tests
python -m pytest tests/ -v
Expected output:
31 passed in ~1s
The test suite covers:
TestExpenseRepositoryβ 13 tests (CRUD + search + summaries)TestExpenseServiceβ 10 tests (business logic + error handling)TestToolsβ 8 tests (MCP tool integration)
Tests use an in-memory SQLite database with full transaction rollback isolation between each test.
π Database
SQLite (Local)
Zero configuration. The expenses.db file is created automatically on first run.
DATABASE_URL=sqlite:///./expenses.db
PostgreSQL (Docker / Production)
DATABASE_URL=postgresql://expense_user:expense_pass@localhost:5432/expense_db
The Expense table is created automatically via Base.metadata.create_all() on startup.
| Column | Type | Notes |
|---|---|---|
id |
Integer | Primary key |
amount |
Float | Required, must be > 0 |
category |
String | Required |
description |
String | Optional |
merchant |
String | Optional |
payment_method |
String | Optional |
currency |
String | Default: INR |
expense_date |
Date | Required |
created_at |
DateTime | Auto-set to UTC now |
π¦ Tech Stack
| Layer | Library | Version |
|---|---|---|
| MCP Framework | mcp (FastMCP) |
1.28.1 |
| Settings | pydantic-settings |
2.14.2 |
| ORM | SQLAlchemy |
2.0.51 |
| Validation | pydantic |
2.13.4 |
| PostgreSQL driver | psycopg2-binary |
2.9.10 |
| HTTP server | uvicorn + starlette |
β |
| Testing | pytest |
9.1.1 |
π License
MIT
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.