Skip to content

echomodel/monarch-access

Repository files navigation

Monarch Access

Lightweight CLI and Python SDK for accessing Monarch Money financial data.

$ monarch accounts
ACCOUNTS (5)
+--------------------------------+--------------------+----------------+
| Account                        | Institution        |        Balance |
+--------------------------------+--------------------+----------------+
| [Checking]                     |                    |      $8,434.56 |
|   Primary Checking             | First National     |      $5,234.56 |
|   Joint Checking               | First National     |      $3,200.00 |
| [Credit Card]                  |                    |     -$3,148.06 |
|   Rewards Card                 | Premium Credit     |     -$2,345.67 |
|   Store Card                   | Target             |       -$802.39 |
| [Savings]                      |                    |     $12,500.00 |
|   Emergency Fund               | First National     |     $12,500.00 |
+--------------------------------+--------------------+----------------+
$ monarch transactions list --start 2025-01-01 --limit 5
TRANSACTIONS (5)
+------------+--------------------------+----------------------+--------------+
| Date       | Merchant                 | Category             |       Amount |
+------------+--------------------------+----------------------+--------------+
| 2025-01-15 | Amazon                   | Shopping             |     -$127.43 |
| 2025-01-14 | Whole Foods              | Groceries            |      -$89.23 |
| 2025-01-13 | Shell                    | Gas                  |      -$45.00 |
| 2025-01-12 | Netflix                  | Entertainment        |      -$15.99 |
| 2025-01-10 | Employer Payroll         | Salary               |    $3,500.00 |
+------------+--------------------------+----------------------+--------------+

Total: $3,222.35

Installation

pipx install git+https://github.com/krisrowe/monarch-access.git

This installs three commands:

  • monarch - The CLI tool for direct command-line use
  • monarch-mcp - The MCP server for AI assistant integration (see MCP Server)
  • monarch-admin - User management for MCP server (local and cloud)

Requirements

  • Python 3.10+
  • A Monarch Money account

Authentication

Monarch doesn't have a public API, so you need to grab your session token from the browser:

  1. Go to https://app.monarch.com/ and log in
  2. Open DevTools (F12) → Console tab
  3. Paste and run:
    JSON.parse(JSON.parse(localStorage.getItem("persist:root")).user).token
  4. Copy the token string
  5. Register it:
    monarch-admin connect local
    monarch-admin users add local --token $MONARCH_SESSION_TOKEN

The token is stored in the local user store and used by both the CLI and MCP server. Tokens typically last several months — rotate yours with:

monarch-admin users update-profile local token $MONARCH_SESSION_TOKEN

CLI Usage

All commands default to text format with ASCII tables. Use --format json or --format csv for machine-readable output.

List Transactions

# Transactions since a date
monarch transactions list --start 2025-12-01

# Date range (both inclusive)
monarch transactions list --start 2025-01-01 --end 2025-12-31

# Filter by account (supports wildcards)
monarch transactions list --start 2025-01-01 --account "Chase*"

# Filter by category (comma-separated)
monarch transactions list --start 2025-01-01 --category "Shopping,Groceries"

# Filter by merchant (supports wildcards)
monarch transactions list --start 2025-01-01 --merchant "*amazon*"

# Output as JSON or CSV
monarch transactions list --start 2025-01-01 --format json
monarch transactions list --start 2025-01-01 --format csv

# Limit results (default 1000)
monarch transactions list --start 2025-01-01 --limit 50

JSON output example:

$ monarch transactions list --start 2025-01-01 --limit 1 --format json
{
  "transactions": [
    {
      "id": "311447260750935400",
      "amount": -127.43,
      "pending": false,
      "date": "2025-01-15",
      "hideFromReports": false,
      "needsReview": false,
      "plaidName": "AMAZON #7491",
      "notes": "",
      "isRecurring": false,
      "account": {
        "id": "acc_004",
        "displayName": "Rewards Card"
      },
      "merchant": {
        "id": "merch_amazon",
        "name": "Amazon"
      },
      "category": {
        "id": "cat_005",
        "name": "Shopping"
      },
      "tags": []
    }
  ],
  "count": 1,
  "total": 147
}

Get a Single Transaction

monarch transactions get TRANSACTION_ID
monarch transactions get TRANSACTION_ID --format json

Update a Transaction

# Update notes
monarch transactions update TRANSACTION_ID --notes "New note"

# Update category (by name)
monarch transactions update TRANSACTION_ID --category "Groceries"

# Update merchant
monarch transactions update TRANSACTION_ID --merchant "Amazon"

# Clear notes (use empty string)
monarch transactions update TRANSACTION_ID --notes ""

List Accounts

monarch accounts
monarch accounts --format json
monarch accounts --format csv

Manage Accounts

# Close an account — keeps its balance history in net worth, zeros it forward
monarch account close <account_id>
monarch account close <account_id> --date 2025-06-30

# Reopen a closed account
monarch account update <account_id> --reopen

# Rename
monarch account update <account_id> --name "New Name"

# Exclude from / include in net worth (retroactive — removes balance from history)
monarch account update <account_id> --exclude-net-worth
monarch account update <account_id> --include-net-worth

# Hide / unhide from the accounts list
monarch account update <account_id> --hide
monarch account update <account_id> --unhide

Close vs. exclude. Closing (account close) keeps the account's historical balance snapshots in net worth and reads $0 from the close date forward — the right way to retire a manual placeholder once a real account links, so net worth neither double-counts nor drops retroactively. Excluding (--exclude-net-worth) removes the balance from net worth across all of history. Closing is reversible with --reopen.

Balance History

# Download an account's daily balance history as CSV (Date,Balance)
monarch balances download <account_id>
monarch balances download <account_id> -o history.csv

# Replace an account's balance history from a CSV file
monarch balances upload <account_id> history.csv

# Back up the current history before replacing, and skip the prompt
monarch balances upload <account_id> history.csv -o backup.csv --yes

Upload replaces the entire balance history (there is no append mode) and sets the account's current balance to the final row. Balance history is independent of transactions — uploading creates no transactions and doesn't affect income/expense reports. Useful for correcting stale balances on accounts that stopped syncing, importing history for manual accounts, or migrating a balance curve between accounts.

Because the replace is destructive, uploads are guarded by a read-before-write interlock:

  • The CLI reads the current history first, shows what will be replaced, optionally writes it to a backup CSV (-o), and prompts for confirmation (--yes to skip).
  • The SDK and MCP tool require an expected_token — a digest number of the current history returned by download_balance_history. The upload re-reads the live history, recomputes the token, and refuses (changing nothing) unless it matches. This guarantees the prior history was read (so the change is reversible) and that nothing changed underneath. On success, the replaced history is returned under previous_snapshots for rollback.

Net Worth Report

monarch net-worth
monarch net-worth --format json
monarch net-worth --format csv

Shows assets and liabilities grouped by category with totals.

Investment Holdings

# All holdings across investment accounts
monarch holdings

# Holdings in a single account
monarch holdings --account <account_id>

# Holdings as of a past date (historical snapshot)
monarch holdings --date 2025-01-15

monarch holdings --format json
monarch holdings --format csv

Returns security-level positions — ticker, share quantity, closing price, current value, cost basis, and per-acquisition tax lots. cost_basis may be null for synced positions where the data provider did not supply basis.

Python SDK Usage

import asyncio
from monarch.client import MonarchClient
from monarch import accounts, categories
from monarch.transactions import list as txn_list, get as txn_get, update as txn_update

async def main():
    client = MonarchClient()

    # Get all accounts
    accts = await accounts.get_accounts(client)

    # Get transactions
    data = await txn_list.get_transactions(
        client,
        limit=100,
        start_date="2025-01-01",
        end_date="2025-12-31",
    )
    txns = data["results"]

    # Get a single transaction
    txn = await txn_get.get_transaction(client, "some-transaction-id")

    # Update a transaction
    updated = await txn_update.update_transaction(
        client,
        transaction_id="some-transaction-id",
        notes="Updated via SDK",
    )

    # Get categories
    cats = await categories.get_categories(client)

asyncio.run(main())

MCP Server for AI Assistants

The monarch-mcp command exposes Monarch data via the Model Context Protocol, enabling AI assistants like Claude and Gemini to access your financial data.

Setup

Register a local MCP user with your Monarch token:

monarch-admin connect local
monarch-admin users add local --token $MONARCH_SESSION_TOKEN

Register with Claude Code

claude mcp add --scope user monarch -- monarch-mcp stdio --user local

Register with Gemini CLI

gemini mcp add monarch -- monarch-mcp stdio --user local

Available Tools

Tool Description
list_accounts Get all accounts with balances
update_account Rename, exclude from net worth, or hide an account
close_account Close an account (keeps balance history in net worth)
get_holdings Get investment holdings (shares, cost basis, tax lots)
download_balance_history Download an account's daily balance snapshots
upload_balance_history Replace an account's balance history
list_categories Get all transaction categories
list_transactions Query transactions with filters
get_transaction Get a single transaction
update_transaction Update category, notes, etc.
mark_transactions_reviewed Bulk mark as reviewed
split_transaction Split across categories
create_transactions Create one or more manual transactions (partial success reported)
delete_transactions Delete one or more transactions (partial success reported)
list_recurring List recurring obligations
update_recurring Update recurring stream settings

For detailed documentation, see MCP-SERVER.md.

Cloud Deployment (Optional)

Deploying monarch-access as an HTTP MCP server means your Monarch session token stays on the server and is never exposed to clients — each client authenticates with a JWT issued by monarch-admin.

Runtime contract

The MCP server reads these environment variables at startup. Any host must provide them:

Variable Required Purpose
SIGNING_KEY yes JWT signing secret. Generate once with python3 -c 'import secrets; print(secrets.token_urlsafe(32))' and supply via your host's secret mechanism.
APP_USERS_PATH yes for durable deploys Directory for per-user profiles. Must be a persistent path — mount a durable volume.
JWT_AUD no Expected JWT audience claim. Leave unset unless you're running multiple apps with a shared signing key.
TOKEN_DURATION_SECONDS no Lifetime of newly issued JWTs. Defaults to ~10 years.

The server serves the MCP endpoint at /, a liveness probe at /health, and admin REST endpoints under /admin/*.

Connect the admin CLI

Once the service is running, point the admin CLI at it with the same SIGNING_KEY the server is using:

monarch-admin connect https://your-service-url --signing-key "$SIGNING_KEY"

connect persists the URL and signing key to ~/.config/monarch/setup.json, so subsequent monarch-admin commands don't need the flags repeated.

Verify the deployment

monarch-admin health

Register a user

monarch-admin users add user@example.com --token "$MONARCH_SESSION_TOKEN"

See Authentication for how to obtain $MONARCH_SESSION_TOKEN. To rotate a user's token in place (keeps their JWT valid and their profile intact):

monarch-admin users update-profile user@example.com token "$NEW_TOKEN"

To revoke a user entirely (invalidates their JWT), use monarch-admin users revoke user@example.com.

Issue a JWT for an MCP client

monarch-admin tokens create user@example.com

Copy the returned token and register the remote server with your MCP client. Both Claude Code and Gemini CLI expand ${VAR} in MCP config, so keep the token in an env var rather than pasting it into config files:

export MONARCH_JWT="<token from tokens create>"

# Claude Code
claude mcp add --scope user --transport http monarch https://your-service-url/ \
  --header "Authorization: Bearer \${MONARCH_JWT}"

# Gemini CLI
gemini mcp add --transport http monarch https://your-service-url/ \
  --header "Authorization: Bearer \${MONARCH_JWT}"

Development

See CONTRIBUTING.md for development setup, testing, and architecture.

For agents

If you are a coding agent operating this repo with plugin support, the author-mcp-app and mcp-app-admin skills provide step-by-step workflows for authoring and operating apps on the mcp-app framework. They are optional — this README and CONTRIBUTING.md are self-sufficient.

License

MIT

About

Lightweight CLI, Python SDK, and MCP server for accessing Monarch Money financial data

Topics

Resources

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors