Pokaždé, když mi přijde faktura nebo pokyn k vkladu od brokera, dělám tu samou hloupost: ručně opisuju číslo účtu, částku a variabilní symbol do bankovní aplikace. Jedna přehozená číslice a peníze letí cizímu člověku. České faktury sice čím dál častěji nesou QR Platbu, kterou stačí naskenovat — ale zdaleka ne všechny. A tak jsem si jedno odpoledne řekl, že to vyřeším.
Výsledek je qr.cz-agents.dev — bezplatný generátor evropských platebních QR kódů (český SPAYD i evropský EPC/GiroCode), a zároveň stejná logika jako MCP server @czagents/payqr — tedy rozhraní, kterému AI agenti (třeba Claude) rozumí a umí ho použít. Je to nejnovější kousek do cz-agents — sady MCP serverů nad českými veřejnými daty (ARES, ČNB, sankce, insolvence), o které jsem psal dřív. Tohle je upřímná případová studie: co bylo snadné, co mě překvapilo, a jedna lekce, kterou jsem nečekal.
Co bylo snadné
Platební formáty jsou jen řetězce. SPAYD je SPD*1.0*ACC:CZ65…*AM:1250.00*CC:CZK*X-VS:…, EPC/GiroCode je dvanáct řádků definovaných normou EPC069-12. Validace IBANu je trik na deset řádků (mod-97). Generování je tedy deterministické — žádná AI, žádné externí API, žádné překvapení v zaokrouhlení. Celá webová aplikace běží v prohlížeči: OCR i čtení QR (tesseract.js a jsQR) zpracují obrázek lokálně, nic se nikam neposílá. To je u platebních údajů zásadní — slib „váš obrázek nikdy neopustí vaše zařízení" jsem mohl napsat jen proto, že je doslova pravda (žádná serverová část).
Co mě překvapilo (ta lekce)
Stejnou logiku jsem vystavil jako MCP server, aby AI agent (třeba Claude) uměl vzít fakturu, přečíst z ní údaje a vygenerovat platební QR. A tady přišel den plný iterací.
MCP server umí vrátit obrázek. Jenže ukázalo se, že Claude Desktop obrázky, které nástroj vrací jako výsledek volání, spolehlivě nevykresluje, a model zároveň neumí přenést několikakilobajtový base64 řetězec do souboru, aniž by ho cestou poškodil. Výsledek: místo QR kódu jen poškozený obrázek — v chatu pár nesmyslných pixelů. Zkoušel jsem to ladit instrukcemi — marně, protože nešlo o opatrnost, ale o princip: jazykové modely nejsou stavěné na bezchybné opisování dlouhých náhodných řetězců, takže v 2 KB tokenů dřív nebo později udělají chybu.
Správné řešení nebylo „nauč model být opatrnější", ale dostat model z kritické cesty:
- Server si svůj QR sám ověří — vygenerovaný PNG znovu dekóduje a porovná s původními daty (
self_verified). Model už nic neověřuje. - Obrázek se nabídne jako krátká, dočasná URL — ne base64 k přepisu. URL nejde zkomolit.
- Sdílený odkaz na web je neprůhledný (
?p=<id>) — žádná platební data v URL, takže nic neúniká do historie ani logů a odkaz nejde podvrhnout.
Lekce, kterou si odnáším: u nástroje, kde jedna chyba znamená špatně poslané peníze, patří verifikace na server a deterministickou vrstvu, ne do instrukcí pro model.
A není to o QR. Je to obecný vzor pro AI nástroje: model navrhuje, deterministická vrstva ověřuje a nese odpovědnost za korektnost. Čím dražší je chyba, tím víc rozhodování patří mimo model — do kódu, který selže předvídatelně.
Funguje to?
Praktický test: poslal jsem reálný vklad přes QR vygenerovaný tímhle nástrojem. Banka kód přečetla, předvyplnila platbu, a příjemce (broker) potvrdil, že peníze dorazily na správný účet. Ne demo — reálné peníze tam, kam měly.
Kde to žije
Nástroj běží na qr.cz-agents.dev — IBAN nebo snímek obrazovky, vše v prohlížeči, zdarma a bez účtu. Kód je open-source (MIT) na GitHubu, jako součást širší sady cz-agents.
Co bych přidal příště: dávkové generování QR z více faktur naráz a uložení šablon příjemců. Zatím to ale dělá přesně to, kvůli čemu vzniklo. Nejlepší věci vznikají z vlastního otravného problému — tenhle vyřešil ten můj.