eqlx.aiOpen research

eqlx.org / eqlx-ebelge

Python library · MCP server · v0.1 · Apache-2.0

Read e-Fatura and e-Defter files. Catch what does not add up.

Turkish companies exchange invoices (e-Fatura) and keep their books (e-Defter) as XML files in the format of GİB, the tax authority. eqlx-ebelge reads those files on your machine, turns them into clean data and a trial balance, and lists what does not add up. AI agents use it read-only.

What goes in, what comes out

No model inside, no network access. Same files, same answer.

You give

  • e-Fatura and e-Arşiv invoices (UBL-TR XML)
  • e-Defter journals and ledgers (XBRL GL XML)
  • as files, folders or ZIP archives

eqlx-ebelge checks

  • the check digit of every tax id
  • lines, VAT and the amount to pay
  • the same invoice appearing twice
  • debits against credits in every journal entry

You get

  • one clean row per invoice
  • a trial balance (mizan) from the journal
  • a list of findings, each with its rule and file

One folder, start to finish

The ten made-up files that ship with the tool (ebelge sample demo), checked with ebelge check demo.

1You give a folder

Nine invoices and one month of the journal, the book that lists every accounting entry.

  • fatura_01.xml … fatura_07.xml 7 invoices
  • fatura_08_toplam_hatali.xml invoice
  • fatura_09_vkn_hatali.xml invoice
  • edefter_2026_10_yevmiye.xml journal, 7 entries

2The tool reads each invoice

Invoice EQX2026000000008, as it comes out of the XML.

Seller tax id (VKN)4477127820
Line 1: steel profile, 10 × 185.401,854.00
Line 2: installation, 2,276 less 227.60 discount2,048.40
VAT (KDV) at 20 %780.48
Total with VAT4,682.88
Amount to pay, as written99,999.99

3Is the tax id a possible one?

A VKN is a company's 10-digit tax number; its last digit is computed from the first nine.

4477127820seller on 8 invoicespasses
4477127821seller on invoice 9fails

Same seller name, one digit apart.

4Does the invoice add up?

Invoice 8: the amount to pay, recomputed from the lines and VAT, against what is written.

Lines
3,902.40
VAT
780.48
Recomputed
4,682.88
Written
99,999.99
gap 95,317.11 error: payable

5Is any invoice there twice?

Compared across all files, not one by one.

Invoice 2EQX20260000000022026-10-07 · 10,140.12fatura_02.xml
Invoice 7EQX20260000000072026-10-07 · 10,140.12fatura_07.xml
warning same seller, buyer, date and amount

6Does the journal balance?

In every entry, debits must equal credits. All 7 entries of October, added up:

Debits
864,500.00
Credits
864,500.00
7 of 7 entries balance: no finding
3findings · 2 errors, 1 warning

What comes back

Invoice 8 states 99,999.99 to pay where the totals give 4,682.88. Invoice 9 carries seller VKN 4477127821, which fails its check digit. Invoices 2 and 7 look like the same invoice under two numbers.

exit code 1

Each finding names its rule and its file. The command ends with code 1 when there is an error, so a pipeline can stop on it.

The result at a glance

The same demo folder: 10 documents, 9 invoices, 1 journal file with 7 entries.

5 of 9 invoices pass every check; 4 need a second look.

No findingWarning · possible duplicate pairError · wrong amount to pay, invalid tax id

The trial balance from the journal

A trial balance (mizan) is the list of accounts with what each one holds. ebelge mizan demo builds it from the entries.

Debit balances

What the company holds and has spent.

102 Banks
550,000
153 Goods
68,000
621 Cost of goods sold
52,000
120 Customers
30,000
191 VAT paid
24,000
770 Overheads
8,500
100 Cash
1,500
Total 734,000.00

Credit balances

Where the money came from.

500 Capital
500,000
320 Suppliers
144,000
600 Sales
75,000
391 VAT charged
15,000
Total 734,000.00

Both sides come to 734,000.00. Account names are shortened into English here; the tool returns the Turkish names from the file (KASA, BANKALAR, …).

Everything it checks

Tax idsA VKN (company) or TCKN (person) that fails its check digit, has the wrong length, or is missing.
Invoice arithmeticLines against the total, VAT against its rate, the amount to pay against the totals less tevkifat (VAT withheld by the buyer) and stopaj (tax withheld at source).
DuplicatesThe same ETTN (the invoice's unique id) twice; the same seller and number twice; the same seller, buyer, date and amount under different numbers.
Journal entriesDebits and credits that differ, header totals that disagree with the lines, counters that repeat or skip, dates outside the period.
FilesMalformed or unsafe XML, oversized or over-compressed ZIPs, documents that are not invoices or ledgers.

How an agent uses it

The agent decides what to look at. The tool reads the XML and does the arithmetic. It sees one folder and writes nothing.

Point it at a folderPaths outside it, .. and symlinks that lead out are refused
list_documentsWhat is in the folder and its ZIPs
checkEvery check, duplicates across all files
read_invoicesParties, lines, taxes and totals as data
trial_balanceThe mizan, by main or sub-account
claude mcp add ebelge -- ebelge mcp --root /path/to/invoices

Asked in Turkish to check the demo folder, Claude called check and answered with a table of the three findings above. It also noticed that the invalid VKN is one digit away from the seller's real one, a likely typo.

How it was tested

Against the public sample packages of GİB for e-Fatura, e-Arşiv (invoices to non-registered buyers) and e-Defter, and against made-up documents.

✓0 false alarmson GİB's public e-Defter samples
✓Real findings onlyon GİB's e-Fatura samples: each one is an inconsistency in the sample
✓62 testsincluding malicious XML, ZIP bombs and attempts to read outside the folder
✓2 per checkone made-up document that triggers it, one that does not
✓Hostile XML refusedentity expansion and external entities
✓ZIP limitsread in memory; size, file count and compression ratio capped

What the GİB samples taught it

The first run on GİB's packages showed readings that were missing. They are now handled and tested.

Exempt taxesinvoices that show a tax but do not charge it
Withholdingtax the buyer keeps back and pays to the state
Market invoiceswholesale-market (hal) invoices with their own charges
General ledgerthe kebir, read account by account

What it does not do

No signature checkIt does not verify the electronic signature or GİB seal. A file can pass every check and still be forged.
No GİB accessIt cannot tell whether an invoice was registered, cancelled or rejected.
Signals, not verdictsA warning is a reason to look, not proof of fraud.
Not GİB's own validationThe checks are arithmetic and structural; GİB's schema packages are not bundled.
pip install "eqlx-ebelge[mcp]"

ebelge sample demo     # ten made-up files to try it on
ebelge check demo      # every check
ebelge mizan demo      # trial balance from the journal

Local only: no network access, no telemetry, one dependency for the core.