proton-mail-bridge-client 1.14.0 → 1.16.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/README.md +46 -136
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +54 -5
- package/dist/index.js.map +1 -1
- package/dist/services/background-sync-service.d.ts +1 -0
- package/dist/services/background-sync-service.d.ts.map +1 -1
- package/dist/services/background-sync-service.js +10 -4
- package/dist/services/background-sync-service.js.map +1 -1
- package/dist/services/local-index-service.d.ts +1 -0
- package/dist/services/local-index-service.d.ts.map +1 -1
- package/dist/services/local-index-service.js +26 -8
- package/dist/services/local-index-service.js.map +1 -1
- package/dist/services/simple-imap-service.d.ts +2 -0
- package/dist/services/simple-imap-service.d.ts.map +1 -1
- package/dist/services/simple-imap-service.js +101 -16
- package/dist/services/simple-imap-service.js.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -24,12 +24,12 @@
|
|
|
24
24
|
|
|
25
25
|
---
|
|
26
26
|
|
|
27
|
-
Give Claude Desktop (or Cline, or any MCP client) full access to your Proton Mail inbox: read, search, send, draft, triage threads, manage folders, save attachments, and more.
|
|
27
|
+
Give Claude Desktop (or Cline, or any MCP client) full access to your Proton Mail inbox: read, search, send, draft, triage threads, manage folders, save attachments, and more — 78 MCP tools in total. Most of the same capabilities are also available as a full CLI for scripting, cron, and piped automation — no Claude required.
|
|
28
28
|
|
|
29
29
|
## What you get
|
|
30
30
|
|
|
31
31
|
- **Claude reads and manages your Proton Mail** — triage, reply, draft, archive, search, move, batch-act on threads, pull attachments
|
|
32
|
-
- **Full CLI** — same
|
|
32
|
+
- **Full CLI** — 73 commands covering nearly all of the same capabilities, scriptable and pipeable, works in cron and shell scripts
|
|
33
33
|
- **Fast local search** — full-text search across your inbox without hitting IMAP on every query
|
|
34
34
|
- **Safety controls** — read-only mode, send gate, destructive-action confirmation, per-action allowlist
|
|
35
35
|
- **Privacy-native** — no third-party email service involved; your mail stays on your machine
|
|
@@ -194,6 +194,40 @@ The wizard handles config automatically. If you need to set it up by hand, three
|
|
|
194
194
|
|
|
195
195
|
---
|
|
196
196
|
|
|
197
|
+
## Connect to Claude Code
|
|
198
|
+
|
|
199
|
+
Install globally, then register the server with one command:
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
npm install -g proton-mail-bridge-client
|
|
203
|
+
|
|
204
|
+
claude mcp add proton-mail-bridge \
|
|
205
|
+
-e PROTONMAIL_USERNAME=you@proton.me \
|
|
206
|
+
-e PROTONMAIL_PASSWORD=your-bridge-password \
|
|
207
|
+
-- proton-mail-bridge-mcp
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
`your-bridge-password` is the Bridge app's own password (**Bridge → account → Mailbox details**), not your Proton account password — see the note under [Prerequisites](#prerequisites).
|
|
211
|
+
|
|
212
|
+
By default this registers the server for the current project only. Add `-s user` to make it available in every project:
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
claude mcp add proton-mail-bridge -s user \
|
|
216
|
+
-e PROTONMAIL_USERNAME=you@proton.me \
|
|
217
|
+
-e PROTONMAIL_PASSWORD=your-bridge-password \
|
|
218
|
+
-- proton-mail-bridge-mcp
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Verify it's connected:
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
claude mcp list
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
For file-based or command-based credentials instead of plaintext env vars, add `-e PROTONMAIL_USERNAME_FILE=/path/to/file` (or `_COMMAND`) the same way — see the credential methods under [Manual config](#connect-to-claude-desktop) above.
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
197
231
|
## Connect to Cline (VS Code)
|
|
198
232
|
|
|
199
233
|
Install globally (`npm install -g proton-mail-bridge-client`), then open Cline's MCP settings:
|
|
@@ -247,6 +281,8 @@ Reload the Cline extension after saving. Proton Mail tools will appear in Cline'
|
|
|
247
281
|
|
|
248
282
|
> **Tip:** When creating folders, use `Folders/Name` (not just `Name`) — that's the Proton Bridge namespace for real folders vs. labels.
|
|
249
283
|
|
|
284
|
+
More recipes — expanded triage prompts, cron scripts for scheduled digests, and a Claude Code `/mail-triage` slash command — are in [examples/](examples/).
|
|
285
|
+
|
|
250
286
|
---
|
|
251
287
|
|
|
252
288
|
## Recommended System Prompt
|
|
@@ -268,144 +304,18 @@ Rules:
|
|
|
268
304
|
|
|
269
305
|
## CLI
|
|
270
306
|
|
|
271
|
-
|
|
272
|
-
proton-mail-bridge-client <command> [options]
|
|
273
|
-
```
|
|
274
|
-
|
|
275
|
-
All commands support `--json` for machine-readable output.
|
|
276
|
-
|
|
277
|
-
### Read
|
|
278
|
-
|
|
279
|
-
```bash
|
|
280
|
-
proton-mail-bridge-client emails --folder INBOX --limit 25
|
|
281
|
-
proton-mail-bridge-client read INBOX::25642
|
|
282
|
-
proton-mail-bridge-client search "invoice" --limit 10
|
|
283
|
-
proton-mail-bridge-client search --live --from openai.com
|
|
284
|
-
proton-mail-bridge-client attachments INBOX::25642
|
|
285
|
-
```
|
|
286
|
-
|
|
287
|
-
### Triage
|
|
288
|
-
|
|
289
|
-
```bash
|
|
290
|
-
proton-mail-bridge-client digest
|
|
291
|
-
proton-mail-bridge-client threads "quarterly review"
|
|
292
|
-
proton-mail-bridge-client actionable
|
|
293
|
-
proton-mail-bridge-client followups
|
|
294
|
-
proton-mail-bridge-client thread-brief <threadId>
|
|
295
|
-
proton-mail-bridge-client document-threads --category invoice
|
|
296
|
-
proton-mail-bridge-client meeting-context alice@example.com
|
|
297
|
-
```
|
|
298
|
-
|
|
299
|
-
### Compose & send
|
|
300
|
-
|
|
301
|
-
```bash
|
|
302
|
-
proton-mail-bridge-client send --to bob@example.com --subject "Hey" --body "Hello"
|
|
303
|
-
echo "Hello" | proton-mail-bridge-client send --to bob@example.com --subject "Hey"
|
|
304
|
-
proton-mail-bridge-client reply INBOX::25642 --body "On it."
|
|
305
|
-
proton-mail-bridge-client reply INBOX::25642 --reply-all --body "On it."
|
|
306
|
-
proton-mail-bridge-client forward INBOX::25642 --to carol@example.com
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
### Mailbox actions
|
|
310
|
-
|
|
311
|
-
```bash
|
|
312
|
-
proton-mail-bridge-client move INBOX::25642 Folders/Archive
|
|
313
|
-
proton-mail-bridge-client archive INBOX::25642
|
|
314
|
-
proton-mail-bridge-client trash INBOX::25642
|
|
315
|
-
proton-mail-bridge-client restore Trash::25642
|
|
316
|
-
proton-mail-bridge-client mark-read INBOX::25642
|
|
317
|
-
proton-mail-bridge-client mark-read INBOX::25642 --unread
|
|
318
|
-
proton-mail-bridge-client star INBOX::25642
|
|
319
|
-
proton-mail-bridge-client delete INBOX::25642
|
|
320
|
-
proton-mail-bridge-client batch archive INBOX::100,INBOX::101,INBOX::102
|
|
321
|
-
proton-mail-bridge-client thread-action <threadId> archive
|
|
322
|
-
```
|
|
323
|
-
|
|
324
|
-
### Folders
|
|
325
|
-
|
|
326
|
-
```bash
|
|
327
|
-
proton-mail-bridge-client folders
|
|
328
|
-
proton-mail-bridge-client create-folder Folders/Receipts
|
|
329
|
-
proton-mail-bridge-client rename-folder Folders/Receipts Folders/Bills
|
|
330
|
-
proton-mail-bridge-client delete-folder Folders/Bills
|
|
331
|
-
```
|
|
332
|
-
|
|
333
|
-
### Drafts
|
|
334
|
-
|
|
335
|
-
```bash
|
|
336
|
-
proton-mail-bridge-client drafts
|
|
337
|
-
proton-mail-bridge-client draft-create --to bob@example.com --subject "Draft" --body "..."
|
|
338
|
-
proton-mail-bridge-client draft-read <id>
|
|
339
|
-
proton-mail-bridge-client draft-update <id> --subject "Updated subject"
|
|
340
|
-
proton-mail-bridge-client draft-reply INBOX::25642 --body "Will do."
|
|
341
|
-
proton-mail-bridge-client draft-forward INBOX::25642 --to carol@example.com
|
|
342
|
-
proton-mail-bridge-client draft-sync <id>
|
|
343
|
-
proton-mail-bridge-client draft-send <id>
|
|
344
|
-
proton-mail-bridge-client draft-delete <id>
|
|
345
|
-
proton-mail-bridge-client remote-drafts
|
|
346
|
-
```
|
|
347
|
-
|
|
348
|
-
### Analytics & diagnostics
|
|
349
|
-
|
|
350
|
-
```bash
|
|
351
|
-
proton-mail-bridge-client stats
|
|
352
|
-
proton-mail-bridge-client analytics
|
|
353
|
-
proton-mail-bridge-client contacts
|
|
354
|
-
proton-mail-bridge-client volume-trends --days 14
|
|
355
|
-
proton-mail-bridge-client watch --timeout 30
|
|
356
|
-
proton-mail-bridge-client test-email you@example.com
|
|
357
|
-
proton-mail-bridge-client doctor
|
|
358
|
-
proton-mail-bridge-client status
|
|
359
|
-
proton-mail-bridge-client sync --folder INBOX --limit 150
|
|
360
|
-
```
|
|
361
|
-
|
|
362
|
-
### Ambient notifications
|
|
363
|
-
|
|
364
|
-
Run as a background daemon — sends a system notification (macOS / Linux) whenever new mail arrives:
|
|
365
|
-
|
|
366
|
-
```bash
|
|
367
|
-
proton-mail-bridge-client notify # foreground (Ctrl+C to stop)
|
|
368
|
-
proton-mail-bridge-client notify & # background
|
|
369
|
-
proton-mail-bridge-client notify --folder INBOX --timeout 60 # custom folder and idle timeout
|
|
370
|
-
```
|
|
371
|
-
|
|
372
|
-
Each event is also written as a JSON line to stdout:
|
|
373
|
-
|
|
374
|
-
```json
|
|
375
|
-
{"event":"new_mail","folder":"INBOX","count":2,"at":"2026-05-18T14:32:01.000Z"}
|
|
376
|
-
```
|
|
377
|
-
|
|
378
|
-
Uses IMAP IDLE — no polling between events. Reconnects automatically on transient errors.
|
|
379
|
-
|
|
380
|
-
### MCP tool passthrough
|
|
381
|
-
|
|
382
|
-
Any MCP tool is also callable directly from the CLI:
|
|
307
|
+
Every capability is also a scriptable terminal command — no Claude required:
|
|
383
308
|
|
|
384
309
|
```bash
|
|
385
|
-
proton-mail-bridge-client
|
|
386
|
-
proton-mail-bridge-client
|
|
387
|
-
proton-mail-bridge-client
|
|
310
|
+
proton-mail-bridge-client digest # morning triage summary
|
|
311
|
+
proton-mail-bridge-client search --from stripe.com --json | jq . # scriptable search
|
|
312
|
+
echo "Deploy done" | proton-mail-bridge-client send --to you@x.com --subject "Deploy"
|
|
313
|
+
proton-mail-bridge-client notify & # background new-mail alerts
|
|
388
314
|
```
|
|
389
315
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
```bash
|
|
393
|
-
# Morning digest to a file
|
|
394
|
-
proton-mail-bridge-client digest --json > ~/morning-mail.json
|
|
316
|
+
All commands support `--json` for machine-readable output, and any MCP tool is directly callable via `proton-mail-bridge-client tool <name> --args '{...}'`.
|
|
395
317
|
|
|
396
|
-
|
|
397
|
-
proton-mail-bridge-client search --from stripe.com --json | jq '.[].subject'
|
|
398
|
-
|
|
399
|
-
# Pipe a script's output directly into an email
|
|
400
|
-
echo "Deploy complete on $(hostname) at $(date)" \
|
|
401
|
-
| proton-mail-bridge-client send --to alerts@example.com --subject "Deploy done"
|
|
402
|
-
|
|
403
|
-
# Scheduled digest every weekday at 8am (cron)
|
|
404
|
-
0 8 * * 1-5 proton-mail-bridge-client digest >> ~/mail-log.txt
|
|
405
|
-
|
|
406
|
-
# Count unread in INBOX
|
|
407
|
-
proton-mail-bridge-client emails --folder INBOX --json | jq '[.[] | select(.isRead == false)] | length'
|
|
408
|
-
```
|
|
318
|
+
**Full command reference: [docs/cli.md](docs/cli.md)** (73 commands across read, triage, compose, mailbox actions, folders, drafts, analytics, and diagnostics).
|
|
409
319
|
|
|
410
320
|
---
|
|
411
321
|
|
|
@@ -500,7 +410,7 @@ PROTONMAIL_IDLE_MAX_SECONDS='30'
|
|
|
500
410
|
`mark_email_read` · `star_email` · `move_email` · `archive_email` · `trash_email` · `restore_email` · `delete_email` · `batch_email_action` · `apply_thread_action` · `empty_folder` · `bulk_delete` · `bulk_move` · `bulk_update_flags` · `bulk_update_labels` · `update_message_flags` · `update_message_labels`
|
|
501
411
|
|
|
502
412
|
### Folder management
|
|
503
|
-
`create_folder` · `rename_folder` · `delete_folder` · `create_label`
|
|
413
|
+
`create_folder` · `rename_folder` · `delete_folder` · `create_label` · `rename_label` · `delete_label`
|
|
504
414
|
|
|
505
415
|
### Analytics
|
|
506
416
|
`get_email_stats` · `get_email_analytics` · `get_contacts` · `get_volume_trends` · `folder_stats` · `top_senders`
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAOA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAYnE,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAOA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAYnE,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EAAwD,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAC5H,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,KAAK,EAYV,gBAAgB,EACjB,MAAM,kBAAkB,CAAC;AAq/E1B,wBAAgB,kBAAkB,IAAI,gBAAgB,CA0FrD;AAED,wBAAgB,YAAY,CAC1B,MAAM,EAAE,gBAAgB,EACxB,OAAO,GAAE;IACP,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC1B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAq2EP;AAED,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAmD1C"}
|
package/dist/index.js
CHANGED
|
@@ -13,7 +13,7 @@ import { AuditService } from "./services/audit-service.js";
|
|
|
13
13
|
import { BackgroundSyncService } from "./services/background-sync-service.js";
|
|
14
14
|
import { DraftStoreService } from "./services/draft-store-service.js";
|
|
15
15
|
import { LocalIndexService } from "./services/local-index-service.js";
|
|
16
|
-
import { SimpleIMAPService } from "./services/simple-imap-service.js";
|
|
16
|
+
import { isLikelyAuthenticationError, isLikelyConnectionError, SimpleIMAPService } from "./services/simple-imap-service.js";
|
|
17
17
|
import { SMTPService } from "./services/smtp-service.js";
|
|
18
18
|
import { ensureValidEmails, isTextLikeMimeType, isValidEmail, lowerCaseAddress, normalizeBoolean, normalizeLimit, normalizeJsonValue, parseEmails, renderMarkdown, stringifyForJson, } from "./utils/helpers.js";
|
|
19
19
|
import { logger } from "./utils/logger.js";
|
|
@@ -1043,7 +1043,7 @@ const TOOLS = [
|
|
|
1043
1043
|
},
|
|
1044
1044
|
{
|
|
1045
1045
|
name: "run_doctor",
|
|
1046
|
-
description: "Run a comprehensive production health check covering SMTP auth, IMAP auth, optional IMAP IDLE probe, SQLite index integrity,
|
|
1046
|
+
description: "Run a comprehensive production health check covering SMTP auth, IMAP auth, optional IMAP IDLE probe, SQLite index integrity, sync-failed drafts, runtime policy validation, and what this server can/cannot do (capabilities). Connection failures include a classified diagnosis (authentication_failed vs bridge_unreachable) with a specific fix. Use to fully diagnose or validate the setup. Prefer get_connection_status for a quick protocol-only reachability check.",
|
|
1047
1047
|
annotations: { readOnlyHint: true },
|
|
1048
1048
|
inputSchema: {
|
|
1049
1049
|
type: "object",
|
|
@@ -2355,7 +2355,10 @@ export function buildConfigFromEnv() {
|
|
|
2355
2355
|
allowRemoteDraftSync,
|
|
2356
2356
|
allowedActions: parseAllowedActionsEnv("PROTONMAIL_ALLOWED_ACTIONS"),
|
|
2357
2357
|
startupSync: parseBooleanEnv("PROTONMAIL_STARTUP_SYNC", autoSync),
|
|
2358
|
-
|
|
2358
|
+
// Comma-separated; Sent is included by default so pendingOn/digest/follow-up
|
|
2359
|
+
// candidates don't misreport threads that were already answered — IDLE still
|
|
2360
|
+
// only watches the first folder (see BackgroundSyncService.primaryIdleFolder).
|
|
2361
|
+
autoSyncFolder: process.env.PROTONMAIL_AUTO_SYNC_FOLDER?.trim() || "INBOX,Sent",
|
|
2359
2362
|
autoSyncFull: parseBooleanEnv("PROTONMAIL_AUTO_SYNC_FULL", false),
|
|
2360
2363
|
autoSyncLimitPerFolder: parseIntegerEnv("PROTONMAIL_AUTO_SYNC_LIMIT_PER_FOLDER", 100, 1, 500),
|
|
2361
2364
|
idleWatchEnabled,
|
|
@@ -3730,7 +3733,7 @@ export function createServer(config, options = {}) {
|
|
|
3730
3733
|
const includeImap = normalizeBoolean(args.includeImap, true);
|
|
3731
3734
|
const includeIdleProbe = normalizeBoolean(args.includeIdleProbe, false);
|
|
3732
3735
|
const idleTimeoutSeconds = normalizeLimit(args.idleTimeoutSeconds, 5, 1, 60);
|
|
3733
|
-
const [smtpStatus, imapStatus, indexStatus, integrity] = await Promise.all([
|
|
3736
|
+
const [smtpStatus, imapStatus, indexStatus, integrity, drafts] = await Promise.all([
|
|
3734
3737
|
includeSmtp
|
|
3735
3738
|
? Promise.allSettled([smtpService.verifyConnection()]).then(([result]) => result)
|
|
3736
3739
|
: Promise.resolve({ status: "fulfilled", value: undefined }),
|
|
@@ -3739,6 +3742,7 @@ export function createServer(config, options = {}) {
|
|
|
3739
3742
|
: Promise.resolve({ status: "fulfilled", value: undefined }),
|
|
3740
3743
|
localIndexService.getStatus(),
|
|
3741
3744
|
localIndexService.runIntegrityCheck(),
|
|
3745
|
+
draftStore.listDrafts(true),
|
|
3742
3746
|
]);
|
|
3743
3747
|
const idleProbe = includeIdleProbe
|
|
3744
3748
|
? await Promise.allSettled([
|
|
@@ -3748,6 +3752,24 @@ export function createServer(config, options = {}) {
|
|
|
3748
3752
|
}),
|
|
3749
3753
|
]).then(([result]) => result)
|
|
3750
3754
|
: undefined;
|
|
3755
|
+
// Classifies the connection failure into a specific, actionable cause —
|
|
3756
|
+
// without PROTONMAIL_DEBUG this used to just say "connection failed" for
|
|
3757
|
+
// both a wrong password and Bridge not being open at all.
|
|
3758
|
+
const diagnoseFailure = (reason) => {
|
|
3759
|
+
if (isLikelyAuthenticationError(reason)) {
|
|
3760
|
+
return {
|
|
3761
|
+
cause: "authentication_failed",
|
|
3762
|
+
suggestion: "PROTONMAIL_PASSWORD must be the Proton Bridge password (Bridge app -> account -> Mailbox details), not your Proton account password. Confirm you're signed in inside the Bridge app.",
|
|
3763
|
+
};
|
|
3764
|
+
}
|
|
3765
|
+
if (isLikelyConnectionError(reason)) {
|
|
3766
|
+
return {
|
|
3767
|
+
cause: "bridge_unreachable",
|
|
3768
|
+
suggestion: "Proton Bridge isn't reachable on the configured host/port. Make sure the Bridge app is running, and that PROTONMAIL_IMAP_HOST/PORT and PROTONMAIL_SMTP_HOST/PORT match Bridge's Mailbox details.",
|
|
3769
|
+
};
|
|
3770
|
+
}
|
|
3771
|
+
return undefined;
|
|
3772
|
+
};
|
|
3751
3773
|
return createTextResult({
|
|
3752
3774
|
checkedAt: new Date().toISOString(),
|
|
3753
3775
|
runtime: sanitizeRuntimeConfig(config.runtime),
|
|
@@ -3761,6 +3783,7 @@ export function createServer(config, options = {}) {
|
|
|
3761
3783
|
? smtpStatus.reason.message
|
|
3762
3784
|
: String(smtpStatus.reason)
|
|
3763
3785
|
: "SMTP connection failed.",
|
|
3786
|
+
...(smtpStatus.status === "rejected" ? { diagnosis: diagnoseFailure(smtpStatus.reason) } : {}),
|
|
3764
3787
|
},
|
|
3765
3788
|
imap: {
|
|
3766
3789
|
ok: imapStatus.status === "fulfilled",
|
|
@@ -3773,6 +3796,7 @@ export function createServer(config, options = {}) {
|
|
|
3773
3796
|
? imapStatus.reason.message
|
|
3774
3797
|
: String(imapStatus.reason)
|
|
3775
3798
|
: "IMAP connection failed.",
|
|
3799
|
+
...(imapStatus.status === "rejected" ? { diagnosis: diagnoseFailure(imapStatus.reason) } : {}),
|
|
3776
3800
|
},
|
|
3777
3801
|
idleProbe: idleProbe === undefined
|
|
3778
3802
|
? { skipped: true }
|
|
@@ -3789,9 +3813,28 @@ export function createServer(config, options = {}) {
|
|
|
3789
3813
|
backgroundSync: backgroundSyncService.getStatus(),
|
|
3790
3814
|
index: indexStatus,
|
|
3791
3815
|
integrity,
|
|
3816
|
+
drafts: {
|
|
3817
|
+
total: drafts.length,
|
|
3818
|
+
syncFailed: drafts.filter((draft) => draft.remoteSyncState === "sync_failed").length,
|
|
3819
|
+
syncFailedIds: drafts
|
|
3820
|
+
.filter((draft) => draft.remoteSyncState === "sync_failed")
|
|
3821
|
+
.map((draft) => draft.id),
|
|
3822
|
+
},
|
|
3792
3823
|
audit: {
|
|
3793
3824
|
path: auditService.getPath(),
|
|
3794
3825
|
},
|
|
3826
|
+
// What this server can and cannot do, given Proton Bridge only proxies
|
|
3827
|
+
// local IMAP/SMTP — prevents an agent from attempting an impossible
|
|
3828
|
+
// operation (e.g. server-side filters) and getting a confusing failure.
|
|
3829
|
+
capabilities: {
|
|
3830
|
+
supported: ["mail read/search/send", "folders", "labels (IMAP folders under Labels/)", "drafts", "local full-text index"],
|
|
3831
|
+
notSupported: [
|
|
3832
|
+
"server-side filters/rules (no ManageSieve access through Bridge)",
|
|
3833
|
+
"real contacts / address book (no CardDAV access through Bridge)",
|
|
3834
|
+
"calendar (no CalDAV access through Bridge)",
|
|
3835
|
+
"vacation responder (Proton account API only, not exposed via Bridge)",
|
|
3836
|
+
],
|
|
3837
|
+
},
|
|
3795
3838
|
});
|
|
3796
3839
|
}
|
|
3797
3840
|
case "get_runtime_status": {
|
|
@@ -4286,7 +4329,13 @@ export function createServer(config, options = {}) {
|
|
|
4286
4329
|
throw error;
|
|
4287
4330
|
}
|
|
4288
4331
|
logger.error("Tool call failed", "MCPServer", { name, error });
|
|
4289
|
-
|
|
4332
|
+
if (isLikelyAuthenticationError(error)) {
|
|
4333
|
+
throw new McpError(ErrorCode.InternalError, "IMAP authentication failed. Check that PROTONMAIL_PASSWORD is your Proton Bridge password (not your Proton account password) and that you're signed in inside the Bridge app. Run run_doctor for a full connectivity check.");
|
|
4334
|
+
}
|
|
4335
|
+
if (isLikelyConnectionError(error)) {
|
|
4336
|
+
throw new McpError(ErrorCode.InternalError, "Could not connect to Proton Bridge. Make sure the Bridge app is running, and that PROTONMAIL_IMAP_HOST/PORT and PROTONMAIL_SMTP_HOST/PORT match the ports shown in Bridge's settings. Run run_doctor for a full connectivity check.");
|
|
4337
|
+
}
|
|
4338
|
+
throw new McpError(ErrorCode.InternalError, "An internal error occurred. Check get_logs for details, or run run_doctor for a full connectivity check.");
|
|
4290
4339
|
}
|
|
4291
4340
|
});
|
|
4292
4341
|
return {
|