Home · Guides

Put a SEPA payment QR code on an invoice from chat

A banking app that scans a code and fills in the transfer form is not doing anything clever with a picture: it is reading eleven lines of plain text in a fixed order, a format called EPC069-12, also known as the EPC QR code or GiroCode. The MCP Barcode server builds that text itself, checks the IBAN before it draws anything, and can pull the beneficiary's IBAN and name straight from the same shared business profile the invoice server already has. "Put a payment QR code on invoice INV-2026-0007" is one call.

Install

claude mcp add barcode -- npx -y @theluckystrike/mcp-barcode

Cursor, Claude Desktop and the rest take the same block, under their own config file. See the setup pages for the exact path and key per client.

The eleven EPC069-12 fields, in order

The record is not a struct with named keys; it is plain text lines joined by newlines, and a scanner reads field N as whatever sits on line N. Getting one field wrong or leaving one out of order corrupts every field after it. The server writes exactly this, dropping only the trailing fields that are empty, since the specification allows the record to stop early:

BCD                    Service tag, fixed
002                    Version. 002, not 001: 001 makes the BIC mandatory, and no
                       euro-area bank has needed a BIC for SEPA since Feb 2016
1                      Character set, 1 = UTF-8
SCT                    Identification: SEPA Credit Transfer, fixed
<BIC>                 Optional under version 002; blank is valid
<name>                Beneficiary name, max 70 characters
<IBAN>                Validated before this line is written
EUR<amount>           EUR plus the amount with two decimals, e.g. EUR120.50; blank
                       if no amount, so the payer types one in
<purpose>             Optional 4-letter ISO 20022 purpose code, e.g. GDDS
<reference>           Structured creditor reference, max 35 chars
<remittance>          Free remittance text, max 140 chars

Reference and remittance are mutually exclusive on purpose: EPC069-12 carries a structured reference or free text, never both, and the tool refuses a call that supplies both rather than guessing which one the banking app should show. The whole record is capped at 331 bytes; a long name plus a long remittance line pushes past it and the tool says by how much, before anything is drawn.

The IBAN is checked with ISO 7064 mod 97, digit by digit

An IBAN carries its own check: move the first four characters to the end, turn every letter into two digits (A=10 through Z=35), and the resulting number must leave a remainder of 1 when divided by 97. A German IBAN is 22 characters, which after that substitution is roughly a 30-digit number; a Maltese one is 31 characters, close to a 47-digit number. Number() in JavaScript cannot hold that many digits without rounding, and a rounded IBAN can still look plausible, so the check here runs digit by digit with a running remainder instead of ever forming the full number. Country and length are checked first against the ISO 13616 registry, since a code that is the wrong length for its country is not an IBAN no matter what its digits say. A single transposed digit fails the mod-97 check and the tool names the remainder it got instead of the 1 it needed, rather than drawing a code that would send a payment to nobody, or to somebody else.

Why the code is EUR only

EPC069-12 encodes a SEPA credit transfer specifically, and a SEPA transfer moves euros between accounts in the SEPA scheme. Passing a non-EUR currency is refused by name, and passing an IBAN from a country outside the SEPA scheme is refused too, even if the IBAN itself checks out, because the format has nowhere to put a currency or an exchange rate: the amount field is euro cents or it is nothing. A dollar or zloty invoice is paid the way it always was, by bank transfer with the account details printed as text; the guide for that is the invoice PDF itself, which never depended on this code to carry a payment.

invoice_payment_qr: the shared profile does the typing

Rather than pass the IBAN and name on every call, invoice_payment_qr reads them from the same shared business profile the invoice server's business_set already wrote once, so an IBAN typed correctly a single time is the IBAN on every invoice's payment code afterward. Give it an invoice number and it reads the total and currency from the invoice server's own store and uses the invoice number as the structured reference, so a client's bank statement shows the exact number to match against the invoice on file:

invoice_payment_qr { invoice_id: "INV-2026-0007" }
-> reads IBAN + name from the shared profile
-> reads total (say EUR 1,697.40) and currency from INV-2026-0007
-> reference defaults to "INV-2026-0007"
-> refuses outright if the invoice is not in EUR

An amount passed alongside an invoice id that disagrees with that invoice's stored total is not silently corrected to match the invoice: the code carries the amount actually given, and the response says so, on the theory that a caller who typed a different number on purpose should get that number, not a second guess.

SVG versus PNG: measured bytes

The same EPC payment record, drawn at five sizes, both ways:

requested sizePNG bytesSVG bytes
128 px1,4812,079
256 px2,1862,079
512 px3,5892,079
1024 px7,5852,081
2048 px21,6882,081

An SVG stores the module grid, not pixels, so its size barely moves with the requested size; a PNG grows without limit as the pixel count grows. The two file types cross at roughly 200 px: below that a PNG is the smaller file, above it the SVG is, and the SVG is also the one that stays sharp when a printer scales an invoice template up. That is why SVG is the free-tier format here rather than a small PNG: for the thing most people do with a payment code, put it on a printed or PDF invoice, SVG is the better file outright, not a limited consolation version of PNG.

Code 128 or EAN-13: which one to ask for

barcode_create draws Code 128, EAN-13, EAN-8 or UPC-A, and the four are not interchangeable. EAN-13, EAN-8 and UPC-A are retail symbologies with a fixed digit count and a check digit defined by the standard: they exist so a barcode scanner at a till can look a number up in a product catalogue, and a short input gets its check digit computed while a full-length input with the wrong check digit is refused rather than redrawn, since silently correcting it would print a label that scans as a different product. Reach for EAN-13 when the thing being labelled already has, or needs, a real retail GTIN meant for another system to recognise. Reach for Code 128 for everything else that just needs to be read back as the string you gave it: an internal shelf location, a work order number, a shipping reference, a serial number, anything alphanumeric or longer than 13 digits, since Code 128 encodes the full ASCII range with no fixed length and no external registry to satisfy.

Free tier and Pro

Free gives 20 codes a calendar month across every tool, SVG output for all of them, and every symbology and QR kind: WiFi, vCard, SEPA payment codes and all four barcode types. Pro ($19 once, or $39 for the whole collection, lifetime) adds PNG output from 32 to 4000 px and barcode_batch for up to 500 rows in one call. Full detail on the MCP Barcode page and the general free versus Pro comparison.

Questions

What exactly does a banking app read when it scans the code?

Eleven plain-text lines joined by newlines, in a fixed order: BCD, version 002, character set, SCT, an optional BIC, the beneficiary name, the IBAN, EUR plus the amount, an optional purpose code, and a structured reference or free remittance text, never both. The whole record is capped at 331 bytes.

Can I put a payment QR code on a USD or PLN invoice?

No. EPC069-12 encodes a SEPA credit transfer, which only moves euros, so a non-EUR currency and an IBAN from outside the SEPA scheme are both refused, even if the IBAN itself is valid. A non-EUR invoice is still paid by bank transfer with the account details printed as plain text.

How is the IBAN checked?

ISO 7064 mod 97, computed digit by digit rather than as one large number, because a long IBAN becomes too many digits for JavaScript's Number type to hold without rounding into a different, still-plausible value. Country and length are checked against the ISO 13616 registry first.

Do I have to type my IBAN into every payment code?

No, if you use invoice_payment_qr. It reads the IBAN and name from the shared business profile the invoice server's business_set already wrote, and the amount, currency and reference from the invoice itself when you give it an invoice number.

Should I use EAN-13 or Code 128 for an internal label?

Code 128, for almost anything that is not a retail product needing a real GTIN. It has no fixed length or check-digit standard tying it to a catalogue, and it encodes the full ASCII range, so a work order number, shelf location or serial number all fit it directly. EAN-13 is for a number meant to be looked up in a retail system.

Related

All MCP servers and prices · All guides