proton-mail-bridge-client 1.15.0 → 1.17.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 +49 -137
- package/dist/cli.d.ts +7 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +88 -1
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +16 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +511 -26
- package/dist/index.js.map +1 -1
- package/dist/services/delivery-queue-service.d.ts +35 -0
- package/dist/services/delivery-queue-service.d.ts.map +1 -0
- package/dist/services/delivery-queue-service.js +198 -0
- package/dist/services/delivery-queue-service.js.map +1 -0
- package/dist/services/simple-imap-service.d.ts +20 -0
- package/dist/services/simple-imap-service.d.ts.map +1 -1
- package/dist/services/simple-imap-service.js +94 -11
- package/dist/services/simple-imap-service.js.map +1 -1
- package/dist/services/smtp-service.d.ts.map +1 -1
- package/dist/services/smtp-service.js +22 -2
- package/dist/services/smtp-service.js.map +1 -1
- package/dist/services/snooze-service.d.ts +33 -0
- package/dist/services/snooze-service.d.ts.map +1 -0
- package/dist/services/snooze-service.js +210 -0
- package/dist/services/snooze-service.js.map +1 -0
- package/dist/services/template-service.d.ts +36 -0
- package/dist/services/template-service.d.ts.map +1 -0
- package/dist/services/template-service.js +153 -0
- package/dist/services/template-service.js.map +1 -0
- package/dist/types/index.d.ts +38 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/helpers.d.ts +3 -0
- package/dist/utils/helpers.d.ts.map +1 -1
- package/dist/utils/helpers.js +12 -0
- package/dist/utils/helpers.js.map +1 -1
- package/dist/utils/runtime-policy.d.ts.map +1 -1
- package/dist/utils/runtime-policy.js +1 -0
- package/dist/utils/runtime-policy.js.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
|
|
|
@@ -447,7 +357,7 @@ PROTONMAIL_PASSWORD_COMMAND='pass proton/password'
|
|
|
447
357
|
PROTONMAIL_DATA_DIR="$HOME/.proton-mail-bridge-client"
|
|
448
358
|
|
|
449
359
|
# Tools
|
|
450
|
-
PROTONMAIL_TOOL_TIER='full' # 'core' exposes 20 essential tools (saves context window); 'full' exposes all
|
|
360
|
+
PROTONMAIL_TOOL_TIER='full' # 'core' exposes 20 essential tools (saves context window); 'full' exposes all 93
|
|
451
361
|
|
|
452
362
|
# Safety
|
|
453
363
|
PROTONMAIL_READ_ONLY='false'
|
|
@@ -455,6 +365,8 @@ PROTONMAIL_ALLOW_SEND='true'
|
|
|
455
365
|
PROTONMAIL_ALLOW_REMOTE_DRAFT_SYNC='true'
|
|
456
366
|
PROTONMAIL_ALLOWED_ACTIONS='mark_read,mark_unread,star,unstar,archive,trash,restore'
|
|
457
367
|
PROTONMAIL_CONFIRM_DESTRUCTIVE='false'
|
|
368
|
+
PROTONMAIL_SEND_DELAY_SECONDS='0' # >0: send_email queues instead of sending immediately, cancelable via cancel_send. Only fires while this server stays running.
|
|
369
|
+
PROTONMAIL_SIGNATURE='' # Plain text, appended to send_email bodies (text + HTML). Opt out per-message with appendSignature: false.
|
|
458
370
|
|
|
459
371
|
# Sync
|
|
460
372
|
PROTONMAIL_AUTO_SYNC='true'
|
|
@@ -500,7 +412,7 @@ PROTONMAIL_IDLE_MAX_SECONDS='30'
|
|
|
500
412
|
`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
413
|
|
|
502
414
|
### Folder management
|
|
503
|
-
`create_folder` · `rename_folder` · `delete_folder` · `create_label`
|
|
415
|
+
`create_folder` · `rename_folder` · `delete_folder` · `create_label` · `rename_label` · `delete_label`
|
|
504
416
|
|
|
505
417
|
### Analytics
|
|
506
418
|
`get_email_stats` · `get_email_analytics` · `get_contacts` · `get_volume_trends` · `folder_stats` · `top_senders`
|
package/dist/cli.d.ts
CHANGED
|
@@ -7,6 +7,13 @@ export interface ParsedCliArgs {
|
|
|
7
7
|
flags: CliFlags;
|
|
8
8
|
}
|
|
9
9
|
export declare function parseCliArgs(argv: string[]): ParsedCliArgs;
|
|
10
|
+
interface ToolOnlyCommand {
|
|
11
|
+
command: string;
|
|
12
|
+
tool: string;
|
|
13
|
+
positionals: string[];
|
|
14
|
+
help: string;
|
|
15
|
+
}
|
|
16
|
+
export declare const TOOL_ONLY_COMMANDS: ToolOnlyCommand[];
|
|
10
17
|
export declare function main(): Promise<void>;
|
|
11
18
|
export {};
|
|
12
19
|
//# sourceMappingURL=cli.d.ts.map
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AA4BA,KAAK,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC;AAEjD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE,QAAQ,CAAC;CACjB;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,aAAa,CAgC1D;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AA4BA,KAAK,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC;AAEjD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE,QAAQ,CAAC;CACjB;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,aAAa,CAgC1D;AAskDD,UAAU,eAAe;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,eAAO,MAAM,kBAAkB,EAAE,eAAe,EA4D/C,CAAC;AA0CF,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAyN1C"}
|
package/dist/cli.js
CHANGED
|
@@ -126,6 +126,10 @@ function printHelp() {
|
|
|
126
126
|
" draft-thread-reply <id> Create a reply draft for a thread",
|
|
127
127
|
" tools List every MCP tool exposed by the server",
|
|
128
128
|
" tool <name> Call any MCP tool with JSON arguments",
|
|
129
|
+
"",
|
|
130
|
+
"Additional 1:1 tool commands (required args positional, rest via --args):",
|
|
131
|
+
...TOOL_ONLY_COMMANDS.map((entry) => ` ${entry.command.padEnd(23)} ${entry.help}`),
|
|
132
|
+
"",
|
|
129
133
|
" claude setup Run the interactive Claude Desktop setup wizard",
|
|
130
134
|
" claude install Install or update the Claude Desktop runtime",
|
|
131
135
|
" claude check Check Claude Desktop integration status",
|
|
@@ -1545,6 +1549,83 @@ async function runTool(parsed) {
|
|
|
1545
1549
|
printToolCallResult(result, wantJson);
|
|
1546
1550
|
});
|
|
1547
1551
|
}
|
|
1552
|
+
export const TOOL_ONLY_COMMANDS = [
|
|
1553
|
+
{ command: "cancel-send", tool: "cancel_send", positionals: ["id"], help: "Cancel a send queued by PROTONMAIL_SEND_DELAY_SECONDS" },
|
|
1554
|
+
{ command: "unsubscribe-info", tool: "get_unsubscribe_info", positionals: ["emailId"], help: "Read List-Unsubscribe details for a message" },
|
|
1555
|
+
{ command: "unsubscribe-sender", tool: "unsubscribe_sender", positionals: ["emailId"], help: "Execute a mailto unsubscribe (--args '{\"confirmed\":true}' if required)" },
|
|
1556
|
+
{ command: "reply-to-email", tool: "reply_to_email", positionals: ["emailId", "body"], help: "Immediately send a reply (full tool: attachments/dryRun via --args)" },
|
|
1557
|
+
{ command: "reply-all-email", tool: "reply_all_email", positionals: ["emailId"], help: "Immediately reply to all recipients (--args '{\"body\":...}')" },
|
|
1558
|
+
{ command: "forward-email", tool: "forward_email", positionals: ["emailId", "to"], help: "Immediately forward a message, preserving attachments" },
|
|
1559
|
+
{ command: "list-drafts", tool: "list_drafts", positionals: [], help: "List local drafts (tool form; see also `drafts`)" },
|
|
1560
|
+
{ command: "schedule-draft", tool: "schedule_draft", positionals: ["draftId", "sendAt"], help: "Queue a saved draft to send at a future time" },
|
|
1561
|
+
{ command: "get-email-by-id", tool: "get_email_by_id", positionals: ["emailId"], help: "Fetch one email (tool form; see also `read`)" },
|
|
1562
|
+
{ command: "get-emails-by-ids", tool: "get_emails_by_ids", positionals: ["emailIds"], help: "Fetch up to 25 emails by comma-separated ids" },
|
|
1563
|
+
{ command: "search-emails", tool: "search_emails", positionals: [], help: "Live IMAP search (tool form; see also `search --live`)" },
|
|
1564
|
+
{ command: "get-folders", tool: "get_folders", positionals: [], help: "List folders (tool form; see also `folders`)" },
|
|
1565
|
+
{ command: "sync-folders", tool: "sync_folders", positionals: [], help: "Refresh the in-memory folder list from IMAP" },
|
|
1566
|
+
{ command: "mark-email-read", tool: "mark_email_read", positionals: ["emailId"], help: "Mark read/unread (tool form; see also `mark-read`)" },
|
|
1567
|
+
{ command: "star-email", tool: "star_email", positionals: ["emailId"], help: "Star/unstar (tool form; see also `star`)" },
|
|
1568
|
+
{ command: "move-email", tool: "move_email", positionals: ["emailId", "targetFolder"], help: "Move an email (tool form; see also `move`)" },
|
|
1569
|
+
{ command: "archive-email", tool: "archive_email", positionals: ["emailId"], help: "Archive an email (tool form; see also `archive`)" },
|
|
1570
|
+
{ command: "trash-email", tool: "trash_email", positionals: ["emailId"], help: "Move to Trash (tool form; see also `trash`)" },
|
|
1571
|
+
{ command: "restore-email", tool: "restore_email", positionals: ["emailId"], help: "Restore from Trash (tool form; see also `restore`)" },
|
|
1572
|
+
{ command: "snooze-email", tool: "snooze_email", positionals: ["emailId", "wakeAt"], help: "Snooze a message until wakeAt (ISO timestamp)" },
|
|
1573
|
+
{ command: "cancel-snooze", tool: "cancel_snooze", positionals: ["id"], help: "Wake a snoozed email immediately" },
|
|
1574
|
+
{ command: "create-template", tool: "create_template", positionals: ["name", "subject", "body"], help: "Save a reusable email template" },
|
|
1575
|
+
{ command: "list-templates", tool: "list_templates", positionals: [], help: "List saved email templates" },
|
|
1576
|
+
{ command: "get-template", tool: "get_template", positionals: ["id"], help: "Get a saved template by id" },
|
|
1577
|
+
{ command: "delete-template", tool: "delete_template", positionals: ["id"], help: "Delete a saved template" },
|
|
1578
|
+
{ command: "render-template", tool: "render_template", positionals: ["id"], help: "Render a template ({{var}} substitution via --args '{\"variables\":{...}}')" },
|
|
1579
|
+
{ command: "delete-email", tool: "delete_email", positionals: ["emailId"], help: "Permanently delete (tool form; see also `delete`)" },
|
|
1580
|
+
{ command: "update-message-labels", tool: "update_message_labels", positionals: ["emailId"], help: "Add/remove Proton labels on one message" },
|
|
1581
|
+
{ command: "update-message-flags", tool: "update_message_flags", positionals: ["emailId"], help: "Add/remove IMAP flags on one message" },
|
|
1582
|
+
{ command: "count-messages", tool: "count_messages", positionals: [], help: "Count messages matching live IMAP search criteria" },
|
|
1583
|
+
{ command: "bulk-update-flags", tool: "bulk_update_flags", positionals: [], help: "Add/remove IMAP flags on multiple messages" },
|
|
1584
|
+
{ command: "bulk-update-labels", tool: "bulk_update_labels", positionals: [], help: "Add/remove Proton labels on multiple messages" },
|
|
1585
|
+
{ command: "top-senders", tool: "top_senders", positionals: [], help: "Top senders in a folder over a date range" },
|
|
1586
|
+
{ command: "move-thread", tool: "move_thread", positionals: ["messageId", "destination"], help: "Move every message in a thread" },
|
|
1587
|
+
{ command: "delete-thread", tool: "delete_thread", positionals: ["messageId"], help: "Delete every message in a thread" },
|
|
1588
|
+
{ command: "flag-thread", tool: "flag_thread", positionals: ["messageId"], help: "Add/remove IMAP flags across a thread" },
|
|
1589
|
+
{ command: "create-label", tool: "create_label", positionals: ["name"], help: "Create a Proton label" },
|
|
1590
|
+
{ command: "rename-label", tool: "rename_label", positionals: ["name", "newName"], help: "Rename a Proton label" },
|
|
1591
|
+
{ command: "delete-label", tool: "delete_label", positionals: ["name"], help: "Delete a Proton label" },
|
|
1592
|
+
{ command: "get-connection-status", tool: "get_connection_status", positionals: [], help: "(tool form; see also `connection-status`)" },
|
|
1593
|
+
{ command: "get-runtime-status", tool: "get_runtime_status", positionals: [], help: "(tool form; see also `runtime-status`)" },
|
|
1594
|
+
{ command: "run-doctor", tool: "run_doctor", positionals: [], help: "Full production health check (tool form; see also `doctor`)" },
|
|
1595
|
+
{ command: "run-background-sync", tool: "run_background_sync", positionals: [], help: "Trigger the configured background sync cycle now" },
|
|
1596
|
+
{ command: "sync-emails", tool: "sync_emails", positionals: [], help: "(tool form; see also `sync`)" },
|
|
1597
|
+
{ command: "get-index-status", tool: "get_index_status", positionals: [], help: "(tool form; see also `index-status`)" },
|
|
1598
|
+
{ command: "search-indexed-emails", tool: "search_indexed_emails", positionals: [], help: "(tool form; see also `search`)" },
|
|
1599
|
+
{ command: "get-labels", tool: "get_labels", positionals: [], help: "(tool form; see also `labels`)" },
|
|
1600
|
+
{ command: "get-threads", tool: "get_threads", positionals: [], help: "(tool form; see also `threads`)" },
|
|
1601
|
+
{ command: "get-inbox-digest", tool: "get_inbox_digest", positionals: [], help: "(tool form; see also `digest`)" },
|
|
1602
|
+
{ command: "get-follow-up-candidates", tool: "get_follow_up_candidates", positionals: [], help: "(tool form; see also `followups`)" },
|
|
1603
|
+
{ command: "list-attachments", tool: "list_attachments", positionals: ["emailId"], help: "(tool form; see also `attachments`)" },
|
|
1604
|
+
{ command: "get-attachment-content", tool: "get_attachment_content", positionals: ["emailId", "attachmentId"], help: "Fetch attachment metadata/base64" },
|
|
1605
|
+
{ command: "get-attachment-text", tool: "get_attachment_text", positionals: ["emailId", "attachmentId"], help: "Extract text from a text-like attachment" },
|
|
1606
|
+
{ command: "save-attachments", tool: "save_attachments", positionals: ["emailId"], help: "Save all attachments from an email to disk" },
|
|
1607
|
+
{ command: "save-attachment", tool: "save_attachment", positionals: ["emailId", "attachmentId"], help: "Save one attachment to disk" },
|
|
1608
|
+
{ command: "export-email", tool: "export_email", positionals: ["emailId"], help: "Save raw .eml source to disk" },
|
|
1609
|
+
{ command: "import-email", tool: "import_email", positionals: ["raw"], help: "Import a raw .eml message via IMAP APPEND" },
|
|
1610
|
+
{ command: "clear-index", tool: "clear_index", positionals: [], help: "Delete the local SQLite mailbox index" },
|
|
1611
|
+
{ command: "get-audit-logs", tool: "get_audit_logs", positionals: [], help: "Recent write-operation audit log entries" },
|
|
1612
|
+
];
|
|
1613
|
+
async function runToolOnlyCommand(entry, parsed) {
|
|
1614
|
+
const wantJson = isTruthyFlag(parsed.flags.json);
|
|
1615
|
+
const args = {};
|
|
1616
|
+
entry.positionals.forEach((field, index) => {
|
|
1617
|
+
const value = parsed.positionals[index];
|
|
1618
|
+
if (value === undefined) {
|
|
1619
|
+
throw new Error(`${entry.command} requires: ${entry.positionals.join(", ")}`);
|
|
1620
|
+
}
|
|
1621
|
+
args[field] = value;
|
|
1622
|
+
});
|
|
1623
|
+
Object.assign(args, (await parseToolArgs(parsed)) ?? {});
|
|
1624
|
+
await withMcpClient(async (client) => {
|
|
1625
|
+
const result = await client.callTool({ name: entry.tool, arguments: args });
|
|
1626
|
+
printToolCallResult(result, wantJson);
|
|
1627
|
+
});
|
|
1628
|
+
}
|
|
1548
1629
|
async function runClaude(parsed) {
|
|
1549
1630
|
switch (parsed.subcommand) {
|
|
1550
1631
|
case "setup":
|
|
@@ -1772,8 +1853,14 @@ export async function main() {
|
|
|
1772
1853
|
case "claude":
|
|
1773
1854
|
await runClaude(parsed);
|
|
1774
1855
|
return;
|
|
1775
|
-
default:
|
|
1856
|
+
default: {
|
|
1857
|
+
const toolOnly = TOOL_ONLY_COMMANDS.find((entry) => entry.command === parsed.command);
|
|
1858
|
+
if (toolOnly) {
|
|
1859
|
+
await runToolOnlyCommand(toolOnly, parsed);
|
|
1860
|
+
return;
|
|
1861
|
+
}
|
|
1776
1862
|
throw new Error(`Unknown command: ${parsed.command}`);
|
|
1863
|
+
}
|
|
1777
1864
|
}
|
|
1778
1865
|
}
|
|
1779
1866
|
const isDirectExecution = isMainModule(import.meta.url);
|