stalwart-mail-mcp 2.2.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Petr Šrámek
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,226 @@
1
+ # Stalwart Mail MCP
2
+
3
+ *[English](README.md)*
4
+
5
+ MCP server, díky kterému Claude Desktop (a jakýkoli MCP klient přes stdio) pracuje se schránkou
6
+ na vlastním poštovním serveru [Stalwart](https://stalw.art): hledá a čte poštu včetně příloh
7
+ a skenů, odpovídá ve vlákně, odesílá, zakládá koncepty a hledá nebo přidává kontakty.
8
+
9
+ Se serverem mluví protokolem JMAP a přihlašuje se účtem schránky. Na server se nic neinstaluje.
10
+
11
+ ```text
12
+ Claude Desktop ──stdio──▶ dist/index.cjs (Node, tento MCP server)
13
+ │ HTTPS · JMAP (RFC 8620 / 8621 / 9610)
14
+ ▼
15
+ https://mail.example.com/jmap (reverzní proxy → Stalwart)
16
+ ```
17
+
18
+ Jak ho zapojit do malé vlastní infrastruktury — reverzní proxy, co pustit ven, sdílené
19
+ schránky, vlastní balíček pro rodinu nebo tým — popisuje
20
+ [docs/mala-infrastruktura.md](docs/mala-infrastruktura.md).
21
+
22
+ ## Nástroje
23
+
24
+ Názvy mají předponu, výchozí je `mail_` (vlastní balíček si ji může změnit).
25
+
26
+ | Nástroj | Co dělá |
27
+ |---|---|
28
+ | `mail_list_mailboxes` | účty (vlastní + sdílené), složky s počty, povolení odesílatelé, adresáře |
29
+ | `mail_search_emails` | fulltext / od / komu / předmět / složka / datum / nepřečtené / s přílohou, nebo celé vlákno |
30
+ | `mail_get_email` | celá zpráva podle id (HTML → text) s číslovaným seznamem příloh |
31
+ | `mail_get_attachment` | obsah přílohy: text, PDF po stranách, OCR skenů a fotek dokumentů, obrázky; soubor uloží na disk |
32
+ | `mail_send_email` | odeslat nový mail nebo odpověď (`in_reply_to_id`, `reply_all`), přílohy z disku |
33
+ | `mail_create_draft` | totéž, ale jen uložit do Konceptů |
34
+ | `mail_send_draft` / `mail_delete_draft` | odeslat / smazat koncept podle id |
35
+ | `mail_search_contacts` | adresáře všech účtů a navíc odesílatelé a adresáti z historie pošty |
36
+ | `mail_add_contact` | nový kontakt (vlastní nebo sdílený adresář) |
37
+
38
+ Odeslání je okamžité a nejde vzít zpět, proto popisy nástrojů modelu říkají, že má posílat jen
39
+ na výslovný pokyn uživatele a jinak založit koncept.
40
+
41
+ ## Instalace
42
+
43
+ ### Claude Desktop (rozšíření)
44
+
45
+ Stáhni `stalwart-mail.mcpb` z
46
+ [posledního vydání](https://github.com/cybersmurf/stalwart-mail-mcp/releases/latest) a otevři
47
+ ho — Claude Desktop nabídne instalaci. Nebo si ho sestav:
48
+
49
+ ```bash
50
+ npm install
51
+ ./pack.sh # → stalwart-mail.mcpb
52
+ open stalwart-mail.mcpb # Claude Desktop → Install
53
+ ```
54
+
55
+ Vyplň adresu serveru, e-mail a heslo schránky. Volitelně jazyk a klíč Mistral API pro OCR.
56
+ Heslo se ukládá do klíčenky systému.
57
+
58
+ ### Jakýkoli MCP klient (stdio)
59
+
60
+ ```bash
61
+ npm install && npm run build
62
+ ```
63
+
64
+ ```json
65
+ {
66
+ "mcpServers": {
67
+ "stalwart-mail": {
68
+ "command": "node",
69
+ "args": ["/cesta/k/stalwart-mail-mcp/dist/index.cjs"],
70
+ "env": {
71
+ "STALWART_URL": "https://mail.example.com",
72
+ "STALWART_USER": "jana@example.com",
73
+ "STALWART_PASSWORD": "…"
74
+ }
75
+ }
76
+ }
77
+ }
78
+ ```
79
+
80
+ Claude Code: `claude mcp add stalwart-mail --env STALWART_URL=https://mail.example.com --env STALWART_USER=jana@example.com --env STALWART_PASSWORD=… -- node /cesta/k/stalwart-mail-mcp/dist/index.cjs`
81
+
82
+ ## Nastavení
83
+
84
+ | Proměnná | Význam |
85
+ |---|---|
86
+ | `STALWART_URL` | veřejná adresa serveru, např. `https://mail.example.com` (povinné) |
87
+ | `STALWART_USER` | schránka, kterou se přihlašuješ (povinné) |
88
+ | `STALWART_PASSWORD` | heslo schránky nebo heslo aplikace — posílá se jako Basic auth |
89
+ | `STALWART_TOKEN` | přístupový token OAuth místo hesla — posílá se jako Bearer |
90
+ | `MAIL_LANG` | `auto` (výchozí: jazyk počítače, angličtina, když ho neumíme) nebo kód jazyka |
91
+ | `MAIL_TOOL_PREFIX` | předpona názvů nástrojů, výchozí `mail` |
92
+ | `MAIL_BRAND` | zobrazovaný název serveru, výchozí `Stalwart Mail` |
93
+ | `MAIL_DOWNLOAD_DIR` | kam se ukládají přílohy, výchozí `~/Downloads/Mail-Attachments` |
94
+ | `MAIL_TIMEZONE` | časové pásmo (IANA) pro data ve výstupu, výchozí pásmo počítače |
95
+ | `MAIL_OCR_PROVIDER`, `MAIL_OCR_API_KEY`, `MAIL_OCR_MODEL`, `MAIL_OCR_BASE_URL` | kdo čte skeny — viz [Poskytovatelé OCR](#poskytovatelé-ocr) |
96
+ | `MISTRAL_API_KEY` | zkratka: když je nastavený jen tenhle, skeny jdou do Mistral OCR |
97
+ | `MAIL_ALLOW_SEND` | `false` odebere `send_email` a `send_draft` |
98
+ | `MAIL_ALLOW_DRAFTS` | `false` odebere `create_draft` a `delete_draft` |
99
+ | `MAIL_ALLOW_CONTACT_EDIT` | `false` odebere `add_contact` |
100
+ | `MAIL_ALLOW_ATTACHMENTS` | `false` odebere `get_attachment` |
101
+ | `MAIL_SAVE_ATTACHMENTS` | `false` = otevřené přílohy se jen přečtou, na disk se nic nezapíše |
102
+
103
+ ## Co smí dělat
104
+
105
+ Každá schopnost je přepínač v nastavení rozšíření (nebo proměnná výše), ve výchozím stavu je
106
+ vše zapnuté. Vypnutá schopnost se **jako nástroj vůbec nenabídne**, takže platí bez ohledu na
107
+ to, co si pamatují schvalovací dotazy klienta:
108
+
109
+ - vypnuté odesílání → schránka, kterou Claude čte a píše do ní koncepty, ale nikdy z ní neodešle;
110
+ - vypnuté odesílání, koncepty i úpravy kontaktů → schránka jen pro čtení;
111
+ - vypnuté ukládání příloh → `get_attachment` čte soubor z dočasné kopie a je označený jako
112
+ nástroj jen pro čtení; se zapnutým ukládáním zapisuje do složky stahování a je označený jako
113
+ zapisující, s čímž klienti mohou při schvalování zacházet jinak.
114
+
115
+ Samotné schvalování („povolit jednou / povolit vždy“) patří klientovi, ne tomuto serveru.
116
+ V Claude Desktop se nastavuje po nástrojích v nastavení rozšíření; po aktualizaci, která změní
117
+ definici nástroje, se klient může zeptat znovu.
118
+
119
+ ## Přílohy a OCR
120
+
121
+ `mail_get_attachment` stáhne soubor a vrátí to, co model přečte:
122
+
123
+ - textové soubory jako text, HTML převedené na text;
124
+ - PDF jako text po stranách (u dlouhých `page_from` / `page_to`);
125
+ - strany PDF bez textové vrstvy (skeny) a fotky jdou ke zvolenému **poskytovateli OCR** —
126
+ výsledkem je markdown včetně tabulek a takové strany jsou označené `(OCR)`. U smíšeného PDF
127
+ se posílají jen naskenované strany;
128
+ - obrázky se vrací jako obrázky; cokoli nad ~600 kB nebo v HEIC se na macOS zmenší (`sips`);
129
+ - ostatní typy (docx, xlsx, zip…) se jen uloží a vrátí se cesta.
130
+
131
+ Bez poskytovatele nebo s `ocr: false` se sken vrátí jako obrázek 1. strany (macOS)
132
+ s poznámkou. OCR je jediná věc, která z tohoto serveru posílá obsah jinam než na tvůj poštovní
133
+ server — ke zvolenému poskytovateli, nebo s lokálním modelem vůbec nikam.
134
+
135
+ ### Poskytovatelé OCR
136
+
137
+ | `MAIL_OCR_PROVIDER` | Co to je | Potřebuje | Čte PDF |
138
+ |---|---|---|---|
139
+ | `auto` (výchozí) | Mistral, když je nastavený `MISTRAL_API_KEY`; vlastní server, když je zadaná adresa a model; jinak vypnuto | — | — |
140
+ | `mistral` | Mistral OCR (`mistral-ocr-latest`) | klíč | přímo |
141
+ | `anthropic` | Claude přes oficiální SDK (výchozí model `claude-opus-5-5`) | klíč | přímo |
142
+ | `openai`, `openrouter`, `gemini` | hostovaná API kompatibilní s OpenAI (chat s obrázky) | klíč + model | obrázky stran |
143
+ | `ollama`, `lmstudio` | lokální modely na `localhost` | model | obrázky stran |
144
+ | `custom` | jakýkoli jiný server kompatibilní s OpenAI | `MAIL_OCR_BASE_URL` + model | obrázky stran |
145
+ | `off` | bez OCR | — | — |
146
+
147
+ Volbu doplňují `MAIL_OCR_API_KEY`, `MAIL_OCR_MODEL` a `MAIL_OCR_BASE_URL`. Příklady:
148
+
149
+ ```bash
150
+ MAIL_OCR_PROVIDER=ollama MAIL_OCR_MODEL=llama3.2-vision # čistě lokálně
151
+ MAIL_OCR_PROVIDER=openrouter MAIL_OCR_API_KEY=… MAIL_OCR_MODEL=<model s viděním>
152
+ MAIL_OCR_PROVIDER=anthropic MAIL_OCR_API_KEY=…
153
+ MAIL_OCR_PROVIDER=custom MAIL_OCR_BASE_URL=http://nas.lan:8000/v1 MAIL_OCR_MODEL=…
154
+ ```
155
+
156
+ Poskytovatelé, kteří berou jen obrázky, dostanou každou naskenovanou stranu jako PNG vytažené
157
+ z PDF (samotný sken, zmenšený na 2000 px). Stranu, která není jeden velký obrázek, jim předat
158
+ nejde a nahlásí se jako nepřečtená; Mistral a Anthropic čtou jakékoli PDF. Strany se posílají
159
+ po třech.
160
+
161
+ S čím počítat: lokální model může na hustou stranu potřebovat minutu i víc, což může
162
+ přesáhnout časový limit nástroje v klientu — dlouhé skeny čti po rozsazích stran. Obecné
163
+ modely s viděním přepisují dobře, ale jako každé OCR umí v tabulkách s grafikou posunout
164
+ buňky; `preview: true` přidá obrázek strany, aby si to model mohl zkontrolovat. U `anthropic`
165
+ se odmítnutý požadavek na aktuálních modelech Claude zopakuje na serveru na záložním modelu
166
+ (`fallbacks: "default"`).
167
+
168
+ `node test/live-ocr.mjs` pustí poskytovatele nastaveného v prostředí proti naskenovanému
169
+ testovacímu souboru (nebo tvému vlastnímu) a vypíše výsledek.
170
+
171
+ ## Jazyky
172
+
173
+ Názvy a popisy nástrojů, výstupy i chybové hlášky jsou lokalizované. Angličtina je zdroj,
174
+ čeština je psaná ručně a němčina, španělština, francouzština, italština, nizozemština,
175
+ polština, portugalština a slovenština jsou **strojové překlady**, které zatím žádný rodilý
176
+ mluvčí nekontroloval — opravy jsou vítané.
177
+
178
+ Jazyk se přidává nebo opravuje v `src/locales/<kód>.ts` (zkopíruj `en.ts`, zachovej
179
+ `{zástupné značky}` a zalomení řádků) a registruje se v `src/locales/index.ts`. Překlad může
180
+ být neúplný, chybějící texty se vezmou z angličtiny. `npm run test:offline` každý jazyk
181
+ porovná s anglickými klíči.
182
+
183
+ ## Vlastní balíčky (předvolby)
184
+
185
+ Pro rodinu nebo tým jde vyrobit rozšíření, kde je adresa serveru předvyplněná a lidé zadají
186
+ jen e-mail a heslo. Předvolba je složka s vlastním `manifest.json` (a volitelně `icon.png`),
187
+ viz [presets/example](presets/example).
188
+
189
+ ```bash
190
+ ./pack.sh --preset /cesta/k/predvolbe # → /cesta/k/predvolbe/<name>.mcpb
191
+ ```
192
+
193
+ Manifest předvolby nastaví přes `env` `MAIL_TOOL_PREFIX`, `MAIL_BRAND`, `MAIL_LANG` nebo
194
+ `MAIL_DOWNLOAD_DIR` a položce `server_url` dá výchozí hodnotu. `name` předvolby neměň, aby
195
+ Claude Desktop bral nové sestavení jako aktualizaci.
196
+
197
+ ## Testy
198
+
199
+ ```bash
200
+ npm run test:offline # bez schránky: falešný JMAP + falešné OCR, skutečný server přes stdio
201
+ MISTRAL_API_KEY=… node test/offline.mjs --live-ocr # navíc pošle testovací soubory do skutečného OCR
202
+ STALWART_URL=… STALWART_USER=… STALWART_PASSWORD=… node test/smoke.mjs # skutečná schránka
203
+ STALWART_URL=… STALWART_USER=… STALWART_PASSWORD=… node test/smoke.mjs --send # navíc pošle mail sám sobě
204
+ ```
205
+
206
+ Offline test pokrývá přílohy, OCR, předponu nástrojů, výběr jazyka a úplnost překladů.
207
+ Kouřový test založí koncept a zase ho smaže; s `--send` po sobě nechá ve schránce jednu
208
+ testovací zprávu.
209
+
210
+ ## Dobré vědět
211
+
212
+ - **Chybné heslo = ban IP** ve Stalwartu po několika pokusech. Server se přihlašuje až při
213
+ prvním volání nástroje, ne při startu, takže restarty klienta ban nevyrobí; opakované volání
214
+ se špatným heslem ano.
215
+ - Vzniklo pro Stalwart 0.16 a s ním se používá. Poštovní část je čisté RFC 8620/8621 a může
216
+ fungovat i s jinými JMAP servery, ale to není vyzkoušené; kontakty potřebují JMAP for
217
+ Contacts (RFC 9610).
218
+ - `Email/query` s `"inMailbox": null` Stalwart odmítne — filtr musí buď chybět, nebo mít id.
219
+ - Balíček je jeden soubor CommonJS (~3,8 MB, většinu dělá pdf.js z `unpdf`); přípona `.cjs`
220
+ je nutná, protože `package.json` má `"type": "module"`.
221
+ - Výsledek nástroje má v Claude Desktop strop kolem 1 MB, proto limit 600 kB pro vložené
222
+ obrázky.
223
+
224
+ ## Licence
225
+
226
+ MIT
package/README.md ADDED
@@ -0,0 +1,224 @@
1
+ # Stalwart Mail MCP
2
+
3
+ *[Česky](README.cs.md)*
4
+
5
+ An MCP server that lets Claude Desktop (or any MCP client that speaks stdio) work with a mailbox
6
+ on your own [Stalwart](https://stalw.art) mail server: search and read mail including
7
+ attachments and scans, reply in a thread, send, keep drafts, and look up or add contacts.
8
+
9
+ It talks JMAP with the mailbox's own credentials. Nothing is installed on the server.
10
+
11
+ ```text
12
+ Claude Desktop ──stdio──▶ dist/index.cjs (Node, this MCP server)
13
+ │ HTTPS · JMAP (RFC 8620 / 8621 / 9610)
14
+ ▼
15
+ https://mail.example.com/jmap (reverse proxy → Stalwart)
16
+ ```
17
+
18
+ How it fits into a small self-hosted setup — reverse proxy, what to expose, shared mailboxes,
19
+ branded builds for a family or a team — is described in
20
+ [docs/small-infrastructure.md](docs/small-infrastructure.md).
21
+
22
+ ## Tools
23
+
24
+ Names carry a prefix, `mail_` by default (a branded build can change it).
25
+
26
+ | Tool | What it does |
27
+ |---|---|
28
+ | `mail_list_mailboxes` | accounts (own + shared), folders with counts, allowed senders, address books |
29
+ | `mail_search_emails` | full text / from / to / subject / folder / date / unread / has attachment, or a whole thread |
30
+ | `mail_get_email` | a whole message by id (HTML → text) with a numbered list of attachments |
31
+ | `mail_get_attachment` | an attachment's content: text, PDF page by page, OCR of scans and photographed documents, images; saves the file to disk |
32
+ | `mail_send_email` | send a new mail or a reply (`in_reply_to_id`, `reply_all`), attachments from disk |
33
+ | `mail_create_draft` | the same, but only saved to Drafts |
34
+ | `mail_send_draft` / `mail_delete_draft` | send / delete a draft by id |
35
+ | `mail_search_contacts` | address books of every account plus senders and recipients from the mail history |
36
+ | `mail_add_contact` | new contact (own or shared address book) |
37
+
38
+ Sending is immediate and cannot be undone, so the tool descriptions tell the model to send only
39
+ on the user's explicit instruction and to create a draft otherwise.
40
+
41
+ ## Install
42
+
43
+ ### Claude Desktop (extension)
44
+
45
+ Download `stalwart-mail.mcpb` from the
46
+ [latest release](https://github.com/cybersmurf/stalwart-mail-mcp/releases/latest) and open it —
47
+ Claude Desktop offers to install it. Or build it yourself:
48
+
49
+ ```bash
50
+ npm install
51
+ ./pack.sh # → stalwart-mail.mcpb
52
+ open stalwart-mail.mcpb # Claude Desktop → Install
53
+ ```
54
+
55
+ Fill in the server address, the mailbox e-mail and password. Optional: the language and a
56
+ Mistral API key for OCR. The password is kept in the operating system's keychain.
57
+
58
+ ### Any MCP client (stdio)
59
+
60
+ ```bash
61
+ npm install && npm run build
62
+ ```
63
+
64
+ ```json
65
+ {
66
+ "mcpServers": {
67
+ "stalwart-mail": {
68
+ "command": "node",
69
+ "args": ["/path/to/stalwart-mail-mcp/dist/index.cjs"],
70
+ "env": {
71
+ "STALWART_URL": "https://mail.example.com",
72
+ "STALWART_USER": "jane@example.com",
73
+ "STALWART_PASSWORD": "…"
74
+ }
75
+ }
76
+ }
77
+ }
78
+ ```
79
+
80
+ Claude Code: `claude mcp add stalwart-mail --env STALWART_URL=https://mail.example.com --env STALWART_USER=jane@example.com --env STALWART_PASSWORD=… -- node /path/to/stalwart-mail-mcp/dist/index.cjs`
81
+
82
+ ## Configuration
83
+
84
+ | Variable | Meaning |
85
+ |---|---|
86
+ | `STALWART_URL` | public address of the server, e.g. `https://mail.example.com` (required) |
87
+ | `STALWART_USER` | the mailbox you sign in as (required) |
88
+ | `STALWART_PASSWORD` | mailbox or app password — sent as Basic auth |
89
+ | `STALWART_TOKEN` | an OAuth access token instead of the password — sent as Bearer |
90
+ | `MAIL_LANG` | `auto` (default: the machine's language, English when unsupported) or a locale code |
91
+ | `MAIL_TOOL_PREFIX` | prefix of the tool names, default `mail` |
92
+ | `MAIL_BRAND` | display name of the server, default `Stalwart Mail` |
93
+ | `MAIL_DOWNLOAD_DIR` | where attachments are saved, default `~/Downloads/Mail-Attachments` |
94
+ | `MAIL_TIMEZONE` | IANA zone for dates in the output, default the machine's zone |
95
+ | `MAIL_OCR_PROVIDER`, `MAIL_OCR_API_KEY`, `MAIL_OCR_MODEL`, `MAIL_OCR_BASE_URL` | who reads scans — see [OCR providers](#ocr-providers) |
96
+ | `MISTRAL_API_KEY` | shortcut: with only this set, scans go to Mistral OCR |
97
+ | `MAIL_ALLOW_SEND` | `false` removes `send_email` and `send_draft` |
98
+ | `MAIL_ALLOW_DRAFTS` | `false` removes `create_draft` and `delete_draft` |
99
+ | `MAIL_ALLOW_CONTACT_EDIT` | `false` removes `add_contact` |
100
+ | `MAIL_ALLOW_ATTACHMENTS` | `false` removes `get_attachment` |
101
+ | `MAIL_SAVE_ATTACHMENTS` | `false` = opened attachments are only read, nothing is written to disk |
102
+
103
+ ## What it is allowed to do
104
+
105
+ Every capability is a switch in the extension settings (or an env variable above), all on by
106
+ default. A capability that is off is **not offered as a tool at all**, so it holds regardless
107
+ of what the client's approval prompts remember:
108
+
109
+ - sending off → a mailbox Claude can read and draft in, but never send from;
110
+ - sending, drafts and contact edits off → a read-only mailbox;
111
+ - saving attachments off → `get_attachment` reads the file from a temporary copy and is
112
+ annotated read-only; with saving on it writes to the download folder and is annotated as a
113
+ writing tool, which clients may treat differently when asking for approval.
114
+
115
+ Approvals themselves ("allow once / always allow") belong to the client, not to this server.
116
+ In Claude Desktop they are set per tool in the extension's settings; a client may ask again
117
+ after an update that changes a tool's definition.
118
+
119
+ ## Attachments and OCR
120
+
121
+ `mail_get_attachment` downloads the file and returns what the model can read:
122
+
123
+ - text files as text, HTML converted to text;
124
+ - PDFs as text page by page (`page_from` / `page_to` for long ones);
125
+ - PDF pages without a text layer (scans) and photos go to the **OCR provider** you choose —
126
+ the result is markdown including tables, and those pages are marked `(OCR)`. A mixed PDF
127
+ sends only its scanned pages;
128
+ - images are returned as images; anything above ~600 kB or in HEIC is downscaled on macOS
129
+ (`sips`);
130
+ - other types (docx, xlsx, zip…) are only saved, and the path is returned.
131
+
132
+ Without a provider, or with `ocr: false`, a scan comes back as an image of page 1 (macOS) with
133
+ a note. OCR is the only thing in this server that sends content anywhere besides your mail
134
+ server — to the provider you picked, or nowhere at all with a local model.
135
+
136
+ ### OCR providers
137
+
138
+ | `MAIL_OCR_PROVIDER` | What it is | Needs | Reads PDFs |
139
+ |---|---|---|---|
140
+ | `auto` (default) | Mistral when `MISTRAL_API_KEY` is set, a custom server when address and model are set, otherwise off | — | — |
141
+ | `mistral` | Mistral OCR (`mistral-ocr-latest`) | key | directly |
142
+ | `anthropic` | Claude through the official SDK (default model `claude-opus-5-5`) | key | directly |
143
+ | `openai`, `openrouter`, `gemini` | hosted OpenAI-compatible vision chat APIs | key + model | page images |
144
+ | `ollama`, `lmstudio` | local models on `localhost` | model | page images |
145
+ | `custom` | any other OpenAI-compatible server | `MAIL_OCR_BASE_URL` + model | page images |
146
+ | `off` | no OCR | — | — |
147
+
148
+ `MAIL_OCR_API_KEY`, `MAIL_OCR_MODEL` and `MAIL_OCR_BASE_URL` complete the choice. Examples:
149
+
150
+ ```bash
151
+ MAIL_OCR_PROVIDER=ollama MAIL_OCR_MODEL=llama3.2-vision # fully local
152
+ MAIL_OCR_PROVIDER=openrouter MAIL_OCR_API_KEY=… MAIL_OCR_MODEL=<a vision model>
153
+ MAIL_OCR_PROVIDER=anthropic MAIL_OCR_API_KEY=…
154
+ MAIL_OCR_PROVIDER=custom MAIL_OCR_BASE_URL=http://nas.lan:8000/v1 MAIL_OCR_MODEL=…
155
+ ```
156
+
157
+ Providers that take images only get each scanned page as a PNG taken out of the PDF (the
158
+ scan itself, scaled to 2000 px). A page that is not one big picture cannot be handed to them
159
+ and is reported as unread; Mistral and Anthropic read any PDF. Pages are sent three at a time.
160
+
161
+ Things to expect: a local model can need a minute or more per dense page, which may exceed
162
+ your client's tool timeout — read long scans in page ranges. General vision models transcribe
163
+ well but, like every OCR, can misplace cells in tables with graphics; `preview: true` adds the
164
+ page image so the model can check. With `anthropic`, a declined request is retried
165
+ server-side on a fallback model (`fallbacks: "default"`) on the current Claude models.
166
+
167
+ `node test/live-ocr.mjs` runs the provider configured in the environment against a scanned
168
+ fixture (or your own file) and prints the result.
169
+
170
+ ## Languages
171
+
172
+ Tool titles, descriptions, output and error messages are localized. English is the source,
173
+ Czech is written by hand, and German, Spanish, French, Italian, Dutch, Polish, Portuguese and
174
+ Slovak are **machine translations** that no native speaker has reviewed yet — corrections are
175
+ welcome.
176
+
177
+ To add or fix a language edit `src/locales/<code>.ts` (copy `en.ts`, keep the `{placeholders}`
178
+ and line breaks) and register it in `src/locales/index.ts`. A locale may be partial; missing
179
+ keys fall back to English. `npm run test:offline` checks every locale against the English keys.
180
+
181
+ ## Branded builds (presets)
182
+
183
+ For a family or a team you can ship an extension where the server address is pre-filled and
184
+ people only type their e-mail and password. A preset is a folder with its own `manifest.json`
185
+ (and optionally `icon.png`); see [presets/example](presets/example).
186
+
187
+ ```bash
188
+ ./pack.sh --preset /path/to/preset # → /path/to/preset/<name>.mcpb
189
+ ```
190
+
191
+ The preset's manifest sets `MAIL_TOOL_PREFIX`, `MAIL_BRAND`, `MAIL_LANG` or
192
+ `MAIL_DOWNLOAD_DIR` through `env`, and gives `server_url` a default. Keep the preset's `name`
193
+ stable so Claude Desktop treats new builds as updates.
194
+
195
+ ## Tests
196
+
197
+ ```bash
198
+ npm run test:offline # no mailbox needed: fake JMAP + fake OCR, the real server over stdio
199
+ MISTRAL_API_KEY=… node test/offline.mjs --live-ocr # also sends the fixtures to the real OCR
200
+ STALWART_URL=… STALWART_USER=… STALWART_PASSWORD=… node test/smoke.mjs # real mailbox
201
+ STALWART_URL=… STALWART_USER=… STALWART_PASSWORD=… node test/smoke.mjs --send # also sends a mail to yourself
202
+ ```
203
+
204
+ The offline test covers attachments, OCR, the tool prefix, language selection and locale
205
+ consistency. The smoke test creates a draft and deletes it; with `--send` it leaves one test
206
+ message in the mailbox.
207
+
208
+ ## Good to know
209
+
210
+ - **A wrong password gets the IP banned** by Stalwart after a few attempts. The server signs in
211
+ on the first tool call, not at start, so restarting the client does not cause bans; calling
212
+ tools repeatedly with a wrong password does.
213
+ - Built for and used with Stalwart 0.16. The mail part is plain RFC 8620/8621 and may work with
214
+ other JMAP servers, but that is untested; contacts need JMAP for Contacts (RFC 9610).
215
+ - `Email/query` with `"inMailbox": null` is rejected by Stalwart — the filter must be absent or
216
+ carry an id.
217
+ - The extension bundle is one CommonJS file (~3.8 MB, most of it pdf.js from `unpdf`); the
218
+ `.cjs` extension matters because `package.json` says `"type": "module"`.
219
+ - A tool result in Claude Desktop is capped at about 1 MB, hence the 600 kB limit for inline
220
+ images.
221
+
222
+ ## License
223
+
224
+ MIT
@@ -0,0 +1,17 @@
1
+ # Third-party notices
2
+
3
+ The distributed bundle (`dist/index.cjs`, the `.mcpb` extension and the npm package) contains
4
+ the following open-source software. Each is used unmodified.
5
+
6
+ | Component | License | Source |
7
+ |---|---|---|
8
+ | @modelcontextprotocol/sdk | MIT | https://github.com/modelcontextprotocol/typescript-sdk |
9
+ | @anthropic-ai/sdk | MIT | https://github.com/anthropics/anthropic-sdk-typescript |
10
+ | zod | MIT | https://github.com/colinhacks/zod |
11
+ | unpdf | MIT | https://github.com/unjs/unpdf |
12
+ | PDF.js (bundled inside unpdf) | Apache-2.0 | https://github.com/mozilla/pdf.js |
13
+
14
+ PDF.js is Copyright Mozilla Foundation and licensed under the Apache License, Version 2.0;
15
+ a copy of that license is available at https://www.apache.org/licenses/LICENSE-2.0.
16
+ The MIT-licensed components are Copyright their respective authors; their license texts ship
17
+ in the corresponding packages on npm.