Install
$ agentstack add mcp-jackstein21-tiller-mcp-server ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
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:
``bash git clone https://github.com/jackstein21/tiller-mcp-server.git cd tiller_mcp ``
- Set up Python environment:
```bash # Using conda (recommended) conda create -n tillermcp python=3.12 conda activate tillermcp
# 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:
``bash # Run the authentication setup script python auth/auth_setup.py ``
Follow 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.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
``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
- 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)group (optional) - Filter by group (partial match)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 ([tillerschema.py](src/tillermcpserver/tillerschema.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 ([sheetsclient.py](src/tillermcpserver/sheetsclient.py))
- Google Sheets API authentication and connection
- Automatic token refresh handling
- Efficient sheet range queries with singleton pattern
- MCP Tools ([server.py](src/tillermcpserver/server.py))
- FastMCP framework with
@mcp.tool()decorators - Read-only operations with comprehensive validation
- JSON response formatting with helpful error messages
Troubleshooting
Authentication Issues
Error: "TILLERSHEETID 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](PRD.md)
- Data Model: Add Pydantic model to [tillerschema.py](src/tillermcpserver/tillerschema.py)
- API Client: Add sheet query method to [sheetsclient.py](src/tillermcpserver/sheetsclient.py)
- MCP Tool: Add tool definition to [server.py](src/tillermcpserver/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
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: jackstein21
- Source: jackstein21/tiller-mcp-server
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.