uol-mcp 0.0.0-stage → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +62 -0
- package/LICENSE +21 -0
- package/README.cs.md +143 -0
- package/README.md +281 -2
- package/dist/config.js +244 -0
- package/dist/config.js.map +1 -0
- package/dist/domain/audit.js +23 -0
- package/dist/domain/audit.js.map +1 -0
- package/dist/domain/bank.js +39 -0
- package/dist/domain/bank.js.map +1 -0
- package/dist/domain/company.js +12 -0
- package/dist/domain/company.js.map +1 -0
- package/dist/domain/contact-names.js +79 -0
- package/dist/domain/contact-names.js.map +1 -0
- package/dist/domain/files.js +36 -0
- package/dist/domain/files.js.map +1 -0
- package/dist/domain/ledger.js +92 -0
- package/dist/domain/ledger.js.map +1 -0
- package/dist/domain/paging.js +17 -0
- package/dist/domain/paging.js.map +1 -0
- package/dist/domain/receivables.js +109 -0
- package/dist/domain/receivables.js.map +1 -0
- package/dist/domain/uploads.js +60 -0
- package/dist/domain/uploads.js.map +1 -0
- package/dist/domain/vat.js +109 -0
- package/dist/domain/vat.js.map +1 -0
- package/dist/http.js +168 -0
- package/dist/http.js.map +1 -0
- package/dist/index.js +128 -0
- package/dist/index.js.map +1 -0
- package/dist/instructions.js +16 -0
- package/dist/instructions.js.map +1 -0
- package/dist/prompts.js +60 -0
- package/dist/prompts.js.map +1 -0
- package/dist/resources.js +57 -0
- package/dist/resources.js.map +1 -0
- package/dist/server.js +103 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/accounts.js +33 -0
- package/dist/tools/accounts.js.map +1 -0
- package/dist/tools/banking.js +105 -0
- package/dist/tools/banking.js.map +1 -0
- package/dist/tools/company.js +96 -0
- package/dist/tools/company.js.map +1 -0
- package/dist/tools/contacts.js +131 -0
- package/dist/tools/contacts.js.map +1 -0
- package/dist/tools/context.js +82 -0
- package/dist/tools/context.js.map +1 -0
- package/dist/tools/destructive.js +96 -0
- package/dist/tools/destructive.js.map +1 -0
- package/dist/tools/documents.js +124 -0
- package/dist/tools/documents.js.map +1 -0
- package/dist/tools/files.js +20 -0
- package/dist/tools/files.js.map +1 -0
- package/dist/tools/insights.js +270 -0
- package/dist/tools/insights.js.map +1 -0
- package/dist/tools/invoices.js +329 -0
- package/dist/tools/invoices.js.map +1 -0
- package/dist/tools/ledger.js +138 -0
- package/dist/tools/ledger.js.map +1 -0
- package/dist/tools/raw.js +47 -0
- package/dist/tools/raw.js.map +1 -0
- package/dist/tools/receivables.js +84 -0
- package/dist/tools/receivables.js.map +1 -0
- package/dist/tools/schemas.js +41 -0
- package/dist/tools/schemas.js.map +1 -0
- package/dist/tools/warehouse.js +181 -0
- package/dist/tools/warehouse.js.map +1 -0
- package/dist/tools/write-support.js +34 -0
- package/dist/tools/write-support.js.map +1 -0
- package/dist/tools/writes-documents.js +117 -0
- package/dist/tools/writes-documents.js.map +1 -0
- package/dist/tools/writes-records.js +324 -0
- package/dist/tools/writes-records.js.map +1 -0
- package/dist/tools/writes.js +291 -0
- package/dist/tools/writes.js.map +1 -0
- package/dist/uol/client.js +61 -0
- package/dist/uol/client.js.map +1 -0
- package/dist/uol/errors.js +50 -0
- package/dist/uol/errors.js.map +1 -0
- package/dist/uol/http.js +213 -0
- package/dist/uol/http.js.map +1 -0
- package/dist/uol/normalize.js +117 -0
- package/dist/uol/normalize.js.map +1 -0
- package/dist/uol/rate-limit.js +55 -0
- package/dist/uol/rate-limit.js.map +1 -0
- package/package.json +57 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to uol-mcp. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
4
|
+
and the project uses [Semantic Versioning](https://semver.org/).
|
|
5
|
+
|
|
6
|
+
## [Unreleased]
|
|
7
|
+
|
|
8
|
+
## [0.4.1] — 2026-11-05
|
|
9
|
+
|
|
10
|
+
### Security
|
|
11
|
+
|
|
12
|
+
- Ids are validated before they go into a URL path. `..` used to pass, so
|
|
13
|
+
`untag_uploaded_document(tag_id="..")` became `DELETE /uploaded_documents/<id>/` — a tag removal
|
|
14
|
+
that deleted the whole document.
|
|
15
|
+
- The HTTP server no longer reads `file_path` uploads from its own disk unless `UOL_UPLOAD_DIRS` is set
|
|
16
|
+
explicitly; remote callers send `content_base64`.
|
|
17
|
+
- Download file names built from ids are sanitised too; downloads never replace an existing file
|
|
18
|
+
(a taken name gets a ` (1)` suffix) and are saved readable by the owner only.
|
|
19
|
+
- An invalid `UOL_PROFILES_FILE` is reported without quoting the file, which could contain a token.
|
|
20
|
+
- The Docker image no longer ships npm, yarn and corepack (the server needs only node), and the base
|
|
21
|
+
image is pinned by digest.
|
|
22
|
+
- Release workflow hardened: publishing waits for approval on the `release` environment, actions are
|
|
23
|
+
pinned to commit SHAs, jobs with publishing rights don't run dependency install scripts, the
|
|
24
|
+
`mcp-publisher` download is checked against its release checksum, and an existing release asset is
|
|
25
|
+
never overwritten.
|
|
26
|
+
- CI scans: `npm audit`, Trivy (image), CodeQL, dependency review on pull requests, Dependabot.
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
|
|
30
|
+
- Supplier and customer names were missing on long invoice lists: names were looked up one contact
|
|
31
|
+
at a time, at most 15 per call. Long lists now read the contact list first.
|
|
32
|
+
- `get_business_snapshot` lists sections that were read only partly in `incomplete`, and
|
|
33
|
+
`get_bank_balances` returns `truncated`, as the other summaries already did.
|
|
34
|
+
|
|
35
|
+
## [0.4.0] — 2026-11-05
|
|
36
|
+
|
|
37
|
+
First public release (0.1–0.3 were internal milestones).
|
|
38
|
+
|
|
39
|
+
### Added
|
|
40
|
+
|
|
41
|
+
- **Read tools** (default): company, codebooks, sales and purchase invoices with payment status,
|
|
42
|
+
receivables with totals per currency, PDF / ISDOC export, contacts, uploaded documents, `api_get`.
|
|
43
|
+
- **Insights**: financial overview from the general ledger, VAT per filing period, bank balances, and a
|
|
44
|
+
one-call business snapshot.
|
|
45
|
+
- **Optional toolsets** (`UOL_TOOLSETS`): `ledger`, `banking`, `warehouse`.
|
|
46
|
+
- **Writes** (`UOL_ACCESS=write`): document upload, sales invoices (draft by default, idempotent),
|
|
47
|
+
purchase invoices, contacts, payment demands, the uploaded-document workflow; every write supports
|
|
48
|
+
`dry_run` and can be recorded in `UOL_AUDIT_LOG`.
|
|
49
|
+
- **Destructive tools** (`UOL_ACCESS=full`): delete a draft, storno / back to draft, `api_request`.
|
|
50
|
+
- **Several companies**: `UOL_ACCOUNTS` (all in the client config) or `UOL_PROFILES_FILE`;
|
|
51
|
+
`list_accounts` and an `account` argument on every tool.
|
|
52
|
+
- Czech prompts (`monthly_review`, `vat_check`, `overdue_followup`, `process_inbox`) and the
|
|
53
|
+
`uol://guide` / `uol://company` resources.
|
|
54
|
+
- Streamable HTTP transport: single-tenant with a bearer token, or pass-through with per-request
|
|
55
|
+
credentials.
|
|
56
|
+
- `uol-mcp doctor` checks the configuration (every account).
|
|
57
|
+
- Distribution: npm, GHCR image (amd64 / arm64), Claude Desktop extension (`.mcpb`), MCP Registry
|
|
58
|
+
(`eu.humblecode/uol`).
|
|
59
|
+
|
|
60
|
+
[Unreleased]: https://github.com/jakubbegera/uol-mcp/compare/v0.4.1...HEAD
|
|
61
|
+
[0.4.1]: https://github.com/jakubbegera/uol-mcp/compare/v0.4.0...v0.4.1
|
|
62
|
+
[0.4.0]: https://github.com/jakubbegera/uol-mcp/releases/tag/v0.4.0
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jakub Begera
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.cs.md
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# uol-mcp — návod
|
|
2
|
+
|
|
3
|
+
Napojení [UOL Účetnictví](https://www.uol.cz) na AI asistenty (Claude, Cursor a další klienty
|
|
4
|
+
s podporou [MCP](https://modelcontextprotocol.io)). Asistent pak umí odpovídat nad vaším účetnictvím:
|
|
5
|
+
vydané a přijaté faktury, kdo vám dluží, nahrané doklady, kontakty.
|
|
6
|
+
|
|
7
|
+
> **Neoficiální projekt.** Není spojený s UOL a.s. Komunikuje s veřejným
|
|
8
|
+
> [UOL REST API](https://api.uol.cz/) pomocí vašeho vlastního API tokenu.
|
|
9
|
+
|
|
10
|
+
[English](README.md)
|
|
11
|
+
|
|
12
|
+
**Stav:** verze 0.4, ve výchozím stavu pouze čtení, zápis lze zapnout. Změny jednotlivých verzí
|
|
13
|
+
popisuje [CHANGELOG.md](CHANGELOG.md).
|
|
14
|
+
|
|
15
|
+
## Co umí
|
|
16
|
+
|
|
17
|
+
- **Přehled firmy jedním dotazem:** tento a minulý měsíc, DPH, pohledávky, doklady ke zpracování
|
|
18
|
+
a zůstatky na účtech.
|
|
19
|
+
- **Tržby, náklady a zisk:** po měsících z hlavní knihy, stejně jako dashboard UOL, včetně
|
|
20
|
+
největších nákladových a výnosových účtů.
|
|
21
|
+
- **DPH:** za zdaňovací období, k zaplacení nebo nadměrný odpočet, termín podání; u neuzavřeného
|
|
22
|
+
období jako odhad z faktur.
|
|
23
|
+
- **Zůstatky na účtech:** podle účtů a měn (UOL eviduje měsíční počáteční stavy, ne aktuální zůstatek).
|
|
24
|
+
- **Faktury:** hledání vydaných i přijatých faktur, detail s položkami a DPH, stav úhrady
|
|
25
|
+
u vydaných faktur.
|
|
26
|
+
- **Pohledávky:** kdo vám dluží, kolik a jak dlouho po splatnosti, součty podle měn.
|
|
27
|
+
- **Export:** PDF nebo ISDOC vydané faktury uložené na disk.
|
|
28
|
+
- **Kontakty:** odběratelé a dodavatelé podle názvu, IČO nebo DIČ, s adresami a bankovními účty.
|
|
29
|
+
- **Nahrané doklady:** co čeká na zpracování, stažení původního souboru.
|
|
30
|
+
- **Číselníky:** měny, střediska, zakázky, ceníky, vlastní bankovní účty a další.
|
|
31
|
+
|
|
32
|
+
Připravené postupy (v klientech jako příkazy s lomítkem): `monthly_review` (měsíční přehled),
|
|
33
|
+
`vat_check` (kontrola DPH), `overdue_followup` (návrhy upomínek, nic neodesílá) a `process_inbox`
|
|
34
|
+
(projde nahrané doklady).
|
|
35
|
+
|
|
36
|
+
Příklady otázek:
|
|
37
|
+
|
|
38
|
+
- „Jak si letos stojíme?“
|
|
39
|
+
- „Kolik zaplatím DPH za tento kvartál?“
|
|
40
|
+
- „Na čem nejvíc utrácíme?“
|
|
41
|
+
- „Kdo mi dluží víc než 30 dní?“
|
|
42
|
+
- „Je faktura 2026000123 zaplacená?“
|
|
43
|
+
- „Kolik jsme letos fakturovali firmě Alza?“
|
|
44
|
+
- „Stáhni mi PDF poslední vydané faktury.“
|
|
45
|
+
- „Které nahrané doklady ještě účetní nezpracovala?“
|
|
46
|
+
|
|
47
|
+
## Jak získat API token
|
|
48
|
+
|
|
49
|
+
1. Otevřete v UOL stránku API tokenů (adresa `/api_tokens` na vaší instanci, např.
|
|
50
|
+
`https://firma.ucetnictvi.uol.cz/api_tokens`) a vytvořte token.
|
|
51
|
+
2. Uživatel musí mít oprávnění **REST API**. Doporučujeme samostatného uživatele jen s právy,
|
|
52
|
+
která má asistent mít.
|
|
53
|
+
|
|
54
|
+
Název instance (tenant) je první část vaší adresy UOL: `https://firma.ucetnictvi.uol.cz` → `firma`.
|
|
55
|
+
|
|
56
|
+
Chcete si to nejdřív vyzkoušet? S `UOL_TENANT=demo` se použije veřejná DEMO firma od UOL,
|
|
57
|
+
token není potřeba.
|
|
58
|
+
|
|
59
|
+
## Nastavení v Claude Desktop
|
|
60
|
+
|
|
61
|
+
Nastavení → Developer → Edit Config a doplňte:
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"mcpServers": {
|
|
66
|
+
"uol": {
|
|
67
|
+
"command": "npx",
|
|
68
|
+
"args": ["-y", "uol-mcp"],
|
|
69
|
+
"env": {
|
|
70
|
+
"UOL_TENANT": "firma",
|
|
71
|
+
"UOL_EMAIL": "vas@email.cz",
|
|
72
|
+
"UOL_TOKEN": "vas-token"
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Po restartu Claude Desktop zkuste: „Jaké jsou údaje naší firmy v UOL?“
|
|
80
|
+
|
|
81
|
+
Ostatní klienty (Claude Code, Cursor, VS Code), Docker, HTTP server a všechny proměnné prostředí
|
|
82
|
+
popisuje [anglické README](README.md#configuration).
|
|
83
|
+
|
|
84
|
+
## Zápis (volitelný)
|
|
85
|
+
|
|
86
|
+
S `UOL_ACCESS=write` (v Claude Desktop rozšíření pole „Access“ = `write`) asistent umí navíc:
|
|
87
|
+
|
|
88
|
+
- **nahrát doklad** (PDF) účetní do UOL, a to jen ze složek Stažené soubory, Plocha a Dokumenty
|
|
89
|
+
(nebo ze složek v `UOL_UPLOAD_DIRS`);
|
|
90
|
+
- **vystavit fakturu** existujícímu kontaktu, standardně jako koncept;
|
|
91
|
+
- **upravit nebo vystavit koncept faktury**; už vystavenou fakturu UOL měnit nedovolí;
|
|
92
|
+
- **zaevidovat přijatou fakturu**, **založit nebo upravit kontakt** (s kontrolou duplicitního IČO);
|
|
93
|
+
- **vytvořit upomínku** k neuhrazeným fakturám jednoho odběratele (nic se neodesílá);
|
|
94
|
+
- **zpracovat nahrané doklady**: označit jako zpracované, spárovat s fakturou, přidat štítek.
|
|
95
|
+
|
|
96
|
+
S `UOL_ACCESS=full` navíc smazání konceptu faktury, storno nebo vrácení vystavené faktury do konceptu
|
|
97
|
+
a obecný zápis do libovolného endpointu.
|
|
98
|
+
|
|
99
|
+
Před každým zápisem si asistent nechá vše ukázat nanečisto a klient vás požádá o souhlas.
|
|
100
|
+
Opakované vytvoření stejné faktury nevznikne dvakrát.
|
|
101
|
+
|
|
102
|
+
## Více firem (pro účetní)
|
|
103
|
+
|
|
104
|
+
Jeden server obslouží víc klientských firem. Účty vyjmenujete v `UOL_ACCOUNTS` a každému dáte
|
|
105
|
+
vlastní proměnné, vše přímo v konfiguraci klienta:
|
|
106
|
+
|
|
107
|
+
```json
|
|
108
|
+
"env": {
|
|
109
|
+
"UOL_ACCOUNTS": "firma,novak",
|
|
110
|
+
"UOL_ACCOUNT_FIRMA_TENANT": "firma",
|
|
111
|
+
"UOL_ACCOUNT_FIRMA_EMAIL": "vas@email.cz",
|
|
112
|
+
"UOL_ACCOUNT_FIRMA_TOKEN": "token-firmy",
|
|
113
|
+
"UOL_ACCOUNT_NOVAK_TENANT": "novak",
|
|
114
|
+
"UOL_ACCOUNT_NOVAK_EMAIL": "vas@email.cz",
|
|
115
|
+
"UOL_ACCOUNT_NOVAK_TOKEN": "token-novaka",
|
|
116
|
+
"UOL_ACCOUNT_NOVAK_LABEL": "Novák s.r.o."
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Výchozí je první účet. Asistent pak u každého dotazu ví, které firmy se týká, třeba „Kdo dluží firmě
|
|
121
|
+
Novák?“. Tokeny nemusí být v konfiguraci napsané přímo: s 1Password CLI stačí odkazy `op://…`
|
|
122
|
+
a server spustit přes `op run`. Stejné nastavení jde mít i v souboru (`UOL_PROFILES_FILE`), viz
|
|
123
|
+
[anglické README](README.md#several-companies).
|
|
124
|
+
|
|
125
|
+
## Soukromí a bezpečnost
|
|
126
|
+
|
|
127
|
+
- Bez `UOL_ACCESS=write` server data jen čte. Text uvnitř faktur, poznámek a dokladů je pro
|
|
128
|
+
asistenta jen data: před schválením zápisu si zkontrolujte, co navrhuje.
|
|
129
|
+
- Vše, co nástroje vrátí, dostane AI model, který váš klient používá. Účetnictví obsahuje osobní
|
|
130
|
+
údaje kontaktů a zaměstnanců; zvolte si takový tarif, s jehož podmínkami souhlasíte.
|
|
131
|
+
- Přihlašovací údaje se posílají jen na `https://*.uol.cz` a nikdy se nezapisují do logů.
|
|
132
|
+
- Stažené soubory se ukládají jen do složky `UOL_DOWNLOAD_DIR` (výchozí `~/Downloads/uol-mcp`),
|
|
133
|
+
čitelné jen pro vás, a nikdy nepřepíšou existující soubor.
|
|
134
|
+
|
|
135
|
+
## Zapojte se
|
|
136
|
+
|
|
137
|
+
Příspěvky jsou vítané: chyby, zvláštnosti API, nové nástroje i úpravy dokumentace. Postup popisuje
|
|
138
|
+
[CONTRIBUTING.md](CONTRIBUTING.md) (anglicky). Bezpečnostní problémy prosím hlaste neveřejně podle
|
|
139
|
+
[SECURITY.md](SECURITY.md).
|
|
140
|
+
|
|
141
|
+
## Licence
|
|
142
|
+
|
|
143
|
+
[MIT](LICENSE)
|
package/README.md
CHANGED
|
@@ -1,3 +1,282 @@
|
|
|
1
|
-
#
|
|
1
|
+
# uol-mcp
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[Model Context Protocol](https://modelcontextprotocol.io) server for
|
|
4
|
+
[UOL Účetnictví](https://www.uol.cz) — ask Claude, Cursor or any other MCP client about your
|
|
5
|
+
bookkeeping: issued and received invoices, who owes you money, uploaded documents, contacts.
|
|
6
|
+
|
|
7
|
+
> **Unofficial.** Not affiliated with or endorsed by UOL a.s. It talks to the public
|
|
8
|
+
> [UOL REST API](https://api.uol.cz/) with your own API token.
|
|
9
|
+
|
|
10
|
+
[Česky](README.cs.md)
|
|
11
|
+
|
|
12
|
+
**Status:** v0.4 — read-only by default, opt-in writes. What changed: [CHANGELOG.md](CHANGELOG.md).
|
|
13
|
+
|
|
14
|
+
## What it can do
|
|
15
|
+
|
|
16
|
+
| Tool | Answers |
|
|
17
|
+
|---|---|
|
|
18
|
+
| `get_business_snapshot` | How the company is doing, in one call: this month vs last, VAT, receivables, documents to process, bank |
|
|
19
|
+
| `get_financial_overview` | Revenue, expenses and profit per month from the general ledger, largest accounts |
|
|
20
|
+
| `get_vat_overview` | VAT per filing period: to pay or excess deduction, due date, final or estimate |
|
|
21
|
+
| `get_bank_balances` | Bank balances per account and currency (UOL keeps monthly snapshots) |
|
|
22
|
+
| `get_company` | Company name, IČO, DIČ, address, VAT filing period; doubles as a connection check |
|
|
23
|
+
| `search_sales_invoices`, `get_sales_invoice` | Issued invoices with line items, VAT and payment status |
|
|
24
|
+
| `search_purchase_invoices`, `get_purchase_invoice` | Received invoices |
|
|
25
|
+
| `list_receivables` | Who owes you, how much, how long overdue — totals per currency |
|
|
26
|
+
| `export_sales_invoice` | PDF or ISDOC of an issued invoice, saved to disk (ISDOC is also returned as XML) |
|
|
27
|
+
| `search_contacts`, `get_contact` | Customers and suppliers by name, IČO or DIČ, with addresses and bank accounts |
|
|
28
|
+
| `list_uploaded_documents`, `get_uploaded_document`, `download_uploaded_document` | Documents uploaded for the accountant, their state and files |
|
|
29
|
+
| `list_codebook` | Currencies, departments, contracts, price lists, own bank accounts, … |
|
|
30
|
+
| `api_get` | Read-only GET of any other `/v1/…` endpoint |
|
|
31
|
+
|
|
32
|
+
Example questions: *"Jak si letos stojíme?"*, *"Kolik zaplatím DPH za tento kvartál?"*,
|
|
33
|
+
*"Kdo mi dluží víc než 30 dní?"*, *"Je faktura 2026000123 zaplacená?"*,
|
|
34
|
+
*"Na čem nejvíc utrácíme?"*, *"Stáhni mi PDF poslední vydané faktury."*
|
|
35
|
+
|
|
36
|
+
More read tools are available as opt-in toolsets (`UOL_TOOLSETS`): `ledger` (general-ledger postings, internal
|
|
37
|
+
documents), `banking` (bank movements, petty-cash documents) and `warehouse` (products, stock levels, orders).
|
|
38
|
+
|
|
39
|
+
Ready-made prompts (slash commands in most clients): `monthly_review`, `vat_check`,
|
|
40
|
+
`overdue_followup` (drafts reminders, sends nothing), `process_inbox`. The `uol://guide` resource
|
|
41
|
+
explains the domain to the model.
|
|
42
|
+
|
|
43
|
+
The server knows the API's quirks: invoice status `valid` means *draft*, payment status exists only
|
|
44
|
+
for issued invoices, credit notes come with positive amounts, revenue and expenses have to be read
|
|
45
|
+
from the ledger (excluding year-end closing entries), purchase invoices ignore issue-date filters,
|
|
46
|
+
files have three different download shapes, and the rate limit (30 requests / 10 s) is respected
|
|
47
|
+
client-side. See [docs/DESIGN.md](docs/DESIGN.md).
|
|
48
|
+
|
|
49
|
+
## Getting an API token
|
|
50
|
+
|
|
51
|
+
1. Open the API tokens page of your UOL tenant (path `/api_tokens`, e.g.
|
|
52
|
+
`https://firma.ucetnictvi.uol.cz/api_tokens`) and create a token.
|
|
53
|
+
2. The UOL user needs the **REST API** permission. A dedicated user with only the rights you want
|
|
54
|
+
the assistant to have is a good idea.
|
|
55
|
+
|
|
56
|
+
Your tenant is the first part of your UOL address: `https://firma.ucetnictvi.uol.cz` → `firma`.
|
|
57
|
+
|
|
58
|
+
Want to try it first? `UOL_TENANT=demo` uses UOL's public DEMO company, no token needed.
|
|
59
|
+
|
|
60
|
+
## Configuration
|
|
61
|
+
|
|
62
|
+
| Variable | Meaning |
|
|
63
|
+
|---|---|
|
|
64
|
+
| `UOL_TENANT` | `demo`, your tenant name (`firma`), a host prefix (`firma.sandbox`) or the full `https://….uol.cz` URL |
|
|
65
|
+
| `UOL_EMAIL` | E-mail you log into UOL with |
|
|
66
|
+
| `UOL_TOKEN` | API token |
|
|
67
|
+
| `UOL_DOWNLOAD_DIR` | Where exported and downloaded files go (default `~/Downloads/uol-mcp`) |
|
|
68
|
+
| `UOL_TOOLSETS` | Comma-separated: `core`, `insights` (these two are the default), `ledger`, `banking`, `warehouse`, or `all` |
|
|
69
|
+
| `UOL_ACCESS` | `read` (default), `write` or `full` — see [Writing](#writing-opt-in) |
|
|
70
|
+
| `UOL_ACCOUNTS`, `UOL_DEFAULT_ACCOUNT` | Several companies in one server — see [Several companies](#several-companies) |
|
|
71
|
+
| `UOL_PROFILES_FILE` | The same from a JSON file |
|
|
72
|
+
| `UOL_UPLOAD_DIRS` | Folders `upload_document` may read from (default `~/Downloads`, `~/Desktop`, `~/Documents`; `:`-separated, `;` on Windows). The HTTP server has no default: without this variable it accepts only `content_base64` |
|
|
73
|
+
| `UOL_AUDIT_LOG` | File that records every write as a JSON line |
|
|
74
|
+
| `UOL_TIMEOUT_MS` | Timeout of one UOL request (default `30000`) |
|
|
75
|
+
| `UOL_DEBUG` | `1` logs requests to stderr (never credentials) |
|
|
76
|
+
|
|
77
|
+
### Claude Desktop
|
|
78
|
+
|
|
79
|
+
Settings → Developer → Edit Config, then add:
|
|
80
|
+
|
|
81
|
+
```json
|
|
82
|
+
{
|
|
83
|
+
"mcpServers": {
|
|
84
|
+
"uol": {
|
|
85
|
+
"command": "npx",
|
|
86
|
+
"args": ["-y", "uol-mcp"],
|
|
87
|
+
"env": {
|
|
88
|
+
"UOL_TENANT": "firma",
|
|
89
|
+
"UOL_EMAIL": "you@example.com",
|
|
90
|
+
"UOL_TOKEN": "your-token"
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Claude Code
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
claude mcp add uol -e UOL_TENANT=firma -e UOL_EMAIL=you@example.com -e UOL_TOKEN=your-token -- npx -y uol-mcp
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Cursor / VS Code
|
|
104
|
+
|
|
105
|
+
Cursor (`.cursor/mcp.json`) uses the same `mcpServers` block as Claude Desktop. VS Code
|
|
106
|
+
(`.vscode/mcp.json`):
|
|
107
|
+
|
|
108
|
+
```json
|
|
109
|
+
{
|
|
110
|
+
"servers": {
|
|
111
|
+
"uol": {
|
|
112
|
+
"type": "stdio",
|
|
113
|
+
"command": "npx",
|
|
114
|
+
"args": ["-y", "uol-mcp"],
|
|
115
|
+
"env": { "UOL_TENANT": "firma", "UOL_EMAIL": "you@example.com", "UOL_TOKEN": "your-token" }
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Docker
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
docker run -i --rm -e UOL_TENANT=firma -e UOL_EMAIL=you@example.com -e UOL_TOKEN=your-token -v "$HOME/Downloads/uol-mcp:/data" ghcr.io/jakubbegera/uol-mcp
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Exported and downloaded files are written to `/data` inside the container; the `-v` mount keeps them.
|
|
128
|
+
In an MCP client config, use `docker` as the command and the rest as `args`.
|
|
129
|
+
|
|
130
|
+
### Claude Desktop extension
|
|
131
|
+
|
|
132
|
+
Each release ships `uol-mcp.mcpb`. Open it to install, then fill in tenant, e-mail and token in the
|
|
133
|
+
form; the token is stored as a secret. `bash scripts/build-mcpb.sh` builds the bundle from source.
|
|
134
|
+
|
|
135
|
+
### HTTP server (self-hosting)
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
MCP_TRANSPORT=http MCP_AUTH_TOKEN=change-me UOL_TENANT=firma UOL_EMAIL=you@example.com UOL_TOKEN=your-token npx -y uol-mcp
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
The endpoint is `http://127.0.0.1:3000/mcp` (`HOST`, `PORT` to change; `/health` for probes).
|
|
142
|
+
Two modes:
|
|
143
|
+
|
|
144
|
+
- **One tenant**: UOL credentials in the server's env. Clients must send `Authorization: Bearer
|
|
145
|
+
<MCP_AUTH_TOKEN>`; the server refuses to start without the token.
|
|
146
|
+
- **Pass-through**: no UOL credentials in the env. Each client sends its own `X-UOL-Tenant`,
|
|
147
|
+
`X-UOL-Email` and `X-UOL-Token` headers with every request; the server stores nothing.
|
|
148
|
+
`MCP_AUTH_TOKEN` is optional.
|
|
149
|
+
|
|
150
|
+
Over HTTP, exported invoices and downloaded documents come back inside the tool result instead of
|
|
151
|
+
being saved on the server, and `upload_document` takes the file as `content_base64` — it reads no
|
|
152
|
+
paths on the server unless `UOL_UPLOAD_DIRS` is set. In Docker, bind to all interfaces and publish the
|
|
153
|
+
port: `docker run -p 3000:3000 -e MCP_TRANSPORT=http -e HOST=0.0.0.0 -e MCP_ALLOWED_HOSTS=mcp.example.com …`.
|
|
154
|
+
|
|
155
|
+
| Variable | Meaning |
|
|
156
|
+
|---|---|
|
|
157
|
+
| `MCP_TRANSPORT` | `http` starts the HTTP server (same as `--http`) |
|
|
158
|
+
| `HOST`, `PORT` | Bind address, default `127.0.0.1:3000` |
|
|
159
|
+
| `MCP_AUTH_TOKEN` | Bearer token clients must send; required in one-tenant mode, recommended in pass-through |
|
|
160
|
+
| `MCP_ALLOWED_HOSTS` | Accepted `Host` names (comma-separated) when not bound to localhost |
|
|
161
|
+
| `MCP_ALLOWED_ORIGINS` | Browser origins allowed to call the endpoint (none by default) |
|
|
162
|
+
|
|
163
|
+
The server speaks plain HTTP: anywhere beyond localhost, put it behind a reverse proxy that
|
|
164
|
+
terminates TLS, and use a long random `MCP_AUTH_TOKEN`.
|
|
165
|
+
|
|
166
|
+
### Check the setup
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
UOL_TENANT=firma UOL_EMAIL=you@example.com UOL_TOKEN=your-token npx -y uol-mcp doctor
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Writing (opt-in)
|
|
173
|
+
|
|
174
|
+
With `UOL_ACCESS=write` these tools appear:
|
|
175
|
+
|
|
176
|
+
| Tool | Does |
|
|
177
|
+
|---|---|
|
|
178
|
+
| `upload_document` | Uploads a PDF to UOL's document inbox for the accountant (only from `UOL_UPLOAD_DIRS`) |
|
|
179
|
+
| `create_sales_invoice` | Creates an issued invoice for an existing contact — a draft unless `issue: true` |
|
|
180
|
+
| `update_sales_invoice` | Changes or issues a draft invoice (UOL doesn't allow editing issued ones) |
|
|
181
|
+
| `create_purchase_invoice` | Books a received invoice from an existing supplier |
|
|
182
|
+
| `create_contact`, `update_contact` | Adds or changes a customer / supplier (refuses a duplicate IČO) |
|
|
183
|
+
| `create_payment_demand` | Creates a payment demand (upomínka) for unpaid invoices of one customer — never sends it |
|
|
184
|
+
| `mark_document_processed`, `pair_uploaded_document`, `tag_uploaded_document`, `untag_uploaded_document` | The accountant's inbox: state, link to the booked record, tags |
|
|
185
|
+
|
|
186
|
+
`UOL_ACCESS=full` adds `delete_sales_invoice` (drafts only), `repair_sales_invoice` (storno or back to
|
|
187
|
+
draft for issued invoices) and `api_request` (a raw write to any endpoint).
|
|
188
|
+
|
|
189
|
+
Invoice lines need a UOL product (`list_codebook` with `kind: products` lists them). Every write
|
|
190
|
+
supports `dry_run` (shows exactly what would be sent), creates are safe to retry
|
|
191
|
+
(idempotency key), and the tools are marked so clients ask you before running them. Set
|
|
192
|
+
`UOL_AUDIT_LOG` to keep a record of every write.
|
|
193
|
+
|
|
194
|
+
## Several companies
|
|
195
|
+
|
|
196
|
+
Accountants with several clients on UOL can serve them all from one server. List the accounts in
|
|
197
|
+
`UOL_ACCOUNTS` and give each one its own variables (name upper-cased, `-` becomes `_`):
|
|
198
|
+
|
|
199
|
+
```json
|
|
200
|
+
"env": {
|
|
201
|
+
"UOL_ACCOUNTS": "firma,novak",
|
|
202
|
+
"UOL_ACCOUNT_FIRMA_TENANT": "firma",
|
|
203
|
+
"UOL_ACCOUNT_FIRMA_EMAIL": "ja@firma.cz",
|
|
204
|
+
"UOL_ACCOUNT_FIRMA_TOKEN": "op://Private/UOL firma/credential",
|
|
205
|
+
"UOL_ACCOUNT_NOVAK_TENANT": "novak",
|
|
206
|
+
"UOL_ACCOUNT_NOVAK_EMAIL": "ja@firma.cz",
|
|
207
|
+
"UOL_ACCOUNT_NOVAK_TOKEN": "op://Private/UOL novak/credential",
|
|
208
|
+
"UOL_ACCOUNT_NOVAK_LABEL": "Novák s.r.o."
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
The first account is the default (or set `UOL_DEFAULT_ACCOUNT`). With the 1Password CLI, start the
|
|
213
|
+
server as `op run -- node …/dist/index.js` and the `op://` references are replaced by the tokens at
|
|
214
|
+
startup — nothing secret sits in the config. `uol-mcp doctor` checks every account.
|
|
215
|
+
|
|
216
|
+
Alternatively, point `UOL_PROFILES_FILE` at a JSON file:
|
|
217
|
+
|
|
218
|
+
```json
|
|
219
|
+
{
|
|
220
|
+
"default": "firma",
|
|
221
|
+
"accounts": {
|
|
222
|
+
"firma": { "tenant": "firma", "email": "ja@firma.cz", "token_env": "UOL_TOKEN_FIRMA" },
|
|
223
|
+
"novak": { "tenant": "novak", "email": "ja@firma.cz", "token_env": "UOL_TOKEN_NOVAK", "label": "Novák s.r.o." }
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
`token_env` names an environment variable holding the token, so the file needs no secrets (an inline
|
|
229
|
+
`token` works too; keep such a file `chmod 600`). The server then offers `list_accounts`, and every tool
|
|
230
|
+
takes an `account` argument — *"Kdo dluží firmě Novák?"* goes to the right tenant. Each account keeps
|
|
231
|
+
its own rate limit.
|
|
232
|
+
|
|
233
|
+
## Privacy and safety
|
|
234
|
+
|
|
235
|
+
- Read-only unless you set `UOL_ACCESS=write`. Text inside invoices, notes and documents is treated
|
|
236
|
+
as data: review what the assistant proposes to write before you approve it.
|
|
237
|
+
- Whatever the tools return goes to the AI model your client uses. Accounting data contains personal
|
|
238
|
+
data of your contacts and employees — use a plan whose terms you are comfortable with.
|
|
239
|
+
- Credentials are used only for `https://*.uol.cz` and are never written to logs or tool output.
|
|
240
|
+
- Downloaded files are saved under `UOL_DOWNLOAD_DIR` only, readable by the owner, and never replace an existing file (a taken name gets a ` (1)` suffix).
|
|
241
|
+
|
|
242
|
+
## From source
|
|
243
|
+
|
|
244
|
+
Requires Node.js 22+.
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
git clone https://github.com/jakubbegera/uol-mcp.git
|
|
248
|
+
cd uol-mcp
|
|
249
|
+
npm install
|
|
250
|
+
npm run build
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Then point your client at `node /path/to/uol-mcp/dist/index.js` instead of `npx -y uol-mcp`.
|
|
254
|
+
|
|
255
|
+
## Development
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
npm test # unit + MCP-level tests against recorded DEMO responses
|
|
259
|
+
npm run typecheck
|
|
260
|
+
npm run smoke # calls every tool against the live DEMO tenant
|
|
261
|
+
npm run record-fixtures # refreshes test/fixtures/demo from the DEMO tenant
|
|
262
|
+
bash scripts/build-mcpb.sh # builds build/uol-mcp.mcpb
|
|
263
|
+
docker build -t uol-mcp .
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
CI runs the type check, tests, `npm audit`, a Trivy scan of the Docker image, CodeQL and, on pull
|
|
267
|
+
requests, dependency review; Dependabot keeps dependencies, actions and the base image current.
|
|
268
|
+
|
|
269
|
+
Releases are cut by pushing a `v*` tag; after a maintainer approves the `release` environment,
|
|
270
|
+
`.github/workflows/release.yml` publishes to npm, GHCR, the GitHub release (MCPB bundle) and the MCP
|
|
271
|
+
Registry.
|
|
272
|
+
|
|
273
|
+
Design notes, API facts and the roadmap are in [docs/DESIGN.md](docs/DESIGN.md).
|
|
274
|
+
|
|
275
|
+
## Contributing
|
|
276
|
+
|
|
277
|
+
Contributions are welcome — see [CONTRIBUTING.md](CONTRIBUTING.md). Report security problems
|
|
278
|
+
privately as described in [SECURITY.md](SECURITY.md).
|
|
279
|
+
|
|
280
|
+
## License
|
|
281
|
+
|
|
282
|
+
[MIT](LICENSE)
|