Expense MCP Server

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.

Category
Visit Server

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.yaml Blueprint 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 5432
  • expense_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 β€” /mcp speaks 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

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.

Official
Featured
TypeScript
Magic Component Platform (MCP)

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.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

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.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

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.

Official
Featured
TypeScript
Kagi MCP Server

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.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

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.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured