Skip to main content
Glama
eloircorona

hledger-mcp

hledger-mcp

MCP server for hledger — exposes double-entry accounting tools to AI agents via the Model Context Protocol.

Built with fastmcp.

Tools

Tool

Description

get_balance

Account balances, optionally filtered by account and period

get_register

Transaction history, optionally filtered by account, period, and limit

get_budget

Budget report (requires budget directives in the journal)

add_transaction

Append a new transaction to the journal

Related MCP server: bookie

Requirements

  • Python 3.11+

  • hledger installed and on PATH

  • uv (for uvx invocation)

Usage

Run directly with uvx

uvx --from /path/to/hledger-mcp hledger-mcp

Add to Claude Code

{
  "mcpServers": {
    "hledger": {
      "command": "uvx",
      "args": ["--from", "/path/to/hledger-mcp", "hledger-mcp"]
    }
  }
}

Journal path

By default, the server reads and writes to ~/hledger.journal. Override with the HLEDGER_JOURNAL environment variable:

HLEDGER_JOURNAL=/path/to/my.journal uvx --from /path/to/hledger-mcp hledger-mcp

Or in mcp.json:

{
  "mcpServers": {
    "hledger": {
      "command": "uvx",
      "args": ["--from", "/path/to/hledger-mcp", "hledger-mcp"],
      "env": {
        "HLEDGER_JOURNAL": "/home/user/finance/ledger.journal"
      }
    }
  }
}

Using with orbit

orbit is an AI session launcher that manages context — MCPs, instructions, and permissions — across a layered scope hierarchy: workspace → tenant → project → repository. hledger ships as a first-class orbit plugin.

Setup (3 commands)

# Register the plugin with orbit
curl -fsSL https://raw.githubusercontent.com/eloircorona/hledger-mcp/main/hledger.toml \
  -o ~/.orbit/plugins/hledger.toml

# Install hledger if not already present
orbit plugins install hledger

# Configure the journal path for this instance
orbit plugins auth hledger

# Enable the MCP for the current scope (tenant, project, or global)
orbit plugins enable hledger

orbit plugins auth prompts for the instance name and journal path, then wires everything up. No config files to edit manually.

If you already cloned the repo, the one-liner becomes:

cp hledger.toml ~/.orbit/plugins/

Launch

orbit launch <scope>

orbit starts the session with hledger connected alongside any other MCPs in scope. Switch to a different tenant and hledger disappears automatically.

Multiple journals

Need separate instances for personal and business finances? Run orbit plugins auth hledger again with a different instance name — orbit tracks them independently:

orbit plugins auth hledger   # instance: personal → ~/finance/personal.journal
orbit plugins auth hledger   # instance: business → ~/finance/business.journal

Why this matters

A typical personal finance setup in orbit pairs hledger-mcp with:

MCP

Purpose

hledger

Typed access to the journal — query balances, add transactions

filesystem

Browse receipts, bank exports, tax documents

sqlite

Structured queries over imported CSV data

Because orbit merges MCPs layer by layer, you can scope hledger to a specific tenant so it only loads when you're working on finances — never leaking into other sessions.

orbit handles context scoping, MCP lifecycle, engine selection (Claude, Gemini, local), and session instructions — so the AI always has the right tools for the current domain, with zero manual configuration per session.

Tool reference

get_balance

Returns the balance report (hledger bal).

get_balance(account="gastos", period="this month")
get_balance(account="activos:banco")
get_balance()

Param

Type

Description

account

str (optional)

Account name pattern to filter

period

str (optional)

Period expression: "this month", "2026-08", "Q1", "last year", etc.

get_register

Returns the register report (hledger reg).

get_register(account="gastos:alimentacion", period="this month")
get_register(limit=20)

Param

Type

Description

account

str (optional)

Account name pattern to filter

period

str (optional)

Period expression

limit

int (optional)

Max number of entries to return

get_budget

Returns the budget report (hledger budget). Requires ~ monthly or similar budget directives in your journal.

get_budget(period="this month")

Param

Type

Description

period

str (optional)

Period expression

add_transaction

Appends a transaction to the journal file.

add_transaction(
    date="2026-08-08",
    description="Supermercado Walmart",
    postings=[
        {"account": "gastos:alimentacion", "amount": "850 MXN"},
        {"account": "activos:banco:bbva"},   # no amount — hledger auto-balances
    ]
)

Param

Type

Description

date

str

ISO date: "2026-08-08"

description

str

Payee or description

postings

list[dict]

List of {"account": str, "amount": str}. Last entry may omit amount.

The resulting journal entry:

2026-08-08 Supermercado Walmart
    gastos:alimentacion                       850 MXN
    activos:banco:bbva

Account conventions (hledger standard)

activos:      assets  (bank, cash, investments)
pasivos:      liabilities  (credit cards, loans)
ingresos:     income  (salary, freelance)
gastos:       expenses  (food, transport, rent)
patrimonio:   equity  (opening balances)

Development

git clone git@github.com:eloircorona/hledger-mcp.git
cd hledger-mcp
uv sync
uv run hledger-mcp

License

MIT

Available Tools

4 tools
add_transactionAdd TransactionC

Add a new transaction to the journal.

ParametersJSON Schema
NameRequiredDescriptionDefault
dateYesISO date string, e.g. '2026-08-08'
postingsYesList of postings. Each is {"account": "gastos:alimentacion", "amount": "850 MXN"}. The last posting may omit 'amount' — hledger will auto-balance it.
descriptionYesPayee/description, e.g. 'Supermercado Walmart'

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

C2.9/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden of behavioral disclosure. It only says that a transaction is added, but it does not mention persistence, side effects, idempotency, validation behavior, or the auto-balancing behavior partially described in the schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single efficient sentence with no filler. It loses a point because 'Add a new transaction' largely restates the tool name, though 'to the journal' adds useful context.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple create tool with a complete input schema and an output schema, the description is minimally viable. However, it lacks usage guidance and behavioral context, so an agent still has to infer when to use it and what consequences the write operation has.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description itself adds no parameter-level meaning beyond the general 'journal' context, but the schema already documents date, description, and postings with examples.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action ('Add a new transaction') and resource ('to the journal'), making the tool's core function clear. It is not as explicit as naming the sibling alternative, but it is obviously distinct from the read-only get_* siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives no guidance on when to use this tool versus alternatives. It does not mention that sibling tools are for reading balances, registers, or budgets, nor does it state when add_transaction would or would not be appropriate.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_balanceGet BalanceA

Show account balances. Optionally filter by account name pattern and/or period (e.g. 'this month', '2026-08', 'Q1').

ParametersJSON Schema
NameRequiredDescriptionDefault
periodNo
accountNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the disclosure burden. It conveys that this is a read/show operation and adds filter behavior (name pattern, period examples), but it does not disclose details like default output when filters are omitted, whether all accounts are included, or how period boundaries are handled. Still, the read-only nature is reasonably clear.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded: the primary purpose is stated first, followed by concise filter guidance. Both sentences add value, and there is no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

This is a simple read-only query tool with an output schema, so the description does not need to explain return values. It covers the purpose and both optional parameters adequately. Minor gaps remain around default behavior and explicit sibling differentiation, but the tool can be used correctly from the description alone.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It adds meaningful semantics: 'account' is described as a name pattern, and 'period' is illustrated with concrete examples ('this month', '2026-08', 'Q1'). This goes well beyond the bare parameter names, though exact matching rules remain undefined.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's function with a specific verb and resource: 'Show account balances'. It does not explicitly differentiate from siblings like get_register or get_budget, but the resource 'balances' is intuitively distinct from register/budget tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use the tool—when you need account balances—and explains optional filtering by account name pattern or period. However, it does not explicitly mention when to prefer a sibling tool or state exclusions, leaving routing between alternatives to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_budgetGet BudgetA

Show budget report. Requires budget directives in the journal. Optionally filter by period.

ParametersJSON Schema
NameRequiredDescriptionDefault
periodNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the behavioral disclosure burden. The word 'Show' implies a read-only operation, and the prerequisite about budget directives adds important context about a dependency. It does not mention error behavior, output format details, or side effects, but for a simple read-only report this is a reasonable level of transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two short sentences with no wasted words. The key action is front-loaded, and the prerequisite plus optional filter follow naturally, making it easy to parse and act on.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

This is a simple tool with one optional parameter and an output schema, so the description covers the essential usage context: what is shown, a prerequisite, and an optional filter. Minor gaps like period format are not critical for this level of complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema only defines 'period' without any parameter description, so the description's phrase 'Optionally filter by period' is valuable: it clarifies that the parameter acts as an optional filter. It does not specify the expected string format or allowed values, leaving some ambiguity for the agent.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states the tool's function clearly: 'Show budget report' specifies a distinct action and resource. It is implicitly distinguishable from siblings like get_balance and get_register because it focuses on a budget-specific report, though it does not explicitly name alternatives.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides a useful prerequisite: 'Requires budget directives in the journal,' which helps the agent know when the tool is applicable. However, it does not explicitly explain when to prefer this tool over get_balance, get_register, or add_transaction, nor does it state exclusion conditions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_registerGet RegisterA

Show transaction register (history). Optionally filter by account, period, and max number of entries.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
periodNo
accountNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden. 'Show transaction register (history)' implies a read-only query, but it does not explicitly state read-only behavior, ordering, defaults, pagination, or any other behavioral caveats.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, front-loaded sentence with no filler. It states the purpose and all optional filters efficiently.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description is adequate for a simple filtered history tool, and an output schema exists, but it lacks usage guidance, sibling differentiation, and parameter format details. With no annotations and zero schema description coverage, some context is still missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It maps all three parameters to concepts: account, period, and max number of entries. However, 'period' is vague and no format or value semantics are provided beyond the parameter names.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb and resource: 'Show transaction register (history)'. This clearly conveys the tool's function and distinguishes it from siblings like get_balance, get_budget, and add_transaction.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description does not explain when to use this tool versus alternatives. It mentions optional filters but gives no guidance on choosing get_register over get_balance or get_budget, leaving usage context implied at best.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 4 tool updatesv0.1.0
    • First observedadd_transaction
    • First observedget_balance
    • First observedget_budget
    • First observedget_register

TDQS

A3.6/5.0

Scored across 4 tools

Disambiguation5/5

Each tool targets a distinct hledger concern: balances, transaction history, budget reports, and adding transactions. There is no meaningful overlap between them.

Naming Consistency5/5

All tools follow the verb_noun pattern with 'get_' for read operations and 'add_' for the write operation. Naming is perfectly predictable and consistent.

Tool Count5/5

Four tools is a compact, focused set for a hledger interface covering the most common actions. No tool is redundant, and the scope feels well-suited to an MCP server.

Completeness3/5

The core workflows of viewing balances, transactions, budgets, and adding entries are covered. However, there are notable gaps such as no way to list accounts, edit/delete transactions, or retrieve full transaction details, which are common hledger operations.

Maintenance

ActivitySlowing
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    C
    quality
    D
    maintenance
    A Model Context Protocol server that allows AI assistants to query and analyze financial data through Ledger CLI, enabling tasks like financial reporting, budget analysis, and accounting.
    9
    51
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    A Model Context Protocol (MCP) server that keeps the books for your personal and business finances using double-entry accounting — driven entirely from an LLM.
    51 npm
    MIT
  • F
    license
    Not graded
    quality
    B
    maintenance
    A read-only MCP server that gives AI agents structured access to a Beancount personal finance ledger.
    1
    -
  • A
    license
    Not graded
    quality
    A
    maintenance
    Double-entry accounting ledger MCP server for autonomous agents that enables creating accounts, posting journal entries, and generating financial reports.
    MIT