Skip to main content
Glama
PranaPragada7

Expense Tracker MCP Server

Expense Tracker Platform

CI Coverage Python FastAPI PostgreSQL Docker MCP

An authenticated expense-management API and local AI assistant. The production backend provides user-isolated financial data, PostgreSQL migrations, analytics, idempotent writes, and structured operational signals. The original Streamlit and MCP workflow remains available as a private, single-user AI demonstration.

Expense Tracker interface

Engineering signals

  • FastAPI endpoints with explicit Pydantic request and response contracts

  • Argon2 password hashing and expiring JWT bearer authentication

  • Authorization enforced through user-scoped repository queries

  • PostgreSQL and SQLite support through SQLAlchemy 2

  • Auditable Alembic migrations and automated migration-drift detection

  • Decimal-backed currency values instead of floating-point persistence

  • Pagination, date/category/search filters, and monthly aggregation

  • Idempotency keys that prevent duplicate expense creation during retries

  • Structured request logs, correlation IDs, liveness, and database readiness

  • Non-root containers and a locally bound Docker Compose environment

  • Offline API tests plus migration-backed PostgreSQL integration tests in CI

  • Direct Claude tool use through an 18-tool MCP server for the local assistant

Related MCP server: Expense Tracker MCP Server

Architecture

flowchart LR
    Client[API client] --> API[FastAPI]
    API --> Auth[JWT authentication]
    API --> Service[Business services]
    Service --> Repo[User-scoped repositories]
    Repo --> ORM[SQLAlchemy]
    ORM --> PG[(PostgreSQL)]

    LocalUser[Local user] --> UI[Streamlit]
    UI --> Agent[Claude agent]
    Agent --> MCP[MCP server]
    MCP --> SQLite[(Private SQLite)]

The API path is the production-style, multi-user boundary. Authentication is resolved before business logic, and every category and expense query is scoped to the authenticated user. The local AI path is deliberately private and can be run without exposing personal financial records as a public service.

API capabilities

Area

Endpoint

Behavior

Health

GET /health/live

Process liveness

Health

GET /health/ready

Database readiness

Accounts

POST /api/v1/auth/register

Create an Argon2-protected account

Accounts

POST /api/v1/auth/token

Issue a short-lived bearer token

Accounts

GET /api/v1/me

Read the current identity

Categories

GET/POST /api/v1/categories

Manage user-owned categories

Expenses

GET/POST /api/v1/expenses

Paginated, filtered workflows

Expenses

GET/PATCH/DELETE /api/v1/expenses/{id}

Isolated lifecycle operations

Analytics

GET /api/v1/analytics/monthly

Category-level monthly totals

Send an Idempotency-Key header when creating an expense. Repeating the same request with that key returns the previously created record and identifies the response with X-Idempotent-Replay: true.

Keys are scoped to the authenticated user. Reusing a key with different creation fields returns 409 Conflict; concurrent matching retries recover from the database unique constraint. Amounts such as 12.3 and 12.30 are equivalent. A replay returns the current expense record, even if it has subsequently been edited. Keys live for the lifetime of the expense; deleting the expense also releases its key. Clients should send an explicit expense_date when retrying across dates.

Migration 0002 stores immutable creation fingerprints. For existing keyed rows, it snapshots their values at migration time because older versions did not retain the original request. An old request that differs from that snapshot returns 409.

PATCH requests omit unchanged fields. Explicit null values and whitespace-only names or descriptions return 422 without changing stored data.

Run the API locally

Requirements: Python 3.11 or newer.

python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install -r requirements-dev.txt
Copy-Item .env.example .env
python -m alembic upgrade head
python -m uvicorn expense_tracker.api:app --reload

On macOS or Linux, activate the environment with:

source .venv/bin/activate

The default API database is the ignored local file expense_api.db. Open http://127.0.0.1:8000/docs for the interactive OpenAPI documentation.

For local PostgreSQL and the API container:

docker compose up --build

The compose file binds the API only to 127.0.0.1:8000; it does not deploy or publish anything to a cloud provider. Stop the stack with docker compose down. Add --volumes only when you intentionally want to delete the local PostgreSQL data volume.

Example API workflow

Register an account:

$account = @{
  email = "developer@example.test"
  password = "choose-a-long-local-password"
  display_name = "Developer"
} | ConvertTo-Json

Invoke-RestMethod `
  -Method Post `
  -Uri http://127.0.0.1:8000/api/v1/auth/register `
  -ContentType application/json `
  -Body $account

The generated OpenAPI interface provides authenticated examples for the remaining endpoints without requiring a separate REST client.

Run the local AI assistant

The private assistant requires an Anthropic API key. Set ANTHROPIC_API_KEY in .env, initialize its separate local demonstration database, and launch the UI:

python db_setup.py
streamlit run streamlit_app.py

The MCP server uses stdio and starts automatically when the assistant connects. Manual entry and spending insights work locally; assistant requests require an available Anthropic account and quota.

MCP tool inventory

  • Category management: list_categories, add_category, rename_category, delete_category, get_category_name

  • Expense management: add_expense, update_expense, delete_expense, list_expenses, search_expenses, expenses_by_category, total_expense_by_category, total_expense, monthly_summary

  • Supporting queries: current_date, find_category, get_expense, expenses_between

Validation

Run the same core checks used in CI:

python -m black --check .
python -m ruff check .
python -m compileall -q agent.py client_test.py db_setup.py mcp_client.py server.py streamlit_app.py expense_tracker migrations
python -m pytest -q
python client_test.py
python -m alembic check

CI tests Python 3.11, 3.12, and 3.13. A separate infrastructure job starts PostgreSQL, applies every migration, checks schema drift, exercises an authenticated expense round trip, validates Compose, and builds the API image.

Project structure

Path

Purpose

expense_tracker/api.py

HTTP routes, dependencies, health, request context

expense_tracker/models.py

User, category, and expense relational models

expense_tracker/repositories.py

Authenticated user-scoped persistence

expense_tracker/services.py

Transactions and business rules

expense_tracker/security.py

Argon2 and JWT primitives

expense_tracker/schemas.py

Validated API contracts

migrations/

Versioned PostgreSQL and SQLite schema changes

compose.yaml

Local API and PostgreSQL environment

streamlit_app.py

Private single-user interface

agent.py

Direct Claude tool-calling loop

server.py

Local SQLite operations exposed as MCP tools

tests/

API, authorization, MCP, database, and UI checks

Configuration

Variable

Required

Default

Purpose

DATABASE_URL

No

sqlite:///./expense_api.db

API persistence

JWT_SECRET

Production

Local development value

Bearer-token signing

ACCESS_TOKEN_MINUTES

No

60

Token lifetime

APP_ENV

No

development

Runtime safety mode

LOG_LEVEL

No

INFO

Structured log threshold

ANTHROPIC_API_KEY

AI assistant

None

Claude authentication

ANTHROPIC_MODEL

No

claude-sonnet-5

Assistant model

EXPENSE_DB

No

expenses.db

Private MCP demo storage

Production mode refuses to start with the built-in development JWT secret. Secrets, tokens, local databases, and personal expense records are excluded from Git.

Security scope

The API demonstrates application security controls but has not undergone an independent security audit. It does not connect to banks, process payments, or provide financial advice. Use generated secrets, TLS, rate limiting at the edge, managed backups, and an external security review before handling real sensitive data in a shared environment.

See CHANGELOG.md for release history and CONTRIBUTING.md for contribution guidance.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

  • Log, query, and edit expenses, budgets, and accounts in Manilo from any MCP-compatible AI assistant.

  • Log, query, and edit expenses, budgets, and accounts in Manilo (formerly Ledgy) from any MCP-compatible AI assistant.

  • Log, query, and edit expenses, budgets, and accounts in Ledgy from any MCP-compatible AI assistant.

  • The Ramp MCP server enables users to securely connect Ramp with AI assistants like ChatGPT and Claude to query financial data and take actions using natural language. It transforms Ramp's developer API into a SQL interface that LLMs can query, allowing admins to analyze spend trends, identify cost savings, and run complex SQL analyses on comprehensive datasets (transactions, purchase orders, vendors, users), while all users can manage cards, view transactions, request reimbursements, and get expense policy answers.

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to manage personal expenses through natural conversation, supporting expense tracking, categorization, filtering, and financial summaries. Uses SQLite database to store expense records with full CRUD operations for comprehensive personal finance management.
    1
    -
  • F
    license
    C
    quality
    D
    maintenance
    Enables personal expense management with SQLite storage, allowing users to add, update, delete, list, and summarize expenses by category through natural language interactions.
    5
    -
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables management of expenses via SQLite database, including adding, listing, updating, deleting, filtering, and summing expenses through natural language.
    -