Skip to main content
v0.2.0 Active project

The definitive MCP server for Lunch Money

Let any MCP-compatible AI assistant manage your finances through Lunch Money's full API. Local or remote, secure by default.

0 Tools
0 OAuth Providers
0 Deploy Targets
0 Tests
Why we built this

Checking your finances shouldn't require opening an app.

"What did I spend on food last month?" One question. Your AI should just answer it.

Lunch Money is the best personal finance tool for people who care about their data. But switching contexts — closing your editor, opening a browser, clicking through dashboards — breaks the flow that makes deep work possible.

lunchmoney-mcp puts your complete financial picture inside any MCP-compatible AI assistant. Ask natural questions. Get real answers. The AI handles the API calls, the filtering, the math. You stay in flow.

Everything the API offers, nothing you don't need

Built for real-world use. Secure by design, tested exhaustively, deployable anywhere.

Dual Transport

Run locally over stdio for Claude Desktop and similar clients, or serve over HTTP/SSE as a remote MCP endpoint for multi-user and cloud deployments.

stdio + HTTP/SSE

4 OAuth Providers

Authenticate the remote server with Google, GitHub, CyberArk Identity, or any custom OIDC-compliant provider. Zero custom auth code needed.

Google · GitHub · CyberArk · Custom OIDC

Two-Tier Security

API tokens live in the OS keychain (macOS, GNOME, Windows). Session data is encrypted with AES-256-GCM at rest, with the key stored in that same keychain.

Keychain + AES-256-GCM

5 Deployment Targets

Ship it your way: Docker container, systemd service, Railway one-click, Render.com, or Fly.io. Every path is documented with working configs.

Docker · systemd · Railway · Render · Fly.io

278 Tests, >90% Coverage

Table-driven tests using Vitest. Every tool, every error path, every edge case is exercised before it ships.

>90% line coverage supply chain hardened

Up and running in under a minute

No config files. No environment variables to juggle. The token goes straight to your OS keychain.

Install & run setup

Install globally or run with npx. The setup wizard validates your token and stores it in the OS keychain.

bash
# Install globally (optional)
$ npm install -g @infamousjoeg/lunchmoney-mcp

# Or run directly with npx
$ npx @infamousjoeg/lunchmoney-mcp setup

Add to your MCP client

Configure Claude Desktop, Cursor, or any MCP client with this config.

json — claude_desktop_config.json
{
  "mcpServers": {
    "lunchmoney": {
      "command": "npx",
      "args": ["@infamousjoeg/lunchmoney-mcp"]
    }
  }
}

Or deploy remotely

Run over HTTP with OAuth for multi-device access via Claude.ai.

bash — remote / HTTP mode
# Start the HTTP server (default port 8080)
$ npx @infamousjoeg/lunchmoney-mcp --http

# With a specific port and OAuth provider
$ export AUTH_PROVIDER=github
$ npx @infamousjoeg/lunchmoney-mcp \
    --http \
    --port 8080

What a tool call looks like

Select a scenario to see the exact MCP call your AI makes — and what comes back. Every field, every parameter, validated before it hits the network.

Tool call
getTransactions({
  start_date: "2026-02-01",
  end_date:   "2026-02-28",
  is_income: false
})
Response
[
  {
    "id": 9241, "date": "2026-02-14",
    "payee": "Whole Foods Market",
    "amount": "-84.37",
    "category": "Groceries"
  },
  ... 47 more transactions
]
Tool call
getBudgets({
  start_date: "2026-03-01",
  end_date:   "2026-03-31"
})
Response (filtered)
{
  "category": "Groceries",
  "budget_amount": 400.00,
  "spent_amount":  218.45,
  "remaining":     181.55,
  "pct_used":      "54.6%"
}
Tool call
getRecurringItems({
  start_date: "2026-03-26"
})
Response
[
  {
    "payee": "Netflix",
    "amount": "-22.99",
    "cadence": "monthly",
    "next_billing": "2026-04-01"
  },
  {
    "payee": "GitHub Pro",
    "amount": "-4.00",
    "cadence": "monthly",
    "next_billing": "2026-04-05"
  }
]
Tool call
createTransaction({
  date:     "2026-03-26",
  payee:    "Blue Bottle Coffee",
  amount:   7.50,
  category: "Coffee & Dining",
  notes:    "Cortado"
})
Response
{
  "ids": [9318],
  "status": "ok"
}

37 tools across 9 categories

Every tool maps directly to a Lunch Money API operation. Input validation is enforced with Zod schemas before any network call.

37 tools, zero endpoints skipped
  • configureLunchMoneyToken
    Configure and validate your Lunch Money API token. Stores it securely in the OS keychain on success.
    token: string
  • getUser
    Get account details including email, name, and currency preferences for the authenticated user.
    (no params)
  • getCategories
    List all categories including groups and parent categories.
    (no params)
  • getCategory
    Get a single category by ID.
    id: number
  • createCategory
    Create a new spending or income category with optional group assignment.
    name: string, is_income?: boolean, group_id?: number
  • updateCategory
    Update an existing category's name, description, or group membership.
    id: number, name?: string, description?: string
  • deleteCategory
    Delete a category by ID. Returns an error if the category has associated transactions.
    id: number
  • createCategoryGroup
    Create a new category group with optional initial category IDs.
    name: string, category_ids?: number[]
  • addToGroup
    Add existing categories to a category group by specifying the group ID and category IDs.
    id: number, category_ids: number[]
  • getTags
    List all transaction tags for the authenticated account.
    (no params)
  • createTag
    Create a new tag that can be applied to transactions.
    name: string
  • updateTag
    Update a tag's name by ID.
    id: number, name: string
  • deleteTag
    Delete a tag by ID. The tag is removed from all associated transactions.
    id: number
  • getTransactions
    List transactions with filtering by date range, category, tag, account, and more.
    start_date, end_date, category_id?, tag_id?, is_income?
  • getTransaction
    Get a single transaction by ID with full details.
    id: number
  • createTransaction
    Create a new transaction with date, amount, payee, category, and optional notes.
    date, payee, amount, category_id?, notes?
  • updateTransaction
    Update a transaction's properties including category, tags, notes, and review status.
    id: number, ...patch fields
  • deleteTransaction
    Delete a transaction by ID. Irreversible — use with confirmation from the user.
    id: number
  • bulkUpdateTransactions
    Bulk update multiple transactions in a single API call. Accepts an array of transaction IDs and fields to patch.
    ids: number[], ...patch fields
  • getTransactionGroup
    Retrieve a transaction group and its child transactions.
    id: number
  • createTransactionGroup
    Group multiple transactions under a single parent transaction.
    date, payee, transactions: number[]
  • deleteTransactionGroup
    Delete a transaction group, restoring the individual transactions.
    id: number
  • unsplitTransactions
    Reverse a split, merging child transactions back into the original parent.
    parent_ids: number[], remove_parents?: boolean
  • getRecurringItems
    List all recurring expense and income items with their schedules and amounts.
    start_date?: string
  • createRecurringItem
    Create a new recurring item with payee, amount, cadence, and start date.
    payee, amount, cadence, start_date
  • updateRecurringItem
    Update a recurring item's amount, schedule, or categorization.
    id: number, ...patch fields
  • deleteRecurringItem
    Delete a recurring item by ID.
    id: number
  • getBudgets
    List all budgets with their categories, amounts, and spending to date.
    start_date, end_date
  • createBudget
    Create a new budget for a category with a target amount and time period.
    start_date, category_id, amount
  • updateBudget
    Update a budget's amount or time period.
    start_date, category_id, amount
  • deleteBudget
    Delete a budget by category and date.
    start_date, category_id
  • getAssets
    List all manually-managed assets with their current balances and types.
    (no params)
  • createAsset
    Create a new manually-managed asset such as real estate, crypto, or a savings account.
    type_name, name, balance, currency?
  • updateAsset
    Update an asset's balance, name, or type. Use this to manually sync current values.
    id: number, balance?, name?
  • deleteAsset
    Delete a manually-managed asset by ID.
    id: number
  • getPlaidAccounts
    List all Plaid-connected accounts with their current balances and institution details.
    (no params)
  • fetchPlaidAccounts
    Trigger a Plaid sync to update balances and pull new transactions for connected accounts.
    start_date?: string

Ship it your way

Every deployment target ships with a working configuration. The remote HTTP server supports all 4 OAuth providers out of the box.

Docker
Containerized, any host

A production-ready Dockerfile is included. Mount a secrets volume or pass credentials via environment variables.

bash
$ docker build -t lunchmoney-mcp .
$ docker run -p 3000:3000 \
    -e LUNCH_MONEY_API_TOKEN=your_token \
    lunchmoney-mcp
systemd
Linux service, auto-restart

Run as a persistent system service with automatic restart on failure. Unit file included in the deploy directory.

bash
# Copy unit file
$ cp deploy/lunchmoney-mcp.service \
    /etc/systemd/system/
$ systemctl enable --now lunchmoney-mcp
Railway
One-click, free tier available

Click to deploy directly from GitHub. Railway detects the Dockerfile automatically. Add your token in the environment variables tab.

json — railway.json
{
  "build": { "builder": "DOCKERFILE" },
  "deploy": { "startCommand": "node dist/cli.js" }
}
Render
Managed web service

A render.yaml is included at the repo root. Connect your GitHub repo and Render picks it up automatically.

yaml — render.yaml (excerpt)
services:
  - type: web
    name: lunchmoney-mcp
    env: docker
    plan: free
Fly.io
Global edge deployment

Deploy close to your users using Fly.io's global network. A fly.toml is included and pre-configured.

bash
$ fly launch --no-deploy
$ fly secrets set \
    LUNCH_MONEY_API_TOKEN=your_token
$ fly deploy

Designed for sensitive data

Your API token never touches disk unencrypted. Two-tier architecture separates long-lived credentials from short-lived session tokens.

Tier 1 — OS Keychain

Native Secret Storage

Platform keychain integration via keytar. Credentials are protected by the OS and require user authentication to access.

macOS Keychain GNOME Keyring Windows Credential Manager API tokens OAuth credentials AES-256-GCM key
Tier 2 — Encrypted Disk

AES-256-GCM Session Store

Short-lived session tokens are stored on disk encrypted at rest. The encryption key lives exclusively in Tier 1 — compromised disk = no plaintext.

Session tokens OAuth state AES-256-GCM encrypted Authenticated encryption

Threat model

Threat Mitigation Status
Token exfiltration via disk read Token stored only in OS keychain, never written to disk in plaintext Mitigated
Session token theft AES-256-GCM encryption; key in keychain, not adjacent to ciphertext Mitigated
Unauthorized remote access OAuth PKCE flow required for HTTP transport; unauthenticated requests rejected Mitigated
Token leakage in logs Tokens never included in log output; only masked references used Mitigated
Supply chain compromise Minimal production dependencies; audit trail via npm provenance By design
Privileged keychain access OS-level access controls apply; no elevation of privilege is requested By design

Hardened against dependency attacks

MCP servers sit between AI and your data. A compromised dependency could turn this into a data exfiltration tool. We take this seriously.

Supply chain protections

Protection How it works Status
Pinned versions All versions in package.json are exact — no ^ or ~. Compromised releases won't auto-install. Enforced
Lockfile integrity npm ci reproduces the exact dependency tree from the committed package-lock.json. Enforced
npm provenance --provenance creates a cryptographic attestation linking each published package to its source commit. Enforced
Vulnerability scanning npm audit --audit-level=high runs on every CI build and blocks merges on known high-severity findings. Automated
Signature verification npm audit signatures verifies registry signatures on all installed packages in CI. Automated
Dependabot Weekly monitoring for vulnerable dependencies. Major version bumps require manual review before merge. Automated
Minimal surface Only 5 production dependencies. Dev tooling (vitest, typescript) is excluded from the published package. By design

Production dependencies — 5 total

Package Purpose Trust rationale Status
fastmcp MCP protocol framework 1k+ GitHub stars; listed in Anthropic's official MCP servers registry Ecosystem Std
zod Input validation & schema 25k+ GitHub stars, widely audited Audited
keytar OS keychain access Native OS keychain binding; widely adopted, community-maintained post-Atom archival Native Binding
dotenv ENV file parsing 30M+ weekly downloads, minimal surface area Audited
env-paths Platform data directories Zero dependencies, ~50 lines of code Minimal

Verify it yourself

bash
# Verify registry signatures on all installed packages
$ npm audit signatures

# Check provenance attestation — links package to source commit
$ npm view @infamousjoeg/lunchmoney-mcp --json | jq '.dist.attestations'