Skip to main content
Glama
contabridge-mcp

contabridge-mcp

contabridge-mcp

An MCP server that moves bookkeeping between Spanish accounting programs and QuickBooks / Xero, built for AI agents that work for gestorías and accounting firms with many clients. It does not store any data between calls, and every result is deterministic.

Tool

Credits

What it does

convert_journal

2

Converts a libro diario between a3ASESOR/a3ECO/a3CON (SUENLACE.DAT), Sage ContaPlus / Sage 50 (Diario CSV of 142 fields, or XDiario ASCII), ContaSol (APU.ods, destination only), spreadsheet CSV (Holded, Excel, any ERP), QuickBooks (Desktop IIF, Online journal CSV) and Xero (manual journal CSV). It resizes subaccounts (4300001 → 43000001, 430.1 → 43000001), renames accounts and renumbers entries.

invoices_to_journal

3

Books issued and received invoices (and rectificativas) with VAT, recargo de equivalencia and IRPF split out (430/700/477, 600/472/4751/400). Checks base + IVA - IRPF = total; invoices that do not add up go to review, never booked. Returns the VAT summary per rate (libro registro / modelo 303) and open_items for bank_to_journal.

bank_to_journal

3

Turns a Norma 43 statement, the bank's CSV export or a movements list into journal entries against the 572 subaccount. Pending invoices (open_items) are settled first against the customer/supplier subaccount on same amount + reference or name; then ordered rules (text, regex, AEB concept, direction); the rest go to 555 and are listed. Ties are never guessed.

pdf_bank_to_journal

3

Reads a digital bank statement PDF (selectable text: Revolut, Wise, N26, CaixaBank, BBVA, Santander... downloaded from online banking) deterministically, with no OCR and no AI. Checks every row against the running balance (previous balance + amount = printed balance) and opening + in - out = closing; rows that do not add up are flagged, rows whose sign cannot be proven go to review and are not booked. Returns ContaSol (APU.ods), A3, ContaPlus, CSV, QuickBooks/Xero or a Norma 43 (.n43) file. strict_balance=true refuses (free) unless everything adds up.

build_journal

2

Writes entries the agent composed (invoices, payroll, accruals) in any of the formats.

bank_statement_csv

1

Turns a Norma 43 statement into a bank statement CSV for Xero (precoded template) or QuickBooks Online (3 columns).

validate_journal

1

Runs the checks A3 and ContaPlus run on import: balanced entries, debit or credit on each line (never both), PGC groups, fiscal year, mixed account lengths.

resize_account, detect_format, pricing, credits_balance

0

Free helpers.

Output files are returned as content and as content_base64. The base64 version is Windows-1252 with CRLF line endings (UTF-8 with BOM for CSV), which is what these programs import.

Charging works like this:

  • A file that would be rejected (unbalanced, unreadable, missing columns) is refused before any credits are charged.

  • A failure after charging is refunded.

Formats and sources

  • A3: "Enlace contable de entrada. Descripción de registros" (Wolters Kluwer). Record type 0, format 5 (512 bytes) and format 4 (256 bytes). When reading, invoice records (types 1, 2 and 9) are skipped and reported in a warning.

  • ContaPlus: "Protocolo de comunicación de programas de gestión con ContaPlus" (Sage, 2023). Writes Asien, Fecha, SubCta, Contra, Concepto, Documento, MonedaUso=2, EuroDebe and EuroHaber. The fixed-width ASCII variant (32 fields) uses the same layout as the open-source BulmaGés exporter.

  • ContaSol: "Importación Excel / Calc" (Software DELSOL, GIP.C.01.10 rev. 9, 2023), Apuntes file APU.ods, columns A to Q, no header row, Moneda E, Diario 0. The .ods bytes are deterministic. Import it in ContaSol from Utilidades > Importaciones. Subaccounts must have the company's digits: pass account_digits.

  • QuickBooks Desktop IIF: GENERAL JOURNAL transactions (!TRNS/!SPL/!ENDTRNS, tab separated). Debits are positive and credits negative, so the TRNS amount is minus the sum of its SPL lines. Other IIF lists (accounts, customers) are skipped with a warning.

  • QuickBooks Online: "Import journal entries" CSV with Journal No., Journal Date, Account Name, Debits, Credits, Description, Name.

  • Xero: "Import a manual journal" template (*Narration, *Date, Description, *AccountCode, *TaxRate, *Amount, tracking). Lines with the same Narration and Date form one journal. xero_tax_rate sets the TaxRate as named in that organisation (UK No VAT, AU BAS Excluded, NZ No GST, US Tax Exempt).

  • QuickBooks and Xero dates follow date_style: mdy (default for QuickBooks), dmy (default for Xero) or iso. Amounts use a decimal point, and a comma is always read as a thousands separator. Their accounts are names or codes, so they are validated against their own chart, not the PGC. Use account_map to translate them when converting to or from A3/ContaPlus.

  • CSV: columns are detected in Spanish and English (fecha, cuenta, debe, haber, importe+d/h…), or set with column_map. A file without an entry number is grouped into entries by accumulating lines until they balance.

Related MCP server: ledgerkit-mcp

Install

All you need is your KeyFlint license (LIC-...). The gateway URL, its public key and the checkout link have defaults.

Claude Desktop, one click: download contabridge-mcp-X.Y.Z.mcpb from the latest release, double-click it and paste your license. No terminal, no JSON.

Claude Code:

claude mcp add contabridge -e KEYFLINT_LICENSE=LIC-... -- uvx contabridge-mcp

Cursor, Windsurf, Claude Desktop (JSON):

{
  "mcpServers": {
    "contabridge": {
      "command": "uvx",
      "args": ["contabridge-mcp"],
      "env": { "KEYFLINT_LICENSE": "LIC-..." }
    }
  }
}

Optional: KEYFLINT_URL, KEYFLINT_PUBLIC_KEYS (fetched from the gateway and cached in ~/.keyflint/keyring.json when unset), KEYFLINT_CHECKOUT_URL.

Hosted mode: CONTABRIDGE_TRANSPORT=http contabridge-mcp --http (license per request, Authorization: Bearer LIC-...).

Tuning: CONTABRIDGE_PRICES (convert_journal=3,bank_to_journal=5), CONTABRIDGE_MAX_BYTES.

Visual cards (MCP Apps)

In Claude, ChatGPT, VS Code and Goose every paid tool and credits_balance renders as an interactive card in the chat: credit balance with a refill bar and a buy button, or a result summary (key figures, issues, table preview and credits charged). It is the ui://contabridge/card.html resource, self-contained with no network access. Other clients keep getting the same JSON as before.

Claude skill

skills/contabridge/SKILL.md (zipped in distribution/contabridge-skill.zip) tells the agent which tool to use, which account length to ask for, and how to save the file.

Tests

pip install -e '.[test]' && pytest

The tests use a fake KeyFlint gateway and locally signed licenses, so they need no network. A3 and ContaPlus layouts are checked position by position against the official specifications.

License

Business Source License 1.1. Source available; production use needs a KeyFlint license (or must be non-commercial). Each version becomes Apache 2.0 four years after release. See LICENSE.

Available Tools

11 tools
bank_statement_csvConvert bank statement to bank-feed CSVA
Read-onlyIdempotent
Inspect

Turn a Norma 43 (Cuaderno 43) statement into a bank statement CSV that Xero or QuickBooks Online import.

target: xero (precoded statement: *Date, *Amount, Payee, Description, Reference) or quickbooks (3 columns: Date, Description, Amount). Amounts are signed (abono +, cargo -). date_style: mdy | dmy | iso (default mdy for QuickBooks, dmy for Xero). account: last digits of one bank account when the file holds several.

Inputs: target (required), account, content, date_style, +1 more. Returns: object

bank_to_journalBook Norma 43 bank statement as journalA
Read-onlyIdempotent
Inspect

Turn a bank statement (Norma 43, the bank's Excel/CSV export, or a movements list) into journal entries.

One entry per movement: abono -> Debe bank / Haber counterpart; cargo -> Debe counterpart / Haber bank. The counterpart comes from the first matching rule; with no match it goes to suspense_account (default 555 'partidas pendientes de aplicación', padded to the bank account length) and the movement is listed in unmatched, so nothing is guessed.

Args: bank_account: The 572 subaccount of the bank, e.g. "57200001" (for QuickBooks/Xero: that program's bank account name or code, and suspense_account is then required). target_format: csv (default) | a3 | contaplus_csv | contaplus_ascii | contasol | quickbooks_iif | quickbooks_csv | xero_csv. content / content_base64: The .n43 file (base64 for CP850/Latin-1 bytes), or the bank's CSV export (Excel saved as CSV: a header row with fecha + importe, or cargo + abono, and concepto). movements: Instead of a file, [{"date": "2026-03-05", "amount": "-121.00", "text": "IBERDROLA"}] for statements read from Excel or PDF (+ money in, - money out). open_items: Pending invoices to settle FIRST, before rules: [{"account": "43000012", "amount": "1210.00", "reference": "F-2026-031", "name": "Talleres Ruiz", "date": "2026-02-28"}]. Signed as the bank sees it (+ cobro de cliente, - pago a proveedor). A movement is booked against the customer/supplier subaccount only on the same amount AND a unique reference or name in the bank text (or a unique amount within window_days). Ties are listed in open_items.ambiguous and never guessed. invoices_to_journal returns these items ready to pass here. rules: Ordered list, first match wins. Each: {"account": "62800000", "contains": ["IBERDROLA"] or "regex": "...", "common_concept": "03" (AEB concept, e.g. 03 recibos, 04 transferencias, 12 comisiones), "direction": "cargo"|"abono", "concept": optional fixed text}. Text matching is case-insensitive over the movement description (own concept + record-23 texts). bank_accounts: For files with several bank accounts: {IBAN or last digits: "57200002"}. use_value_date: Date entries by value date instead of operation date. account_digits / account_split: Resize every subaccount (see convert_journal). start_entry_number: First entry number (default 1).

Inputs: bank_account (required), rules, content, a3_format, +15 more. Returns: object

build_journalBuild journal import fileA
Read-onlyIdempotent
Inspect

Write journal entries you composed (e.g. from invoices or a payroll summary) as an import file.

entries: [{"date": "2026-03-31", "number": 1 (optional), "lines": [{"account": "64000000", "debit": "1500.00", "concept": "Nómina marzo"}, {"account": "47510000", "credit": "225.00"}, ...]}]. Entries must balance: an unbalanced entry is refused before any charge, with the difference. target_format accepts every format of convert_journal, including quickbooks_iif, quickbooks_csv and xero_csv (date_style / xero_tax_rate as there).

Inputs: entries (required), target_format (required), a3_format, date_style, +7 more. Returns: object

convert_journalConvert journal between accounting programsA
Read-onlyIdempotent
Inspect

Convert a libro diario (journal) between Spanish accounting programs.

Formats: a3 (a3ASESOR/a3ECO/a3CON SUENLACE.DAT, apuntes tipo 0), contaplus_csv (Sage ContaPlus / Sage 50 Diario CSV, 142 fields), contaplus_ascii (XDiario.txt fixed width), contasol (ContaSol APU.ods, destination only: save content_base64 as APU.ods and import it in Utilidades > Importaciones), csv (spreadsheet with header: Holded, Excel, any ERP; columns auto-detected, override with column_map), quickbooks_iif (QuickBooks Desktop general journal), quickbooks_csv (QuickBooks Online journal import), xero_csv (Xero manual journal import). The source is auto-detected. QuickBooks/Xero accounts are names or codes, not PGC subaccounts: use account_map to translate them when converting to or from A3/ContaPlus.

Args: target_format: a3 | contaplus_csv | contaplus_ascii | contasol | csv | quickbooks_iif | quickbooks_csv | xero_csv. content: The file as text. content_base64: raw bytes as base64 (Latin-1/CP1252 files with Ñ). source_format: auto (default) or one of the formats. account_digits: Resize every subaccount to this length (ContaPlus uses a fixed length, e.g. 8); also expands '430.1' shorthand. 0 keeps them. account_split: Where zeros are inserted/removed when resizing (default 4: 4300001 -> 43000001). account_map: Exact account renames applied first, e.g. {"5720001": "57200005"}. start_entry_number: Renumber entries from this number (ContaPlus requires numbers; A3 does not use them). company_code: A3 company code (1-99999). a3_format: 5 (512-byte records, current) or 4 (256, old). column_map: For csv sources, e.g. {"debit": "Importe D", "account": "Cta"}. Keys: number, date, account, account_name, debit, credit, amount, dh, concept, document. csv_delimiter: For csv source/target; auto-detected on read, ';' on write. decimal_comma: csv output with decimal comma (Spanish Excel). fiscal_year: flag dates outside it. strict: Refuse to write a file with validation errors (default), so the target program never rejects it. date_style: Dates in QuickBooks/Xero files, read and write: mdy (US, QuickBooks default), dmy (UK/AU/NZ, Xero default) or iso. xero_tax_rate: TaxRate written on every Xero line, as named in that Xero organisation (UK "No VAT", AU "BAS Excluded", NZ "No GST", US "Tax Exempt").

Inputs: target_format (required), strict, content, a3_format, +13 more. Returns: object

credits_balanceCheck credit balanceB
Read-only
Inspect

Remaining credits on your KeyFlint license. Free.

Inputs: no named parameters. Returns: object

detect_formatDetect accounting file formatB
Read-onlyIdempotent
Inspect

Tell which accounting import format a file is (a3, contaplus_csv, contaplus_ascii, csv, quickbooks_iif, quickbooks_csv, xero_csv). Free.

Inputs: content, content_base64. Returns: object

invoices_to_journalBook invoices with VAT as journalA
Read-onlyIdempotent
Inspect

Book issued and received invoices (facturas emitidas y recibidas) as journal entries with VAT split out.

Read each invoice (PDF, photo, Facturae, email) yourself and pass its figures; this tool does the bookkeeping deterministically. Per invoice: {"kind": "issued"|"received", "number": "F-2026-031", "date": "2026-02-28", "nif": "B12345678", "name": "Talleres Ruiz SL", "taxes": [{"base": "1000.00", "rate": "21", "vat": "210.00" (optional, checked), "recargo_rate": "5.2" (optional)}], "irpf_rate": "15" or "irpf_amount": "150.00" (optional), "total": "1060.00" (optional but recommended: checked), "account": "43000012" (optional), "counterpart_account": "62300000" (optional, default 700 / 600), "concept": optional}. Shortcut for one VAT rate: "base" + "vat_rate". Negative amounts = factura rectificativa (sides swap).

Issued: Debe 430 total (+ 473 IRPF retenido por el cliente) / Haber 700 base + 477 IVA. Received: Debe 600 base + 472 IVA / Haber 4751 IRPF + 400 total. Tax is recomputed (base x rate, half up); a 1-cent difference with the invoice total is absorbed in the largest tax line, more than that sends the invoice to review with the reason, unbooked. Duplicates (same kind + NIF + number) also go to review.

Args: accounts: Override default roots {customers 430, suppliers 400, sales 700, purchases 600, vat_output 477, vat_input 472, irpf_withheld 4751, irpf_suffered 473}. party_accounts: {NIF: subaccount}, e.g. {"B12345678": "43000012"}. Invoices with no account are booked to the generic 430/400 and listed in generic_party_account so the accountant assigns them. vat_accounts: {rate: subaccount}, e.g. {"21": "47700021", "10": "47700010", "re5.2": "47700052"}. target_format / account_digits / company_code / ...: as in build_journal.

Returns the import file, vat_summary (base and cuota per rate for the libro registro / modelo 303), vat_register (one row per invoice and rate), review and open_items to pass to bank_to_journal.

Inputs: invoices (required), accounts, a3_format, date_style, +10 more. Returns: object

pdf_bank_to_journalBook bank statement PDF as journalA
Read-onlyIdempotent
Inspect

Read a digital bank statement PDF (Revolut, Wise, N26, CaixaBank, BBVA, Santander... downloaded from online banking, with selectable text) and turn it into journal entries or a Norma 43 file.

Deterministic: the movements table is located by its header (Fecha, Concepto, Cargo/Abono or Importe, Saldo) and each value is read from its column. No OCR and no AI: scanned PDFs are refused, not guessed. Every row is checked: previous balance + amount = printed balance, and opening + money in - money out = closing balance. Rows that do not add up are booked but listed in flagged_rows with status "mismatch"; rows whose sign (cargo/abono) cannot be proven go to status "review" and are NOT booked. Check balance_check.balanced.

Args: content_base64: The PDF file bytes in base64. target_format: contasol (APU.ods, default) | a3 | contaplus_csv | contaplus_ascii | csv | quickbooks_iif | quickbooks_csv | xero_csv | norma43 (a .n43 file to import in any program that reads Cuaderno 43). bank_account: The 572 subaccount of the bank (default 57200001). rules / suspense_account / open_items / window_days: As in bank_to_journal. strict_balance: true refuses to produce any file (and charges nothing) unless every row and the closing balance add up. account_ccc: For norma43 when the PDF has no Spanish IBAN: 20-digit CCC for record 11. holder: Account holder name for the Norma 43 header (optional).

Inputs: content_base64 (required), rules, holder, a3_format, +15 more. Returns: object

pricingShow tool pricesA
Read-only
Inspect

Credit price of each tool and where to buy credits. Free.

Inputs: no named parameters. Returns: object

resize_accountResize PGC subaccountA
Read-onlyIdempotent
Inspect

Resize or expand a Spanish subaccount code. Free. '430.1' -> '43000001'; 4300001 (7) -> 43000001 (8).

Inputs: digits (required), account (required), split. Returns: object

validate_journalValidate journal before importA
Read-onlyIdempotent
Inspect

Check a journal file the way A3/ContaPlus check it on import, before you send it.

Reports unbalanced entries (with the difference), lines with both or neither debit and credit, non-numeric accounts or accounts outside PGC groups 1-9, mixed subaccount lengths and dates outside fiscal_year. valid is false when any error is found. include_entries returns the first 50 entries parsed. QuickBooks/Xero files are checked against their own chart (any non-empty account), not the PGC.

Inputs: content, column_map, date_style, fiscal_year, +4 more. Returns: object

Tool Schema Changelog

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

Loading tool schema changelog…

    TDQS

    A3.7/5.0

    Scored across 11 tools

    Disambiguation4/5

    Each tool has a distinct input source (existing file, composed entries, bank statement file, bank PDF, invoice figures), so the journal-producing tools are mostly separable. However, bank_statement_csv vs convert_journal's `csv` target, and pdf_bank_to_journal vs bank_to_journal, are close enough that an agent could pick wrong; resize_account also duplicates a convert_journal argument.

    Naming Consistency4/5

    The core domain tools follow a clean verb_noun pattern (convert_journal, validate_journal, build_journal, bank_to_journal, detect_format, resize_account). Minor deviations: bank_statement_csv is a noun phrase and the meta tools pricing / credits_balance are noun-only, breaking the pattern slightly.

    Tool Count5/5

    11 tools is well within the sweet spot, and every tool maps to a real step in the Spanish accounting import workflow (detect, validate, convert, build, bank, invoices, plus free utility/credit tools). No filler tools are present.

    Completeness4/5

    The surface covers detection, validation, format conversion, banking, invoicing, and account helpers, which is strong lifecycle coverage for a conversion server. The notable gap is a full structured-extraction/parse tool (validate_journal only returns the first 50 entries), so reading an arbitrary journal back into data is a partial dead end.

    Maintenance

    ActivityNo data
    ResponsivenessOutdated data

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables AI agents to read and write Cynco accounting data, including querying books, creating invoices, reconciling transactions, and generating financial reports.
      8 npm
      1
      MIT
    • A
      license
      A
      quality
      D
      maintenance
      Enables AI agents to interact with a double-entry ledger, offering tools for account management, balanced journal entries, balance queries, trial balance, and penny-perfect allocation. Built with safety by construction: no update/delete tools, idempotent posting, and an append-only journal.
      7
      MIT
    • A
      license
      A
      quality
      B
      maintenance
      Enables AI agents to issue, correct, and register legally compliant Spanish electronic invoices with AEAT VeriFactu, supporting F1/F2 types, R1–R5 correctives, and NIF validation from Claude, ChatGPT, Cursor, or VS Code.
      136
      480 npm
      2
      MIT
    • A
      license
      A
      quality
      B
      maintenance
      Enables AI assistants to interact with Quipu accounting data via natural language, including invoicing, expenses, contacts, and Spanish VAT reporting.
      18
      49 npm
      MIT