Skip to content

saubury/MoneydanceMCP

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MoneydanceMCP

MCP server integration for Moneydance, the personal finance manager.

Enables AI assistants to query your transactions, spending by category, monthly income/expense summaries, and account metadata ... all from your local Moneydance database.

Ollama makes running open-weight models locally straightforward, but MCP support lives in the host application, not the model itself. To connect a local Ollama model to MCP servers you need a "host" that implements the MCP client protocol and bridges it to the Ollama API. Claude Code fills that role: launched against a local Ollama model with tool-calling support, it acts as the MCP host, meaning financial queries, the financial data itself all stay on locally.

dataflow

Examples

ollama launch claude --model qwen3.5

Claude code is now running locally with its own model serverd by ollama. The .claude/settings.json. We'll use mcp-server-motherduck as the MCP server which provides Claude with direct SQL query access to the local DuckDB database file at the Moneydance export path. It's registered under the name duckdb and exposes tools like execute_query and list_tables so Claude can read and analyse the Moneydance financial data.

Task: Find the biggest spend categories so far in 2026.                                                                     

claude-code

Setup

As a one-off execise - need to export Mondeydance

Python export setup

The ingester

The ingest service is a small Python script that receives transaction data piped directly from Moneydance's internal Jython runtime via stdin, requiring no temporary files on disk. It transforms and loads the raw transaction records into a local DuckDB database. This is used later by the MCP server as a queryable snapshot of your financial data.

Install dependencies:

uv sync  

The exporter

The export step runs as a Python script inside Moneydance's built-in Jython runtime, iterating over every transaction in your account book via the official Java API and piping directly to the ingest service via stdin.

In Moneydance, open the built-in scripting console via "Window -> Show developer console", paste the export script into the editor, and click Run. Be sure to update the real location of MoneydanceMCP/.venv/bin/python

dev-console

import json, subprocess

def get_transactions(book):
    txn_set = book.getTransactionSet()
    transactions = []
    txn_iter = txn_set.iterator()

    while txn_iter.hasNext():
        txn = txn_iter.next()
        if txn.getClass().getSimpleName() != "ParentTxn":
            continue

        account = txn.getAccount()
        currency = account.getCurrencyType()
        amount = currency.getDoubleValue(txn.getValue())

        category = ""
        if txn.getSplitCount() > 0:
            split = txn.getSplit(0)
            cat_acct = split.getAccount()
            if cat_acct:
                category = cat_acct.getFullAccountName()

        d = str(txn.getDateInt())
        date_str = "{}-{}-{}".format(d[:4], d[4:6], d[6:8])

        transactions.append({
            "id":          txn.getUUID(),
            "date":        date_str,
            "description": txn.getDescription(),
            "amount":      amount,
            "account":     account.getFullAccountName(),
            "currency":    currency.getIDString(),
            "category":    category,
            "memo":        txn.getMemo(),
            "cleared":     str(txn.getClearedStatus()),
            "check_num":   txn.getCheckNumber(),
        })

    return transactions

book = moneydance.getCurrentAccountBook()
txns = get_transactions(book)
payload = json.dumps(txns).encode("utf-8")

proc = subprocess.Popen(
    ["/Users/saubury/git/saubury/MoneydanceMCP/.venv/bin/python",
     "/Users/saubury/git/saubury/MoneydanceMCP/Moneydance-ingest.py"],
    stdin=subprocess.PIPE,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE
)
stdout, stderr = proc.communicate(input=payload)

print(stdout.decode("utf-8"))
if stderr:
    print("ERRORS:", stderr.decode("utf-8"))

All going well, you should get a message like this

Beginning snippet at Sun May 10 10:05:00 AEST 2026

Loaded 30506 transactions into Moneydance-export.db

Finished running snippet normally at Sun May 10 10:05:28 AEST 2026

Moneydance runs in a macOS sandbox, so its Path.home() resolves to the container home, not your actual home directory. You'll need to find the location of your export, mine ended up in /Users/saubury/Library/Containers/com.infinitekind.MoneydanceOSX/Data/Moneydance-export.db

Claude Code MCP configuration

This full path of the Moneydance-export.db DuckDB databes needs to be added in .claude/settings.json

This is the Claude Code project settings file configues the MCP servers that Claude Code can use during sessions in this project. Specifically, it sets up a DuckDB MCP server pointing at the newly created Moneydance DuckDB database

About

MCP server integration for Moneydance, the personal finance manager. Enables AI assistants to query personal transactions, spending by category, income/expense etc

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages