Metadata-Version: 2.4
Name: tiller-mcp-server
Version: 0.1.0
Summary: Tiller Money MCP Server
License-File: LICENSE
Requires-Python: >=3.12
Requires-Dist: google-api-python-client>=2.0.0
Requires-Dist: google-auth-httplib2>=0.2.0
Requires-Dist: google-auth-oauthlib>=1.0.0
Requires-Dist: google-auth>=2.0.0
Requires-Dist: mcp>=1.0.0
Requires-Dist: pydantic>=2.0.0
Requires-Dist: python-dotenv>=1.0.0
Description-Content-Type: text/markdown

# 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

1. **Clone this repository**:
   ```bash
   git clone https://github.com/delorenj/tiller-mcp-server.git
   cd tiller-mcp-server
   ```

2. **Set up Python environment**:
   This project uses `mise` for toolchain management (Python, Node.js) and 1Password secret injection, and `uv` for Python virtual environment and dependency management.

   First, install the required toolchains (Python, Node) via `mise`:
   ```bash
   mise install
   ```
   *Note: On directory enter/switch, `mise` will automatically inject secrets from `.env.op` into your `.env` file using the 1Password CLI (`op`).*

   Next, set up the Python virtual environment and install all dependencies:
   ```bash
   # Sync virtual environment and dependencies using uv
   uv sync
   ```

3. **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](https://console.cloud.google.com/)
   - 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.json` in this project

4. **Authenticate with Google Sheets**:
   ```bash
   # Run the authentication setup script
   uv run 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`

5. **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`

   Using `uv` with the project directory is recommended for a clean, platform-independent configuration:

   ```json
   {
     "mcpServers": {
       "Tiller Money": {
         "command": "uv",
         "args": [
           "--directory",
           "/path/to/your/tiller-mcp-server",
           "run",
           "tiller-mcp-server"
         ],
         "env": {
           "TILLER_SHEET_ID": "your_tiller_spreadsheet_id_here"
         }
       }
     }
   }
   ```

   **Important**:
   - Replace `/path/to/your/tiller-mcp-server` with your actual project path
   - Replace `your_tiller_spreadsheet_id_here` with your Tiller spreadsheet ID

6. **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`

7. **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-server/
├── 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
├── PRD.md                     # Product Requirements Document
└── README.md                  # This documentation
```

### Architecture

Three-layer pattern for clean separation of concerns:

1. **Data Models** ([tiller_schema.py](src/tiller_mcp_server/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

2. **API Client** ([sheets_client.py](src/tiller_mcp_server/sheets_client.py))
   - Google Sheets API authentication and connection
   - Automatic token refresh handling
   - Efficient sheet range queries with singleton pattern

3. **MCP Tools** ([server.py](src/tiller_mcp_server/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**: "TILLER_SHEET_ID environment variable not set"
- **Solution**: Add `TILLER_SHEET_ID` to Claude Desktop config under `env` section

**Error**: "Token file not found"
- **Solution**: Run `python auth/auth_setup.py` to create authentication token
- **Solution**: Run `uv run auth/auth_setup.py` to create authentication token

**Error**: "Credentials are invalid and cannot be refreshed"
- **Solution**: Re-run authentication: `python auth/auth_setup.py`
- **Solution**: Re-run authentication: `uv run 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: `uv sync`
- **Solution**: Test server manually: `uv run tiller-mcp-server`

### 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 `uv run 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
```bash
# Test server manually
uv run tiller-mcp-server

# Server logs to stderr (visible in Claude Desktop logs)
```

### Contributing New Tools

1. **Design**: Specify tool requirements in [PRD.md](PRD.md)
2. **Data Model**: Add Pydantic model to [tiller_schema.py](src/tiller_mcp_server/tiller_schema.py)
3. **API Client**: Add sheet query method to [sheets_client.py](src/tiller_mcp_server/sheets_client.py)
4. **MCP Tool**: Add tool definition to [server.py](src/tiller_mcp_server/server.py)
5. **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:
1. Check authentication: `uv run auth/auth_setup.py`
2. Verify configuration: Ensure `TILLER_SHEET_ID` is set in Claude Desktop config
3. Test server manually: `uv run tiller-mcp-server`
4. Review logs: Claude Desktop logs show server stderr output
5. Report issues on GitHub with error details and logs

---

## License

MIT License

---

## Acknowledgments

### Inspiration

Inspired by the [MonarchMoney Python library](https://github.com/hammem/monarchmoney) by [@hammem](https://github.com/hammem) - A fantastic unofficial API for Monarch Money with full MFA support.

Further inspired by [@drbarq](https://github.com/drbarq)'s excellent upgrade: [monarch-mcp-server-god-mode](https://github.com/drbarq/monarch-mcp-server-god-mode)

### Built With

- [Google Sheets API](https://developers.google.com/sheets/api) - Data access
- [FastMCP](https://github.com/jlowin/fastmcp) - MCP server framework
- [Pydantic](https://docs.pydantic.dev/) - Data validation
- [Tiller Money](https://www.tillerhq.com/) - Personal finance tracking platform
