Expense Tracker MCP Server
Stores parsed receipt data, expense items, and purchase history in a local SQLite database with support for querying transactions, item categories, and spending statistics.
Parses PDF receipts from Target stores to extract line items, prices, and purchase metadata for expense tracking.
Parses PDF receipts from Walmart stores to extract line items, prices, and purchase metadata for expense tracking.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Expense Tracker MCP ServerWhen did I last buy eggs?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Expense Tracker MCP Server
A local Model Context Protocol (MCP) server that helps you track grocery and shopping expenses by parsing PDF receipts, automatically categorizing items, and storing them in a SQLite database for easy querying.
Features
PDF Receipt Parsing: Extract line items, prices, and metadata from PDF receipts
Smart Categorization: Hybrid approach using static rules + LLM fallback for item classification
SQLite Storage: Persistent local database for all your expense data
Query Tools: Ask questions like "When did I last buy milk?" or "How often do I buy bread?"
Multi-Store Support: Works with receipts from Walmart, Costco, Target, and more
Related MCP server: Expense Tracker MCP Server
Installation
Prerequisites
Python 3.11 or higher
uv (recommended) or pip
Step 1: Clone or Download
cd /Users/sharan/Desktop/expense_tracker_mcpStep 2: Install Dependencies
Using uv (recommended):
uv syncUsing pip:
pip install -r requirements.txtStep 3: Initialize Database
The database is automatically initialized when you first run the server. The SQLite database will be created at data/expenses.db.
Running Locally
To test the server locally:
python main.pyor with uv:
uv run main.pyThe server will start and listen on stdin/stdout (MCP protocol).
Connecting to Claude Desktop
Step 1: Locate Claude Desktop Config
The configuration file is located at:
macOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%APPDATA%/Claude/claude_desktop_config.jsonLinux:
~/.config/Claude/claude_desktop_config.json
Step 2: Add MCP Server Configuration
Edit the config file and add this entry to mcpServers:
{
"mcpServers": {
"expense-tracker": {
"command": "uv",
"args": [
"--directory",
"/Users/sharan/Desktop/expense_tracker_mcp",
"run",
"main.py"
]
}
}
}Alternative (using python directly):
{
"mcpServers": {
"expense-tracker": {
"command": "/Users/sharan/Desktop/expense_tracker_mcp/.venv/bin/python",
"args": [
"/Users/sharan/Desktop/expense_tracker_mcp/main.py"
]
}
}
}Step 3: Restart Claude Desktop
After saving the config, restart Claude Desktop to load the MCP server.
Usage
Once connected to Claude Desktop, you can use these tools:
1. Import a Receipt
Upload a PDF receipt and the server will parse it:
Import this receipt: /path/to/walmart_receipt.pdfExample Response:
{
"status": "success",
"receipt_id": 1,
"store_name": "Walmart",
"purchase_date": "2025-01-15",
"total": 45.67,
"items_count": 12,
"item_types": {
"milk": 1,
"bread": 1,
"eggs": 1,
"veggies": 3,
"snacks": 2,
"beverages": 2,
"meat": 2
}
}2. Query Item History
Ask when you last bought something:
When did I last buy milk?or
Show me all my milk purchases in the last 6 monthsExample Response:
{
"item_type": "milk",
"purchases": [
{
"date": "2025-01-15",
"store": "Walmart",
"item_name": "Organic Milk 2%",
"quantity": 1.0,
"price": 4.99
},
{
"date": "2024-12-28",
"store": "Costco",
"item_name": "Kirkland Milk",
"quantity": 2.0,
"price": 6.99
}
],
"stats": {
"total_purchases": 2,
"last_purchase_date": "2025-01-15",
"first_purchase_date": "2024-12-28",
"average_days_between": 18.0,
"total_spent": 11.98
}
}3. List All Categories
See all item types you've purchased:
What categories of items have I bought?Example Response:
{
"item_types": [
{
"item_type": "milk",
"total_purchases": 12,
"last_purchase_date": "2025-01-15",
"total_spent": 59.88
},
{
"item_type": "bread",
"total_purchases": 8,
"last_purchase_date": "2025-01-10",
"total_spent": 27.92
}
],
"total_categories": 15
}Supported Item Categories
The categorizer recognizes these item types out of the box:
Dairy: milk, oatmilk, eggs, cheese, yogurt, butter
Grains: bread, rice, lentils, pasta, cereal
Produce: veggies, fruits, potatoes
Proteins: meat, fish
Snacks & Beverages: snacks, beverages
Pantry: oil, spices, sauce
Household: cleaning, paper
Fallback: other (for unrecognized items)
Adding New Categories
Edit expense_tracker/categorizer.py and add patterns to the ITEM_TYPE_MAPPINGS dictionary:
ITEM_TYPE_MAPPINGS = {
# ... existing categories ...
"tofu": ["tofu", "bean curd", "soy protein"],
}Database Schema
The SQLite database (data/expenses.db) contains two main tables:
receipts
id: Auto-increment primary keystore_name: Store name (e.g., "Walmart")purchase_date: ISO format date (YYYY-MM-DD)subtotal: Subtotal amount (nullable)tax: Tax amount (nullable)total: Total amount (required)created_at: Timestamp
items
id: Auto-increment primary keyreceipt_id: Foreign key to receipts tableitem_name_raw: Original item name from receiptitem_type: Normalized categoryquantity: Item quantity (default: 1.0)unit_price: Price per unit (nullable)line_total: Total price for this linecreated_at: Timestamp
How It Works
1. PDF Parsing
Uses pdfplumber to extract text from PDF files, then applies regex patterns to identify:
Store name (Walmart, Costco, Target, etc.)
Purchase date (multiple date formats supported)
Line items with quantities and prices
Totals (subtotal, tax, total)
2. Item Categorization
Hybrid approach:
Static Rules (fast, deterministic)
Checks item name against pre-defined patterns
Handles common grocery items with keyword matching
~90% accuracy for typical grocery items
LLM Fallback (smart, adaptive)
Uses Claude via FastMCP's
Context.sample()for unknown itemsProvides better accuracy for unusual or new items
Automatically adapts to items not in static mappings
3. Database Storage
All data is stored in a local SQLite database with proper indexing for fast queries:
Indexes on
purchase_date,store_name,item_typeForeign key constraints for data integrity
Support for aggregate queries and statistics
Troubleshooting
Server not appearing in Claude Desktop
Check that the path in
claude_desktop_config.jsonis correctRestart Claude Desktop completely
Check Claude Desktop logs for errors
PDF parsing errors
Ensure the PDF is text-based (not a scanned image)
Try opening the PDF in a viewer to verify it contains selectable text
Check that the file path is absolute, not relative
Database locked errors
Close any other tools accessing
data/expenses.dbMake sure only one instance of the server is running
Development
Running Tests
pytest tests/Adding New Features
The modular architecture makes it easy to extend:
New categorization rules: Edit
expense_tracker/categorizer.pyNew receipt formats: Update patterns in
expense_tracker/pdf_parser.pyNew MCP tools: Add tool functions to
main.pywith@mcp.tooldecoratorDatabase changes: Modify schema in
expense_tracker/database.py
License
MIT License - feel free to use and modify for your needs.
Contributing
Contributions welcome! Areas for improvement:
Support for more receipt formats
Better item categorization rules
Export to CSV/Excel functionality
Visualization dashboards
Multi-user support
Support
For issues or questions:
Check the FastMCP documentation
Review MCP protocol docs
File an issue on GitHub
Built with FastMCP - The fast, Pythonic way to build MCP servers
Available Tools
3 toolsget_item_historyA
Query purchase history for a specific item type.
Returns detailed purchase history including:
List of all purchases with dates, stores, quantities, and prices
Statistics: total purchases, date range, average frequency, total spent
Args: item_type: Category to query (e.g., 'milk', 'bread', 'eggs') time_range_days: Number of days to look back (default: 365)
Returns: Dictionary with purchases list and aggregated statistics
| Name | Required | Description | Default |
|---|---|---|---|
| item_type | Yes | Item category to query (e.g., 'milk', 'bread', 'eggs') | |
| time_range_days | No | Number of days to look back (default: 365) |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It describes the return format in detail (list of purchases with specific fields and aggregated statistics), which is valuable context. However, it lacks information on potential limitations, such as data availability, error handling, or performance considerations (e.g., large datasets). This partial coverage results in a baseline score.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured and appropriately sized, starting with the core purpose, detailing return values, and listing parameters. Each sentence serves a clear purpose: the first states the action, the next two outline outputs, and the last specifies args and returns. It could be slightly more concise by avoiding redundancy with the schema, but overall, it's efficient and front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity (2 parameters, read-only query), no annotations, and the presence of an output schema (implied by 'Returns' section), the description is reasonably complete. It explains what the tool does, what it returns, and the parameters, compensating for the lack of annotations. However, it misses some behavioral context like data source or limitations, preventing a perfect score.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, meaning the input schema already fully documents both parameters ('item_type' and 'time_range_days') with descriptions and defaults. The description repeats some of this information (e.g., examples for 'item_type' and the default for 'time_range_days'), adding minimal value beyond the schema. According to the rules, with high schema coverage, the baseline is 3 even without additional param info in the description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose as 'Query purchase history for a specific item type,' which is a specific verb ('query') + resource ('purchase history') combination. It distinguishes itself from sibling tools like 'import_receipt_from_pdf' (data ingestion) and 'list_item_types' (metadata listing) by focusing on historical data retrieval. However, it doesn't explicitly contrast with potential alternatives for querying history, keeping it from a perfect score.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for retrieving purchase history based on item type and time range, but provides no explicit guidance on when to use this tool versus alternatives. There's no mention of prerequisites, such as needing existing data from 'import_receipt_from_pdf,' or exclusions like not handling real-time data. This leaves usage context somewhat vague, relying on the agent to infer from the purpose.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
import_receipt_from_pdfA
Import and parse a receipt from a PDF file.
This tool:
Extracts text from the PDF
Parses receipt metadata (store, date, totals)
Extracts line items with prices
Categorizes each item using hybrid approach (static rules + LLM)
Stores everything in SQLite database
Args: pdf_path: Absolute path to the PDF receipt file ctx: FastMCP context for logging and LLM access
Returns: Summary of imported receipt including store, date, item count, and category breakdown
| Name | Required | Description | Default |
|---|---|---|---|
| pdf_path | Yes | Absolute path to PDF receipt file |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full burden and does well by detailing the multi-step behavior (extraction, parsing, categorization, storage). It explains the hybrid categorization approach and mentions database storage, though it could add more about error handling, performance, or permissions needed for file access.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a clear opening sentence, bullet points for steps, and separate sections for Args and Returns. It's appropriately sized but could be slightly more concise by integrating the Args section into the main text since it repeats schema information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (multi-step processing), no annotations, and the presence of an output schema, the description is fairly complete. It outlines the process and return values, though it could benefit from mentioning error cases or limitations (e.g., PDF quality requirements).
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents the single parameter 'pdf_path'. The description adds minimal value beyond the schema by restating the parameter in the 'Args' section without providing additional context like file format constraints or examples.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the specific action ('Import and parse a receipt from a PDF file') and details the multi-step process (extract text, parse metadata, extract line items, categorize, store). It distinguishes itself from sibling tools like 'get_item_history' and 'list_item_types' by focusing on data ingestion rather than querying existing data.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage when needing to process PDF receipts, but lacks explicit guidance on when to use this tool versus alternatives (none mentioned) or any prerequisites. It doesn't specify scenarios where this tool is preferred or when it should be avoided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_item_typesA
List all item types/categories in the database with statistics.
Returns summary statistics for each item type including:
Total number of purchases
Most recent purchase date
Total amount spent
Useful for getting an overview of all tracked expense categories.
Returns: Dictionary with list of all item types and their statistics
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It effectively describes the tool's behavior by specifying what statistics are returned (total purchases, recent purchase date, total amount spent) and the output format (dictionary with list). It does not cover aspects like rate limits or error handling, but provides solid operational context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured and front-loaded with the core purpose, followed by bullet points for statistics and a usage note. Every sentence adds value without redundancy, making it efficient and easy to parse.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's low complexity (0 parameters), no annotations, and the presence of an output schema (which handles return values), the description is complete. It covers purpose, behavior, usage context, and output semantics adequately without needing to explain parameters or duplicate schema details.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 0 parameters with 100% coverage, so the baseline is 4. The description adds no parameter information, which is appropriate given no parameters exist, and it does not mislead about inputs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb ('List') and resource ('all item types/categories in the database'), and distinguishes it from siblings by specifying it returns statistics rather than individual item history or PDF imports. It goes beyond the name/title to explain what 'list' entails.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context for when to use this tool ('Useful for getting an overview of all tracked expense categories'), which implicitly differentiates it from siblings focused on history or imports. However, it does not explicitly state when not to use it or name alternatives, keeping it from a perfect score.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
TDQS
Each tool has a clearly distinct purpose: get_item_history retrieves detailed purchase history for a specific item, import_receipt_from_pdf processes new receipts into the database, and list_item_types provides an overview of all tracked categories. There is no overlap in functionality, and an agent could easily select the appropriate tool based on the task.
The tool names follow a consistent verb_noun pattern (get_item_history, import_receipt_from_pdf, list_item_types), making them predictable and readable. The minor deviation is that 'import_receipt_from_pdf' includes a preposition ('from'), but this does not significantly impact consistency or clarity.
With only 3 tools, the server feels slightly thin for an expense tracker domain, as it lacks operations like updating or deleting entries, or querying by other criteria (e.g., date ranges or stores). However, the tools cover core functionalities (import, query history, list categories), so it is borderline but functional.
The tool set covers basic import and query operations but has notable gaps: there are no tools for updating or deleting data, managing stores or receipts beyond import, or advanced filtering (e.g., by date or store). This could lead to agent failures if such operations are needed, though core workflows (adding receipts and viewing history) are supported.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Convert PDF bank statements into structured transactions, accounts, and balances.
Personal finance tracker — log transactions, view summaries, and browse a dashboard
Receipt tracker with no friction: receipts arrive by email and file themselves
Invoice and receipt extractor: reads PDF and image invoices/receipts with AI, pulling date…
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables extraction of structured data from documents like invoices, receipts, and bank statements using local Vision AI (Ollama) or cloud providers (Gemini), with data stored in a local SQLite database.9MIT
- FlicenseAqualityDmaintenanceEnables AI assistants like Claude to manage personal expenses locally using SQLite. Supports adding, categorizing, summarizing expenses, setting budgets, and exporting data without cloud services.8
- FlicenseNot gradedqualityDmaintenanceEnables natural language management of personal expenses, including adding, listing, and summarizing expenses with local SQLite storage.
- FlicenseAqualityDmaintenanceParses Italian INAZ payslip PDFs into a local SQLite database, enabling AI clients to analyze salary history, search items, and get detailed breakdowns while keeping data on your machine.51
Appeared in Searches
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Sharan0402/expense-tracker-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server