gnucash-mcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Capabilities
Features and capabilities supported by this server
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
| experimental | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| get_server_configA | Get the server's loaded configuration. Returns loaded modules, tool count, book path, debug mode, and version. Use this to verify which tools are available in this session. |
| switch_bookA | Switch the active GnuCash book (multi-book sessions only). All subsequent tool calls — and the audit/debug logs — operate on the newly-selected book until the next switch. Only present when GNUCASH_BOOK_PATH lists 2+ books. |
| get_account_slotsA | Read slots (custom metadata) from an account. Slots are key-value pairs stored on accounts for metadata like APR, credit limit, reward rates, or any custom data. Args: account: Account ref: full path (e.g., "Liabilities:Credit Cards:Capital One"), %short GUID, or full 32-char GUID. key: Specific slot key to retrieve. If omitted, returns all slots. |
| set_account_slotA | Set a custom metadata slot on an account. Stores a key-value pair on the account. Values are stored as strings. Use for APR, credit limits, reward rates, or any per-account metadata. Args: account: Account ref: full path (e.g., "Liabilities:Credit Cards:Capital One"), %short GUID, or full 32-char GUID. key: Slot key (e.g., "apr", "credit_limit"). value: Slot value (always stored as string). |
| delete_account_slotB | Remove a custom metadata slot from an account. Args: account: Account ref: full path (e.g., "Liabilities:Credit Cards:Capital One"), %short GUID, or full 32-char GUID. key: Slot key to remove. |
| get_audit_logA | Read audit log entries for a date. Returns the human-readable text audit log, led by a
Unlike the row-list tools, the window is anchored to the most
recent entry: Args: log_date: Date to read (YYYY-MM-DD). Defaults to today. limit: Page size (default 50). 0 = count only. offset: Entries to skip back from the most recent (default 0). |
| create_backupA | Create an on-demand backup of the GnuCash book. Uses SQLite's online backup API so the snapshot is safe even
if the book is being read or written concurrently by GnuCash
desktop. Verifies the copy with Manual backups are kept indefinitely — automatic retention
(session / weekly / monthly stages) does not touch them. Use
The response includes a Args:
label: Optional free-text label (sanitized to
|
| list_backupsA | List all available backups, newest first. Leads with a Args: limit: Page size (default 50, max 250). 0 = count only. offset: 0-indexed first row to return (default 0). |
| prune_backupsA | Remove older backups, keeping the most recent N per stage. Default is When Args:
keep_last_n: Number of backups to retain per affected
stage. Must be >= 0.
stage: If set, only prune within this stage. One of
|
| list_budgetsA | List all budgets in the book. Leads with a Args: verbose: If true, return the full JSON envelope. limit: Page size (default 50, max 250). 0 = count only. offset: 0-indexed first row to return (default 0). |
| get_budgetA | Get full details of a budget including all budget amounts. Returns a compact text table by default — collapses uniform
periods (e.g., Args: name: Budget name. verbose: If true, return the full structured dict. |
| create_budgetA | Create a new budget. Args:
name: Budget name (e.g., "2026 Budget").
year: Budget year. Defaults to current year. Ignored when
|
| set_budget_amountA | Set a budget target for an account. Args: budget_name: Name of the budget. account: Account ref: full path (e.g., "Expenses:Groceries"), %short GUID, or full 32-char GUID. amount: Monthly budget amount as string (e.g., "500.00"). period: Which period(s) to set: - None or "all": Set same amount for all periods (default) - Integer 0-11: Set specific period (0 = January for yearly budget) - "q1", "q2", "q3", "q4": Set all periods in quarter |
| get_budget_reportA | Compare actual spending against budget. Returns a compact text table by default with ⚠ markers on categories exceeding budget. Use verbose=true for the full structured dict. Args: budget_name: Name of the budget. period: Which period to report: - None: Current period based on today's date (default) - Integer 0-11: Specific period - "ytd": Year to date (all periods up to current) - "all": All periods account: Optional filter to specific account or parent account. include_children: If True and account specified, include child accounts. verbose: If true, return the structured dict. |
| delete_budgetC | Delete a budget. Args: name: Budget name. |
| create_customerA | Create a new customer. Args: name: Customer name (e.g., "Acme Corp"). currency: ISO currency code (e.g., "USD", "EUR"). Defaults to book's default currency. notes: Optional notes (max 4096 characters). address: Optional address with keys: name, addr1, addr2, addr3, addr4, phone, fax, email. Each sub-field capped at 1024 characters. |
| list_customersA | List all customers. Leads with a Args: active_only: If True, only show active customers. Default True. verbose: If true, return full JSON details for each customer. limit: Page size (default 50, max 250). 0 = count only. offset: 0-indexed first row to return (default 0). |
| get_customerA | Get details for a specific customer by ID. Args: id: Customer ID (e.g., "000001"). This is the human-readable ID shown in GnuCash, not the internal GUID. |
| create_vendorB | Create a new vendor. Args: name: Vendor name (e.g., "Office Depot"). currency: ISO currency code (e.g., "USD", "EUR"). Defaults to book's default currency. notes: Optional notes (max 4096 characters). address: Optional address with keys: name, addr1, addr2, addr3, addr4, phone, fax, email. Each sub-field capped at 1024 characters. |
| list_vendorsA | List all vendors. Leads with a Args: active_only: If True, only show active vendors. Default True. verbose: If true, return full JSON details for each vendor. limit: Page size (default 50, max 250). 0 = count only. offset: 0-indexed first row to return (default 0). |
| get_vendorA | Get details for a specific vendor by ID. Args: id: Vendor ID (e.g., "000001"). This is the human-readable ID shown in GnuCash, not the internal GUID. |
| create_employeeB | Create a new employee. Employee has no Args: name: Employee name (e.g., "Jane Smith"). currency: ISO currency code (e.g., "USD", "EUR"). Defaults to book's default currency. address: Optional address with keys: name, addr1, addr2, addr3, addr4, phone, fax, email. Each sub-field capped at 1024 characters. |
| list_employeesA | List all employees. Leads with a Args: active_only: If True, only show active employees. Default True. verbose: If true, return full JSON details for each employee. limit: Page size (default 50, max 250). 0 = count only. offset: 0-indexed first row to return (default 0). |
| get_employeeA | Get details for a specific employee by ID. Args: id: Employee ID (e.g., "000001"). This is the human-readable ID shown in GnuCash, not the internal GUID. |
| update_customerA | Update an existing customer. Mutates only the fields supplied; everything else stays.
Existing invoices/bills are not retroactively changed —
Args:
id: Customer ID (e.g., "000001").
name: New display name.
currency: New default ISO currency code (e.g., "EUR").
notes: New notes. Pass "" to clear.
active: |
| update_vendorC | Update an existing vendor. Same semantics as Args:
id: Vendor ID (e.g., "000001").
name: New display name.
currency: New default ISO currency code.
notes: New notes. Pass "" to clear.
active: |
| update_employeeA | Update an existing employee. Employee has no Args:
id: Employee ID (e.g., "000001").
name: New display name.
currency: New default ISO currency code.
active: |
| create_billtermA | Create a new billing term. Args: name: Billterm name (e.g., "Net 30"). due_days: Number of days until payment is due. Default 30. description: Optional description. discount_days: Days within which early discount applies. discount_percent: Early payment discount percentage (e.g., "2" for 2%). |
| list_billtermsA | List all billing terms. Leads with a Args: verbose: If true, return full JSON details for each billing term. limit: Page size (default 50, max 250). 0 = count only. offset: 0-indexed first row to return (default 0). |
| create_taxtableA | Create a new sales-tax table. A taxtable holds one or more entries. Each entry contributes either a percentage rate or a flat-value surcharge routed to a specific GL account (ASSET for input-tax credit, LIABILITY for output sales tax payable). Multi-entry composites (e.g., GST 5% + PST 7%) produce multiple tax splits per line at posting time. Args:
name: Taxtable name, unique within the book
(e.g., "CA Sales 7.25%", "BC GST+PST").
entries: List of {type, amount, account} dicts.
Example: create_taxtable( name="BC GST+PST", entries=[ {"type": "percentage", "amount": "5.00", "account": "Liabilities:GST Payable"}, {"type": "percentage", "amount": "7.00", "account": "Liabilities:PST Payable"}, ], ) |
| list_taxtablesA | List all sales-tax tables. Leads with a Args: verbose: If true, return full JSON for each taxtable. limit: Page size (default 50, max 250). 0 = count only. offset: 0-indexed first row to return (default 0). |
| get_taxtableA | Get full details for one sales-tax table. Returns guid, name, refcount (count of Entry rows referencing it — voided invoices still count), and the resolved entry list with account paths. Args: name: Taxtable name. |
| update_taxtableA | Update a sales-tax table's name and/or entries. Diff-style response: only changed fields are returned. Entry replacement on a taxtable that's already in use is
destructive to FUTURE entries' tax math. Existing posted
invoices retain their original splits (splits are stored,
not derived), but new entries on any document will use the
replacement entries' rates. When refcount > 0 and
Args:
name: Current taxtable name.
new_name: New name (optional).
entries: Replacement entry list (optional). Same shape
and validation as |
| delete_taxtableA | Delete a sales-tax table. Refuses when any Entry row references the taxtable (computed via SQL on the entries table). Voided invoices still pin their taxtables — voided entry rows persist for audit-trail purposes. Remove or re-assign referencing entries first. Args: name: Taxtable name. |
| create_invoiceA | Create a customer invoice. Args:
customer_id: Customer ID (e.g., "000001").
date_opened: Date in ISO format (YYYY-MM-DD). Defaults to today.
notes: Optional notes.
currency: ISO currency code. Defaults to the customer's
currency, falling back to the book's default. Pass
explicitly to override.
term: Billterm name (e.g., "Net 30"). Optional.
invoice_id: Custom invoice number (e.g., "INV-2026-001"). If omitted,
auto-generates from the book's invoice counter.
job_id: Optional Job ID. When set, groups the invoice
under the named job. The job must belong to the
same customer and be a customer-job (created
with owner_type='customer'). Use |
| create_billA | Create a vendor bill. Args: vendor_id: Vendor ID (e.g., "000001"). date_opened: Date in ISO format (YYYY-MM-DD). Defaults to today. notes: Optional notes. currency: ISO currency code. Defaults to the vendor's currency, falling back to the book's default. Pass explicitly to override. term: Billterm name (e.g., "Net 30"). Optional. bill_id: Custom bill number (e.g., "BILL-2026-001"). If omitted, auto-generates from the book's bill counter. job_id: Optional Job ID. When set, groups the bill under the named job. The job must belong to the same vendor and be a vendor-job. |
| add_invoice_entryA | Add a line item to a customer invoice. The invoice must not be posted yet. Entries represent individual goods or services being billed. Args:
invoice_id: Invoice ID (e.g., "000001").
account: Income account path (e.g., "Income:Sales").
description: Line item description.
quantity: Quantity as decimal string (e.g., "1", "2.5").
price: Unit price as decimal string (e.g., "100.00").
taxtable: Optional taxtable name. When given, the line
contributes tax components per the taxtable's entries
at posting time. Multi-entry taxtables (e.g., GST+PST)
produce one tax split per entry.
tax_included: If true, |
| add_bill_entryA | Add a line item to a vendor bill. The bill must not be posted yet. Entries represent individual goods or services being billed. Args:
bill_id: Bill ID (e.g., "000001").
account: Expense account path (e.g., "Expenses:Office Supplies").
description: Line item description.
quantity: Quantity as decimal string (e.g., "1", "2.5").
price: Unit price as decimal string (e.g., "50.00").
taxtable: Optional taxtable name. For vendor bills, the
tax component typically routes to an ASSET account
(input-tax credit receivable) per the taxtable's
entries.
tax_included: If true, |
| create_voucherA | Create an employee expense voucher. A voucher is the document an employee submits for reimbursement of out-of-pocket business expenses. It behaves like a vendor bill: post creates the obligation (debit expense accounts, credit A/P), pay settles it from a cash account. Args: employee_id: Employee ID (e.g., "000001"). date_opened: Date in ISO format (YYYY-MM-DD). Defaults to today. notes: Optional notes. currency: ISO currency code. Defaults to the employee's currency, falling back to the book's default. term: Billterm name (e.g., "Net 30"). Optional — vouchers rarely use payment terms. voucher_id: Custom voucher number. If omitted, auto-generates from the book's voucher counter. |
| add_voucher_entryA | Add a line item to an employee expense voucher. The voucher must not be posted yet. Each entry is typically a separate expense category (meals, supplies, travel). Account must be EXPENSE or ASSET. Args:
voucher_id: Voucher ID (e.g., "000001").
account: Expense account path (e.g.,
"Expenses:Meals & Entertainment").
description: Line item description.
quantity: Quantity as decimal string (e.g., "1").
price: Unit price as decimal string (e.g., "42.50").
taxtable: Optional taxtable name. Same semantics as
|
| delete_voucherA | Delete an unposted employee expense voucher. Automatically removes associated entries. Posted vouchers
cannot be deleted — unpost first via Args:
id: Voucher ID (e.g., "000001"). Preferred parameter
name — matches get_invoice / post_invoice / etc.
voucher_id: Legacy alias for |
| create_credit_noteA | Create a credit note against a customer invoice or vendor bill. A credit note reverses part or all of a posted invoice
while preserving the original posting in the audit trail.
At post time, posting direction reverses: customer credit
notes debit Income / credit A/R (reducing receivables);
vendor credit notes debit A/P / credit Expense (reducing
payables). Settled either by refund ( Use Args: owner_id: Customer or vendor ID (e.g., "000001"). owner_type: "customer" or "vendor". Employees are not supported (GnuCash desktop has no UI for employee credit notes; use unpost_invoice + edit on the voucher to amend an employee reimbursement). applies_to_invoice_id: Optional source invoice / bill ID. Must belong to the same owner and use the same currency. Highly recommended for audit trail. Can be omitted for floating credit notes that will be applied later. date_opened: ISO date (YYYY-MM-DD). Defaults to today. notes: Free-text notes (e.g., reason for the credit). currency: ISO currency code. Inherited from source invoice when applies_to_invoice_id is given; otherwise from owner's currency or book default. term: Billterm name. Rarely used for credit notes. credit_note_id: Custom ID. Auto-generated from the shared invoice/bill counter when omitted. |
| add_credit_note_entryA | Add a line item to a credit note. Mirrors Args:
credit_note_id: Credit note ID (e.g., "000032").
account: Account path appropriate for the owner type
(INCOME for customer, EXPENSE/ASSET for vendor).
description: Line item description.
quantity: Quantity as decimal string.
price: Unit price as decimal string.
owner_type: Optional "customer" or "vendor"
disambiguator for ID collisions. Usually omitted.
taxtable: Optional taxtable name. Same semantics as
|
| apply_credit_noteA | Net a posted credit note against a posted invoice or bill from the same owner. No cash moves — the credit balance transfers between lots on the same A/R or A/P account. This is the most common credit-note settlement path: the
bookkeeper issues a credit note against an overcharge,
then nets it against the next invoice from that customer
(or applies it to an outstanding bill on the vendor side).
Use Args:
credit_note_id: The credit note to apply (must be
posted).
applies_to_invoice_id: The target invoice/bill (must
be posted, same owner, same currency, same A/R
or A/P post account).
amount: Decimal-string amount to apply, in the
document currency. Defaults to |
| delete_credit_noteA | Delete an unposted credit note. Validates the target is a credit note before deletion.
Posted credit notes cannot be deleted — unpost first via
Args:
id: Credit note ID. Preferred parameter name — matches
get_invoice / post_invoice / etc.
credit_note_id: Legacy alias for |
| list_invoicesA | List invoices and/or vendor bills. Leads with a Args: owner_type: Filter by type: "customer" for invoices, "vendor" for bills, or omit for all. status: Filter by status: "posted" or "open", or omit for all. verbose: If true, return full JSON details. limit: Page size (default 50, max 250). 0 = count only. job_id: Filter to invoices grouped under a specific job — useful for the "what's part of this engagement?" listing pattern. offset: 0-indexed first row to return (default 0). |
| get_invoiceA | Get full details for an invoice or bill, including line items. Works for both customer invoices and vendor bills. Returns all entries with quantities, prices, and totals. Args: id: Invoice or bill ID (e.g., "000001"). This is the human-readable ID, not the internal GUID. owner_type: Filter by type: "customer" for invoices, "vendor" for bills. Useful when an invoice and bill share the same ID (independent counters). |
| post_invoiceA | Post a customer invoice or vendor bill. Posting creates a transaction in the A/R or A/P account and makes the invoice official. Once posted, entries cannot be added. For a foreign-currency document, the exchange rate is etched
at posting and cannot be updated retroactively. If the latest
price for the invoice currency is more than 7 days from the
post date (the Args: id: Invoice or bill ID (e.g., "000001"). post_account: A/R or A/P account path (e.g., "Assets:Accounts Receivable"). post_date: Date in ISO format (YYYY-MM-DD). Defaults to today. due_date: Payment due date (YYYY-MM-DD). Optional. description: Description for the posting transaction. Optional. owner_type: "customer" or "vendor" for disambiguation when IDs collide. force: Override the stale-FX-rate guard and post with a 7–90 day stale rate. Default False. |
| unpost_invoiceA | Reverse a posted invoice or bill. Deletes the posting transaction and lot, and clears the invoice's posted-state metadata. The invoice returns to "open" state and can be edited or re-posted. Refuses if the invoice has any payments applied — void payments first, then unpost. Args: id: Invoice or bill ID (e.g., "000001"). owner_type: "customer" or "vendor" for disambiguation when IDs collide. |
| pay_invoiceA | Record a payment against a posted invoice or bill. Creates a payment transaction from the specified bank/cash account to the invoice's A/R or A/P account. Partial payments are supported. For cross-currency payments where the rate moved between
post-date and pay-date, a realized FX gain/loss split is
booked. Pass For invoices with early-payment-discount terms (e.g.,
"2/10 Net 30" = 2% off if paid within 10 days), pass
Args:
id: Invoice or bill ID (e.g., "000001").
payment_account: Bank or cash account for payment (e.g., "Assets:Checking").
amount: Payment amount as decimal string (e.g., "500.00").
payment_date: Payment date (YYYY-MM-DD). Defaults to today.
description: Description for the payment transaction. Optional.
owner_type: "customer" or "vendor" for disambiguation.
fx_account: Optional INCOME or EXPENSE account to receive
realized FX gain/loss (cross-currency payments only).
Accepts a full path, %short GUID, or full 32-char GUID.
apply_discount: When True, treat this payment as the
final settlement and absorb the early-payment
discount from the invoice's billterm. Default False
— explicit opt-in. Hard-rejects on credit notes
(refunds don't take discounts).
discount_account: Optional INCOME or EXPENSE account to
receive the discount split. Auto-resolves when
omitted. Accepts full path, %short GUID, or full
32-char GUID.
force: Override the stale-FX-rate guard. A cross-currency
payment etches the rate at pay time; if the latest
price is 7–90 days from the payment date the payment
is refused with |
| delete_invoiceA | Delete an unposted customer invoice. Automatically removes associated entries (line items). Posted invoices cannot be deleted — void them or issue a credit note instead. Args:
id: Invoice ID (e.g., "000001" or "INV-2026-001").
Preferred parameter name — matches get_invoice /
post_invoice / etc.
invoice_id: Legacy alias for |
| delete_billA | Delete an unposted vendor bill. Automatically removes associated entries (line items). Posted bills cannot be deleted — void them or issue a credit note instead. Args:
id: Bill ID (e.g., "000001" or "BILL-2026-001").
Preferred parameter name — matches get_invoice /
post_invoice / etc.
bill_id: Legacy alias for |
| delete_customerA | Delete a customer with no invoices. Customers with any invoices (posted or unposted) cannot be deleted. Delete the invoices first, then delete the customer. Args: customer_id: Customer ID (e.g., "000001"). |
| delete_vendorA | Delete a vendor with no bills. Vendors with any bills (posted or unposted) cannot be deleted. Delete the bills first, then delete the vendor. Args: vendor_id: Vendor ID (e.g., "000001"). |
| delete_employeeB | Delete an employee. Employees in the 1.3.0 release have no associated documents; the delete proceeds unconditionally after slot cleanup. Args: employee_id: Employee ID (e.g., "000001"). |
| create_jobA | Create a job for a customer or vendor. A job groups invoices (or bills) from one counterparty under a project-level container. Useful when a single customer has multiple distinct engagements (e.g., 'API Rewrite' and 'Q3 Maintenance') that should be reported on separately even though invoices flow to the same A/R. Args: owner_id: Customer or vendor ID (e.g., "000001"). owner_type: "customer" or "vendor". Employees are not supported (no GnuCash desktop UI for employee jobs). name: Human-readable job name (e.g., "API Rewrite"). reference: Optional reference string (PO number, project code). |
| list_jobsA | List jobs, optionally filtered. Leads with a Args: owner_type: Filter by "customer" or "vendor". Omit for all. owner_id: Filter by specific customer or vendor ID (requires owner_type). active_only: If True (default), exclude inactive jobs. verbose: If True, return full JSON dicts; otherwise compact tab-separated rows. limit: Page size (default 50, max 250). 0 = count only. offset: 0-indexed first row to return (default 0). |
| get_jobA | Get a job's details by ID. Returns name, owner, active state, plus a count + IDs list of every invoice/bill linked to the job. Args: job_id: Job ID (e.g., "000001"). |
| update_jobA | Update a job's name, reference, or active state. Any subset of fields can be passed; unspecified fields are left unchanged. Returns a diff-style response. Args: job_id: Job ID. name: New name (optional). reference: New reference (optional). active: New active flag — pass False to deactivate a completed job without deleting it (preserves history). |
| get_job_reportA | Per-job summary: billed / paid / outstanding totals across all linked invoices, plus the per-invoice breakdown. Totals are returned as Args: job_id: Job ID (e.g., "000001"). |
| delete_jobA | Delete a job. Refuses by default when invoices/bills are linked to the
job (data-loss prevention). Args: job_id: Job ID. force: If True, re-parent linked invoices instead of refusing. Default False. |
| get_outstanding_invoicesA | Get all posted invoices/bills with outstanding balances. Leads with a Use verbose=true for full JSON with Args: owner_type: Filter by "customer" or "vendor". Omit for all. customer_id: Filter by specific customer ID. vendor_id: Filter by specific vendor ID. verbose: If true, return full JSON details. limit: Page size (default 50, max 250). 0 = count only. offset: 0-indexed first row to return (default 0). |
| vendor_spending_reportA | Get spending breakdown by vendor for a period. Analyzes posted vendor bills to show total billed, total paid, and outstanding amounts per vendor. Returns a compact aligned text table by default. Use verbose=true for the full structured dict (programmatic consumers). Args: start_date: Start of period (YYYY-MM-DD). end_date: End of period (YYYY-MM-DD). vendor_id: Optional filter to a specific vendor. verbose: If true, return the structured dict. group_by: Optional "month", "quarter", or "year" — split the range into sub-period columns of total billed per vendor and return a multi-period TSV table. Overrides verbose. |
| get_book_summaryA | Get a compact overview of the entire GnuCash book. Returns book path, currency, account structure, transaction counts, key balances, net worth, commodities, and scheduled transactions in a single text response. Use this first to orient yourself. |
| list_accountsA | List all accounts in the GnuCash chart of accounts. Leads with a To FIND an account without paging the whole chart, pass
Args:
root: Filter to a subtree (e.g., "Expenses" for expense accounts only).
verbose: If true, return full JSON details for each account.
limit: Page size (default 50, max 250). 0 = count only.
offset: 0-indexed first row to return (default 0).
query: Case-insensitive substring filter on account
path/description. Combines with |
| get_accountB | Get details for a specific account by name. Args: name: Account ref: full path (e.g. 'Assets:Bank:Checking'), %short GUID, or full 32-char GUID |
| get_balanceA | Get the balance of an account as of a specific date. Defaults to today's date — future-dated transactions
(scheduled payments, accrued interest) are excluded. To
project a balance forward including future entries, pass
an explicit Args: account_name: Account ref: full path (e.g. 'Assets:Bank:Checking'), %short GUID, or full 32-char GUID as_of_date: Date in ISO format (YYYY-MM-DD). Defaults to today. |
| list_transactionsA | List transactions with optional filters. Leads with a Compact format (default):
Transactions with more than 4 splits collapse to the top 3 by
|value| plus Args: account: Filter by account name (switches output to register form) start_date: Start date in ISO format (YYYY-MM-DD) end_date: End date in ISO format (YYYY-MM-DD) limit: Page size (default 50, max 250). 0 = count only. offset: 0-indexed first row to return (default 0). verbose: If true, return full JSON details for each transaction. |
| get_transactionA | Get details for a specific transaction by GUID. Args: guid: Transaction GUID (32-character hex string, or 8+ char prefix) |
| create_transactionA | Create a new transaction with splits. Splits must balance to zero. Each split: FIELD TARGETING — the annotation fields, one job each, in GnuCash-register visibility order:
When duplicate detection surfaces candidates (either rejecting
the write with Confidence is Args: description: Transaction description. splits: List of split dicts (see above). Omit to auto-fill from the most recent matching-description transaction. transaction_date: ISO date (YYYY-MM-DD). Defaults to today. currency: ISO currency code. Defaults to book's default. notes: What the purchase was (see FIELD TARGETING above). check_duplicates: Run duplicate detection. Default True. force_create: Create even if HIGH-confidence duplicates found. dry_run: Validate + dupe check only; don't write. |
| create_transactionsA | Create MANY transactions in one atomic command (bulk entry). INPUT — Two opt-in extensions, each activated by naming it in the header (legacy headers parse exactly as before):
All extensions combine; when several split fields are
declared, the header's FIRST group fixes their order (e.g.
AUTO-FILL — a row with NO split cells at all (ends right
after Auto-filled rows are marked
BEHAVIOR — one book-open, one atomic save:
OUTPUT — a JSON envelope of two TSV tables joined by
Args: transactions: The TSV block described above. force: Override ALL blocking (HIGH) duplicates this batch. dry_run: Validate + screen, write nothing. on_error: "abort" (default) or "skip" for structural errors. |
| search_transactionsA | Search transactions by description, memo, notes, or amount. Compact format (default):
Args: query: Search query string. For amount, supports: exact ("100"), greater (">100"), less ("<100"), range ("100-200") field: Field to search: 'description', 'memo', 'notes', or 'amount' limit: Page size (default 50, max 250). 0 = count only. offset: 0-indexed first row to return (default 0). verbose: If true, return full JSON details for each transaction. |
| create_accountA | Create a new account in the chart of accounts. Args: name: Account name (e.g., "AI Subscriptions"). account_type: One of ASSET, BANK, CASH, CREDIT, EQUITY, EXPENSE, INCOME, LIABILITY, MUTUAL, STOCK, RECEIVABLE, PAYABLE. parent: Parent account ref (full path, %short GUID, or full 32-char GUID). Omit for top-level. description: Optional description. placeholder: Container-only account. Default False. commodity: ISO currency code ("USD") or stock/fund symbol ("VTSAX"). Defaults to book's default currency. commodity_namespace: "CURRENCY" (default), "FUND", or an exchange ("NASDAQ", "NYSE"). Required with non-currency commodities. notes: Optional free-text notes (max 4096 bytes). Shows in GnuCash desktop's account editor Notes field. |
| update_accountA | Update an existing account's properties. Args: name: Account ref to update (full path e.g. "Expenses:Groceries", %short GUID, or full 32-char GUID) new_name: New name for the account (just the leaf name, not full path) description: New description placeholder: New placeholder status (true = container only) account_type: New account type (e.g., "CREDIT", "BANK"). Only changes within the same debit/credit polarity are allowed — e.g., LIABILITY to CREDIT, ASSET to BANK. Cross-polarity changes (e.g., ASSET to LIABILITY) are blocked. notes: New notes (max 4096 bytes; shared with GnuCash desktop's Notes field). Pass "" to clear. |
| move_accountB | Move an account to a new parent in the hierarchy. Args: name: Account ref to move (full path e.g. "Expenses:Old:Account", %short GUID, or full 32-char GUID) new_parent: New parent account ref (full path, %short GUID, or full 32-char GUID) |
| delete_accountA | Delete an account from the chart of accounts. Safeguards prevent deletion if the account has children or transactions. Args: name: Account ref to delete (full path, %short GUID, or full 32-char GUID) |
| delete_transactionA | Delete one transaction by GUID — or several in one call. Safeguards prevent deletion if a transaction has reconciled splits (force=true overrides) or is an invoice's posting record (unpost_invoice first). Pass a LIST of GUIDs to delete several in one book open /
one save. The batch is all-or-nothing: every guid is
validated before anything is deleted, so a bad guid rejects
the whole call with nothing removed. Response for a list is
Args: guid: Transaction GUID (32-char hex or 8+ char prefix), or a list of them. force: Allow deleting transactions with reconciled splits. |
| update_transactionA | Update an existing transaction — or broadcast to several. Pass a LIST of GUIDs to apply the SAME supplied values to
every listed transaction in one book open / one save
(all-or-nothing) — the batch-annotation case: one note
across 35 related entries, one call. Args:
guid: Transaction GUID (32-character hex string, or 8+ char prefix), or a list of them
description: New transaction description (optional)
transaction_date: New date in ISO format YYYY-MM-DD (optional)
splits: List of split updates with 'account' and 'amount' (optional).
Must match existing splits by account name and balance to zero.
For cross-currency splits, include 'quantity' (amount in account's commodity).
Include 'memo' to set that split's memo (omit to leave it unchanged).
|
| update_transactionsA | Update MANY transactions with per-row values (bulk edit). INPUT — An EMPTY cell leaves that field UNCHANGED — this batch can
annotate but never clear (clearing is One book open, one save; |
| replace_splitsA | Replace all splits in a transaction with a new set. Replace all splits in a transaction with a completely new set. The transaction's currency, description, date, and notes are preserved. New splits must balance to zero. A new split that reproduces an existing one (same account, amount, and quantity) is an UNCHANGED leg: it keeps the old split's memo (supply a memo to override) and its reconcile state. So recategorizing the expense leg of a reconciled bank transaction is safe — resubmit the bank leg as-is and only the changed leg resets. Args: guid: Transaction GUID (32-character hex string, or 8+ char prefix) splits: Complete new set of splits. Each split needs: - 'account' (required): Account ref — full path, %short GUID, or full 32-char GUID - 'amount' (required): Value in transaction currency, as a decimal string - 'quantity' (optional): Amount in account's commodity, as a decimal string. Required if account commodity differs from transaction currency. - 'memo' (optional): Split memo force: Required only when the replacement would CHANGE a reconciled split (or remove splits from lots) — unchanged reconciled legs are preserved without it. |
| list_commoditiesA | List all commodities (currencies, stocks, etc.) in the book. Leads with a THE PRICE-UPDATE WORK LIST: Args: verbose: If true, return full JSON details for each commodity. limit: Page size (default 50, max 250). 0 = count only. offset: 0-indexed first row to return (default 0). stale_days: Only commodities whose latest market price is at least this many days old, including never-priced ones, excluding the book default currency. Omit for the unfiltered list. held_only: Only commodities some real account is denominated in. Filters AND-combine. |
| create_commodityA | Create a new commodity (stock, mutual fund, etc.). Args: mnemonic: Symbol (e.g., "VTSAX"). Unique within namespace. fullname: Human-readable name. namespace: "FUND" (default) for mutual funds, "NASDAQ"/"NYSE"/ "AMEX" for stocks, or any custom string. fraction: Smallest fractional unit. 1 = whole units, 100 = 2 decimals, 10000 = 4 decimals (default, shares), 1000000 = 6 decimals (crypto). cusip: Optional CUSIP/ISIN identifier. |
| create_pricesA | Record MANY prices in one call (bulk quote entry). INPUT —
Per-row semantics are The companion work list: |
| create_priceA | Record a price for a commodity (stock, NAV, exchange rate). An existing price with the same commodity/currency/date/source is updated rather than duplicated. Args:
commodity: Symbol (e.g., "VTSAX").
namespace: Commodity namespace (e.g., "FUND", "NASDAQ").
value: Price per unit as decimal string (e.g., "250.45").
currency: ISO currency code. Defaults to the book's default
currency — so |
| delete_priceA | Delete a single price entry. Identifies the price by Args: commodity: Symbol (e.g., "VTSAX", "USD", "EUR"). namespace: Namespace (e.g., "FUND", "CURRENCY"). date: ISO date (YYYY-MM-DD) of the price to delete. source: Optional source tag (e.g., "user:price", "user:yfinance"). Required when multiple prices exist on the same commodity+date. |
| get_pricesA | Get price history for a commodity. Leads with a Args: commodity: Symbol of the commodity (e.g., "VTSAX"). namespace: Namespace of the commodity (e.g., "FUND"). start_date: Optional start date filter (YYYY-MM-DD). end_date: Optional end date filter (YYYY-MM-DD). currency: Optional currency filter (e.g., "USD"). limit: Page size (default 50, max 250). 0 = count only. verbose: If true, return the structured dict. offset: 0-indexed first row to return (default 0). |
| get_latest_priceA | Get the most recent price for a commodity. Args: commodity: Symbol of the commodity (e.g., "VTSAX"). namespace: Namespace of the commodity (e.g., "FUND"). currency: Currency for the price. Defaults to the book's default currency. Pass explicitly to get a price quoted in a non-default currency. Returns: JSON with date, value, type, and source of most recent price. Returns null if no price exists. |
| create_lotB | Create a new lot for cost basis tracking. Lots group investment purchases for tracking cost basis and calculating capital gains when selling. Args: account: Account ref for the investment account: full path (e.g., "Assets:Investments:VTSAX"), %short GUID, or full 32-char GUID. title: Lot identifier (e.g., "VTSAX 2026-01-15 purchase"). notes: Optional notes. |
| list_lotsA | List all lots for an investment account. Leads with a Args: account: Account ref (full path, %short GUID, or full 32-char GUID). include_closed: If True, include fully-sold lots. Default False. verbose: If true, return full JSON details for each lot. limit: Page size (default 50, max 250). 0 = count only. offset: 0-indexed first row to return (default 0). |
| get_lotA | Get detailed information about a lot. Args: guid: Lot GUID (or 8+ char prefix). Returns: JSON with lot details including all splits: - title, notes, is_closed - splits: list of all splits with date, quantity, value - summary: total quantity, cost basis, cost per share |
| assign_split_to_lotA | Assign a transaction split to a lot. Use after creating a buy/sell transaction to link the investment account split to its lot for cost basis tracking. Args: split_guid: GUID of the split (from transaction's investment account). 8+ char prefix accepted. lot_guid: GUID of the lot (or 8+ char prefix). Workflow: 1. create_lot("Assets:VTSAX", "VTSAX Jan 2026") 2. create_transaction(...buy 10 shares...) 3. assign_split_to_lot(investment_split_guid, lot_guid) |
| calculate_lot_gainA | Calculate potential or actual capital gain for a lot. If shares and sale_price provided, calculates hypothetical gain. Otherwise uses lot's current state and latest price. Args: lot_guid: Lot GUID (or 8+ char prefix). shares: Optional number of shares to calculate for. Defaults to all remaining shares. sale_price: Optional sale price per share. Defaults to latest price for the commodity. |
| close_lotA | Mark a lot as closed. Use when a lot is fully sold but wasn't automatically marked closed, or to manually close a lot with zero shares. Args: guid: Lot GUID (or 8+ char prefix). Note: Lots are automatically marked closed when their quantity reaches zero through assigned splits. This tool is for manual cleanup. |
| set_reconcile_stateA | Set the reconciliation state for a split. Args: split_guid: GUID of the split to update (32-character hex string, or 8+ char prefix) state: New reconcile state: 'n' (new), 'c' (cleared), 'y' (reconciled) reconcile_date: Date in ISO format (YYYY-MM-DD). Required for 'y', defaults to today. |
| get_reconciliation_statusA | Per-account reconciliation table behind the dashboard's aggregate counts — answers "WHICH accounts are never reconciled / dormant / behind?" One line per reconcilable account with activity, bucketed
exactly as the dashboard classifies them: Args: verbose: Full JSON rows instead of compact TSV lines. limit: Page size (default 50, max 250). 0 = count only. offset: 0-indexed first row to return. |
| get_unreconciled_splitsA | Get unreconciled splits for an account. Leads with a Use verbose=true for full JSON with split GUIDs, amounts, totals,
and the Args: account: Account ref: full path (e.g. 'Assets:Bank:Checking'), %short GUID, or full 32-char GUID as_of_date: Only include splits on or before this date (YYYY-MM-DD) verbose: If true, return full JSON details. Default compact one-line format. limit: Page size (default 50, max 250). 0 = count only. offset: 0-indexed first row to return (default 0). |
| reconcile_accountA | Reconcile splits against a statement balance. SIGN CONVENTION: statement_balance is the ACCOUNT's balance in GnuCash's signs — for liability accounts (credit cards) a $5,000 owed balance is "-5000", not "5000". Two modes:
Both modes verify the resulting reconciled balance ties to statement_balance before mutating; mismatch rejects with the discrepancy amount. TYPICAL STATEMENT FLOW (credit card or bank): batch-enter the statement's transactions (create_transactions), then reconcile_all with the statement's closing date and balance. Multi-month catch-up: enter all months in one batch, then one reconcile_all per statement, oldest first — the through_date default keeps each sweep inside its own statement. Args: account: Account ref: full path (e.g. 'Assets:Bank:Checking'), %short GUID, or full 32-char GUID statement_date: Statement ending date (YYYY-MM-DD) statement_balance: Expected balance from statement (as string, e.g., '1234.56') split_guids: List of split GUIDs to reconcile (targeted mode). Omit for bulk mode. reconcile_all: When true, reconcile all unreconciled splits up to through_date. through_date: Date filter for bulk mode (YYYY-MM-DD); defaults to statement_date. |
| void_transactionA | Void a transaction (proper accounting void, not delete). Voiding preserves the transaction for audit purposes but zeroes out all split values. Use this instead of delete when you need to maintain an audit trail. Args: guid: Transaction GUID to void (32-character hex string, or 8+ char prefix) reason: Reason for voiding (required for audit trail) |
| unvoid_transactionB | Restore a voided transaction. Restores original split values and removes void markers. Args: guid: Transaction GUID to unvoid (32-character hex string, or 8+ char prefix) |
| spending_by_categoryA | Get spending breakdown by expense category for a period. Returns a compact aligned text table by default. Use verbose=true for the full structured dict (programmatic consumers, plotting). Args: start_date: Start of period (YYYY-MM-DD) end_date: End of period (YYYY-MM-DD) depth: Hierarchy depth for grouping (1 = top-level categories, 2 = subcategories) verbose: If true, return the structured dict. group_by: Optional "month", "quarter", or "year" — split the range into sub-period columns and return a multi-period TSV table (category rows, one column per period plus Total and Avg). Overrides verbose. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
| accounts_resource | Full chart of accounts from the GnuCash book. Resources are whole-snapshot reads, so this unwraps the paginated envelope and returns the bare account list (up to the server cap). |
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/ninetails-io/gnucash-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server