Tiller Money MCP Server
Provides read-only access to Tiller Money financial data in Google Sheets, enabling natural language queries for accounts, transactions, categories, and budgets through Claude Desktop.
README
Tiller Money MCP Server
A Model Context Protocol (MCP) server for Tiller Money's Google Sheets-based personal finance tracking. Enables natural language queries against your financial data through Claude Desktop with direct read-only access via the Google Sheets API and OAuth2 authentication.
Quick Start
1. Installation
-
Clone this repository:
git clone https://github.com/jackstein21/tiller-mcp-server.git cd tiller_mcp -
Set up Python environment:
# Using conda (recommended) conda create -n tiller_mcp python=3.12 conda activate tiller_mcp # Install dependencies pip install -r requirements.txt -
Set up Google Cloud Project:
Before authenticating, you need to create a Google Cloud Project and enable the Google Sheets API:
- Go to Google Cloud Console
- Create a new project (or select an existing one)
- Enable the Google Sheets API for your project
- Create OAuth 2.0 credentials (Desktop app type)
- Download the credentials JSON file
- Save it as
auth/credentials.jsonin this project
-
Authenticate with Google Sheets:
# Run the authentication setup script python auth/auth_setup.pyFollow the prompts:
- Your browser will open for Google OAuth consent
- Grant access to Google Sheets
- Authentication token will be saved to
auth/token.json
-
Configure Claude Desktop: Add this to your Claude Desktop configuration file:
macOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%APPDATA%\Claude\claude_desktop_config.json{ "mcpServers": { "Tiller Money": { "command": "/opt/anaconda3/envs/tiller_mcp/bin/python", "args": [ "/path/to/your/tiller_mcp/src/tiller_mcp_server/server.py" ], "env": { "TILLER_SHEET_ID": "your_tiller_spreadsheet_id_here" } } } }Important:
- Replace
/path/to/your/tiller_mcpwith your actual project path - Replace
your_tiller_spreadsheet_id_herewith your Tiller spreadsheet ID - If not using conda, update the
commandpath to your Python interpreter
- Replace
-
Get your Tiller Spreadsheet ID:
- Open your Tiller spreadsheet in Google Sheets
- Copy the ID from the URL:
https://docs.google.com/spreadsheets/d/{SPREADSHEET_ID}/edit
-
Restart Claude Desktop
Features
Account Management
- View all active financial accounts
- Filter by account type (Credit Cards, Retirement, Savings, etc.)
Transaction Queries
- Search and filter transactions with powerful query options
- Date range filtering (start/end date)
- Account filtering (partial matching by account number)
- Category filtering (partial matching, case-insensitive)
- Amount filtering (min/max amounts for expenses or income)
- Description search across transaction text
- Pagination for large result sets
- Chronological sorting (most recent first)
- Detailed transaction lookup by ID
Category Management
- View all category definitions from Tiller
- Filter by category type (Expense, Income, Transfer)
- Filter by category group (Living, Fun, etc.)
- Optional monthly budget allocation data per category
Budget Analysis
- Access monthly budget allocations from Categories sheet
- Compare budgeted vs. actual spending
- Analyze any month or date range
- Natural language budget queries
Available Tools
Accounts
| Tool | Description | Parameters |
|---|---|---|
get_accounts |
Get all active financial accounts | account_type (optional) - Filter by account type/group |
Transactions
| Tool | Description | Parameters |
|---|---|---|
get_transactions |
Query transactions with filtering & pagination | start_date, end_date, account, category, min_amount, max_amount, description, limit, offset (all optional) |
get_transaction_details |
Get complete details for a single transaction | transaction_id (required) - 24-character hex ID |
Categories & Budgets
| Tool | Description | Parameters |
|---|---|---|
get_categories |
Get all category definitions with optional monthly budgets | category_type (optional) - Filter by type (Expense/Income/Transfer)<br>group (optional) - Filter by group (partial match)<br>include_monthly_budgets (optional, default: false) - Include monthly budget data |
Usage Examples
Account Queries
Ask Claude natural language questions like:
- "Show me all my financial accounts"
- "Show me my credit card accounts"
- "List all my retirement accounts"
Transaction Queries
Query transactions using natural language:
- "Show me my 20 most recent transactions"
- "Show me all transactions in December 2025"
- "Get transactions between 12/01/2025 and 12/20/2025"
- "Show me transactions for account ending in 1234"
- "Show me all grocery transactions"
- "Find all dining expenses in December 2025"
- "Show me all expenses over $100"
- "List all income transactions"
- "Find transactions between $20 and $50"
- "Show me all Starbucks transactions"
- "Find all coffee shop purchases"
Combined Filters
Combine multiple criteria in one query:
- "Show me December 2025 transactions for account 1234"
- "Find dining expenses between $20 and $50 in December 2025"
- "Show all grocery transactions over $100"
Category Queries
Explore your category structure:
- "Show me all my categories"
- "List all expense categories"
- "What categories are in the Living group?"
- "Show expense categories in the Fun group"
Budget Analysis
Analyze budgets vs. actual spending:
- "Show me my budget for December 2025"
- "Get all expense categories with their monthly budgets"
- "How much did I spend on groceries in January vs. my budget?"
- "Which categories am I over budget in for this month?"
- "Show me my total budgeted vs. actual spending for December"
Data Structures
Account Object
Each account object contains:
| Field | Type | Description | Example |
|---|---|---|---|
display_name |
string | Account name with masked number | "CREDIT CARD (-XXXX)" |
account_type |
string | Account type/group from Tiller | "Credit Cards", "Retirement", "Savings" |
account_number |
string | Last 4 digits | "-XXXX" |
is_hidden |
boolean | Always false (hidden accounts excluded) | false |
Transaction Object
Each transaction object contains:
| Field | Type | Description | Example |
|---|---|---|---|
date |
string | Transaction date | "12/19/2025" |
description |
string | Merchant/description | "Coffee Shop Downtown" |
category |
string | Transaction category | "Restaurants" |
amount |
float | Amount (negative for expenses) | -15.75 |
amount_str |
string | Formatted amount string | "-$15.75" |
account |
string | Account display name | "CREDIT CARD (-XXXX)" |
account_number |
string | Last 4 digits of account | "XXXX" |
institution |
string | Financial institution | "Chase" |
month |
string | Month grouping | "12/01/25" |
week |
string | Week grouping | "12/15/25" |
transaction_id |
string | Unique 24-char hex ID | "123abc456def789012345678" |
check_number |
string | Check number if applicable | "" |
full_description |
string | Full uppercase description | "COFFEE SHOP DOWNTOWN" |
Category Object
Each category object contains:
| Field | Type | Description | Example |
|---|---|---|---|
category |
string | Category name (unique identifier) | "Groceries", "Dining Out", "Salary" |
group |
string | Category group/classification | "Living", "Fun", "Primary Income" |
type |
string | Category type | "Expense", "Income", "Transfer" |
monthly_budgets |
object (optional) | Monthly budget amounts | {"Jan": {"amount": 600.0, "amount_str": "$600.00"}, ...} |
Monthly Budgets Structure (when include_monthly_budgets=True):
- Contains 12 months: Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec
- Each month has:
amount(float): Parsed budget amount (e.g., 600.0)amount_str(string): Original currency string (e.g., "$600.00")
Data Privacy & Security
Read-Only Access
- v1.0 is completely read-only - No write operations to your spreadsheet
- Safe to use without risk of data corruption
- Future write operations will require explicit user consent
Local Execution
- MCP server runs locally on your machine via stdio
- No cloud deployment or data transmission to third parties
- Data never leaves your local environment
Authentication Security
- OAuth2 credentials stored in
auth/credentials.json(gitignored) - Access token stored in
auth/token.json(gitignored) - Tokens automatically refresh when expired
- Full Google OAuth security model
Hidden Accounts
- Hidden accounts are always excluded from results
- No option to include hidden accounts (by design)
- Ensures sensitive accounts remain private
Tiller Sheet Integration
The MCP server reads from standard Tiller Money spreadsheet tabs:
Accounts Sheet
Uses columns A-D for efficiency:
- Column A: Display name with masked number
- Column B: Class Override (not currently used)
- Column C: Group (account type)
- Column D: Hide flag
Transactions Sheet
Uses columns A-P for complete transaction data including date, description, category, amount, account, institution, and metadata.
Categories Sheet
Uses columns A-C for category definitions, with optional columns D-P for monthly budget allocations (12 months).
Technical Details
Project Structure
tiller_mcp/
├── auth/
│ ├── credentials.json # OAuth credentials (gitignored)
│ ├── token.json # OAuth token (gitignored)
│ └── auth_setup.py # Authentication setup script
├── src/tiller_mcp_server/
│ ├── __init__.py # Package initialization
│ ├── server.py # Main MCP server (FastMCP)
│ ├── sheets_client.py # Google Sheets API wrapper
│ └── tiller_schema.py # Pydantic models
├── config.json # Example Claude Desktop config
├── requirements.txt # Python dependencies
├── PRD.md # Product Requirements Document
└── README.md # This documentation
Architecture
Three-layer pattern for clean separation of concerns:
-
Data Models (tiller_schema.py)
- Pydantic models for type-safe data handling
- Account, Transaction, and Category models
- Currency parsing, date handling, and account number extraction
- Optional monthly budget data support
-
API Client (sheets_client.py)
- Google Sheets API authentication and connection
- Automatic token refresh handling
- Efficient sheet range queries with singleton pattern
-
MCP Tools (server.py)
- FastMCP framework with
@mcp.tool()decorators - Read-only operations with comprehensive validation
- JSON response formatting with helpful error messages
- FastMCP framework with
Troubleshooting
Authentication Issues
Error: "TILLER_SHEET_ID environment variable not set"
- Solution: Add
TILLER_SHEET_IDto Claude Desktop config underenvsection
Error: "Token file not found"
- Solution: Run
python auth/auth_setup.pyto create authentication token
Error: "Credentials are invalid and cannot be refreshed"
- Solution: Re-run authentication:
python auth/auth_setup.py
Server Connection Issues
Error: "Server transport closed unexpectedly" in Claude Desktop
- Solution: Check that the Python path in config is correct
- Solution: Verify all dependencies are installed:
pip install -r requirements.txt - Solution: Test server manually:
python src/tiller_mcp_server/server.py
Data Issues
Error: "Failed to parse account row"
- Solution: Check that your Tiller Accounts sheet has the expected column structure
- Solution: Verify columns A-D contain: Display Name, Class Override, Group, Hide
Common Error Messages
| Error | Solution |
|---|---|
| "No valid session found" | Run python auth/auth_setup.py |
| "Spreadsheet not found" | Verify TILLER_SHEET_ID in config |
| "Permission denied" | Re-run auth setup to grant Sheets access |
| "Invalid credentials" | Check auth/credentials.json exists |
Development
Testing
# Test server manually
python src/tiller_mcp_server/server.py
# Server logs to stderr (visible in Claude Desktop logs)
Contributing New Tools
- Design: Specify tool requirements in PRD.md
- Data Model: Add Pydantic model to tiller_schema.py
- API Client: Add sheet query method to sheets_client.py
- MCP Tool: Add tool definition to server.py
- Test: Validate in Claude Desktop
Google Sheets API Quotas
Free Tier:
- 300 requests per minute (project)
- 60 requests per minute (user)
- No billing required for personal use
Expected Usage:
- Typical query: 1-3 API calls
- Daily usage: < 100 API calls
- Well within free tier limits
Design Principles
- Read-only: No write operations to prevent data corruption
- Local execution: Runs locally via stdio, no cloud deployment
- No caching: Fresh data on every query (within generous API quotas)
- Privacy-first: Hidden accounts always excluded
- Iterative development: One tool at a time, thoroughly tested
Roadmap
Completed Features
- Google Sheets API authentication and integration
- Tiller sheet structure discovery and documentation
- Account management tools
- Transaction query tools with comprehensive filtering
- Category management with budget data access
- Budget vs. actual analysis capabilities
Future Enhancements
- Balance history queries and trend analysis
- Category summary and aggregation tools
- Advanced analytics (spending patterns, trends, forecasting)
- AutoCat rule management (read-only)
- Export and reporting capabilities
Support
For issues, follow these troubleshooting steps:
- Check authentication:
python auth/auth_setup.py - Verify configuration: Ensure
TILLER_SHEET_IDis set in Claude Desktop config - Test server manually:
python src/tiller_mcp_server/server.py - Review logs: Claude Desktop logs show server stderr output
- Report issues on GitHub with error details and logs
License
MIT License
Acknowledgments
Inspiration
Inspired by the MonarchMoney Python library by @hammem - A fantastic unofficial API for Monarch Money with full MFA support.
Further inspired by @drbarq's excellent upgrade: monarch-mcp-server-god-mode
Built With
- Google Sheets API - Data access
- FastMCP - MCP server framework
- Pydantic - Data validation
- Tiller Money - Personal finance tracking platform
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
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.
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.