Skip to main content
Glama
andreajrubino

expense-tracker

Expense Tracker MCP Server

Enterprise-grade documentation for a Python-based Model Context Protocol (MCP) expense tracking server.

āš ļø Proof of Concept (PoC)

This is a quick and dirty implementation based on frameworks and libraries available as of February 2026.

Behavior, APIs, and integration patterns may evolve in future versions of FastMCP, OpenAI Codex, and related tooling. This is just for demonstrative purposes


Table of Contents

  1. Introduction

  2. Architecture Overview

  3. Environment Setup (uv-based)

  4. Installed Packages

  5. Project Structure

  6. MCP Server Overview

  7. Core Functional Components

  8. Excel Storage Layer

  9. Running the Server

  10. Testing with MCP Inspector

  11. Integrating with Codex in VS Code

  12. Operational Considerations

  13. Future Improvements


1. Introduction

This project implements a local Model Context Protocol (MCP) server using Python and FastMCP.

šŸ“¢ Educational Proof of Concept

This repository contains intentionally simple and demonstrative code designed to get started with MCP servers and understand how they work. The implementation prioritizes clarity and approachability over production-grade architecture, advanced patterns, or highly optimized design.

The server allows natural-language expense logging such as:

"I spent 20 dollars on a Batman figure yesterday"

The server:

  • Parses the amount

  • Detects currency

  • Extracts relative or explicit dates

  • Stores the result in an Excel file

  • Exposes tools via MCP for AI agents (e.g., OpenAI Codex in VS Code)

This project demonstrates:

  • Local stdio-based MCP server design

  • Natural language parsing

  • Structured data persistence

  • Tool registration via FastMCP

  • Integration with OpenAI Codex UI

Example result in Codex on VS Code

MCP Architecture


2. Architecture Overview

The solution consists of:

  • FastMCP stdio server

  • Natural language parser

  • Excel persistence layer (openpyxl)

  • Tool registration via decorators

  • Local stdio transport for MCP communication

Transport Type: - STDIO (standard input/output)

Data Storage: - Excel file (expenses.xlsx)

Execution Model: - Event-driven tool invocation


3. Environment Setup (uv-based)

The environment was configured using uv for fast dependency management.

Related MCP server: Expense Tracker MCP Server

Initialize project

uv init

Add required packages

uv add fastmcp openpyxl dateparser pypandoc

This creates:

  • Virtual environment

  • Dependency resolution

  • Lockfile

  • Reproducible environment


4. Installed Packages

Package Purpose


fastmcp MCP server implementation openpyxl Excel read/write operations dateparser Natural language date parsing pypandoc Documentation generation re Regex amount parsing pathlib File handling datetime Timestamp management


5. Project Structure

project-root/
│
ā”œā”€ā”€ server.py
ā”œā”€ā”€ expenses.xlsx
ā”œā”€ā”€ README.md
└── .venv/

6. MCP Server Overview

The server is initialized as:

mcp = FastMCP("expense-tracker")

Tools are registered using:

@mcp.tool

The server starts via:

if __name__ == "__main__":
    mcp.run()

The server communicates using STDIO and must not print to stdout.


7. Core Functional Components

7.1 _parse_amount(raw)

Extracts numeric amount using regex. Handles: - 12.000,16 - 12,000.16 - 12000

Returns:

float

7.2 _parse_currency(raw)

Detects: - $ → USD - € → EUR - Ā£ → GBP - keyword matches (dollars, euro, etc.)

Returns ISO currency code.


7.3 _parse_date_iso(raw)

Uses:

dateparser.search.search_dates()

Configuration: - PREFER_DATES_FROM = "past" - RELATIVE_BASE = datetime.now() - RETURN_AS_TIMEZONE_AWARE = False

Returns:

YYYY-MM-DD

Fallback: - If no date detected → today


7.4 _parse_expense(text)

Combines: - amount - currency - date - description

Returns structured dictionary:

{
    "amount": float,
    "currency": str,
    "date_iso": str,
    "description": str
}

8. Excel Storage Layer

Excel file created if missing:

expenses.xlsx

Header structure:

["Date", "Description", "Amount", "Currency", "Raw Text", "Logged At"]

Append logic ensures: - Workbook exists - Correct sheet name - ISO timestamp logging

Read logic: - Dynamically maps header row - Avoids tuple index errors - Skips blank rows


9. Running the Server

Direct execution

.\.venv\Scripts\python.exe server.py

The process should remain running (stdio server).


10. Testing with MCP Inspector

Launch:

npx @modelcontextprotocol/inspector python server.py

Steps: 1. Open browser UI 2. View tools 3. Call log_expense 4. Call list_expenses


11. Integrating with Codex in VS Code

Open Codex MCP UI

"Connect to a custom MCP"

Select: - STDIO

Configuration

Command to launch:

C:\Users\andre\Documents\Python\MCP\Python\Stdio Server\.venv\Scripts\python.exe

Arguments:

C:\Users\andre\Documents\Python\MCP\Python\Stdio Server\server.py

No environment variables required.

After saving: - Enable the MCP tool - Use in Codex chat:

Example:

Log this expense: I spent 50 dollars on groceries yesterday

12. Operational Considerations

  • Do not print to stdout

  • Use stderr for debugging

  • Always use absolute python path

  • Ensure virtual environment consistency

  • Keep Excel closed during writes

  • Consider file locking for production use


13. Future Improvements

  • Category auto-detection

  • Deduplication logic

  • CSV export

  • SQLite backend

  • Multi-user storage

  • Authentication layer

  • Cloud deployment (HTTP MCP)

  • Structured validation with Pydantic


Available Tools

2 tools
list_expensesA

Return the last N logged expenses.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries full burden. It states the basic behavior but omits details like ordering (e.g., latest first) and edge cases (e.g., fewer expenses than limit).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, well-structured sentence that conveys the purpose efficiently with no wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description is nearly complete for a simple list tool with one parameter and an output schema, but it lacks explicit mention of ordering (e.g., descending by date) and behavior when the limit exceeds available expenses.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description adds meaning to the 'limit' parameter by linking it to 'last N', compensating for the 0% schema description coverage. It clarifies what the parameter controls, though it could mention the default value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('return'), the resource ('expenses'), and the qualifier ('last N logged'), distinguishing it from the sibling tool 'log_expense' which presumably logs expenses.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for retrieving recent expenses but does not explicitly state when to use this tool versus the sibling 'log_expense', nor provide any exclusions or alternative scenarios.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

log_expenseD
ParametersJSON Schema
NameRequiredDescriptionDefault
textYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

D1/5.0
Behavior1/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Tool has no description.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness1/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Tool has no description.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness1/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Tool has no description.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Tool has no description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose1/5

Does the description clearly state what the tool does and how it differs from similar tools?

Tool has no description.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines1/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Tool has no description.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 2 tool updatesv0.1.0
    • First observedlist_expenses
    • First observedlog_expense

TDQS

C2.5/5.0

Scored across 2 tools

Disambiguation5/5

The two tools have clearly distinct purposes: listing expenses and logging a new expense. There is no overlap in functionality.

Naming Consistency5/5

Both tool names follow a consistent verb_noun pattern with snake_case (list_expenses, log_expense).

Tool Count3/5

With only 2 tools, the server feels underdeveloped for an expense tracker, which typically requires at least CRUD operations. However, the count is not extreme for a minimal prototype.

Completeness2/5

The tool set lacks essential operations like updating or deleting expenses, and log_expense has no description, making it incomplete for basic expense management.

Maintenance

ActivityInactive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables users to track and manage personal expenses through natural language, including adding entries, filtering by date/category, viewing statistics, and exporting data in JSON or CSV format.
    3
    -
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables users to track expenses by adding, listing, and summarizing them with category support through natural language.
    -
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables natural language management of personal expenses, including adding, listing, and summarizing expenses with local SQLite storage.
    -
  • F
    license
    A
    quality
    C
    maintenance
    Enables natural language management of personal expenses, including adding, updating, deleting, searching, and summarizing expenses stored in a local SQLite database.
    6
    -