hypermail-mcp 0.7.8 → 0.7.10

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 CHANGED
@@ -3,6 +3,14 @@
3
3
  A **Model Context Protocol** server that lets an agent operate any of the user's
4
4
  inboxes through a single, unified tool surface.
5
5
 
6
+ > **v0.7.10** — Fixed an account-store race where Gmail/Outlook token
7
+ > refreshes could overwrite `get_new_emails` checkpoints. Checkpoint updates now
8
+ > preserve token data and merge delivered IDs at the same timestamp.
9
+ >
10
+ > **v0.7.9** — Replaced server-side email watch/webhook/script delivery with
11
+ > the pull-based `get_new_emails` tool. Agents schedule their own repeated calls
12
+ > and fetch bounded batches of new inbox email.
13
+ >
6
14
  > **v0.7.8** — Default Gmail loopback redirect URI changed from random-port
7
15
  > `/oauth2callback` to fixed `http://127.0.0.1:33333/callback` (still overridable via
8
16
  > `HYPERMAIL_GMAIL_REDIRECT_URI`). `.data/` encryption key directory added to
@@ -23,8 +31,7 @@ inboxes through a single, unified tool surface.
23
31
  > (`attachments` param). `edit_draft` gains `new_attachments` and
24
32
  > `remove_attachments` — `add_attachment_to_draft` is removed (23 tools now).
25
33
  > Draft editing uses multi-strategy thread boundary detection for more reliable
26
- > quoted-thread preservation. Watcher now supports shell-command notification
27
- > alongside webhook delivery. Published CLI installs the MCP SDK dependency so
34
+ > quoted-thread preservation. Published CLI installs the MCP SDK dependency so
28
35
  > global/npx runs do not fail on a missing SDK module.
29
36
  >
30
37
  > **v0.7.4** — `inReplyTo` is now a required parameter on `send_email` and
@@ -40,12 +47,7 @@ inboxes through a single, unified tool surface.
40
47
  > **v0.7.1** — Every config field is now settable via a dedicated
41
48
  > `HYPERMAIL_*` env var. Legacy provider env vars are no longer accepted. See
42
49
  > [Environment Variables](#environment-variables) for the full reference.
43
- >
44
- > **v0.7.0** — Email watch mode: background poll loop detects new inbox
45
- > messages and POSTs them to a configurable webhook URL (e.g. Mastra). Opt-in —
46
- > disabled by default, enabled via `HYPERMAIL_WATCH_ENABLED=true`.
47
- > Works in both stdio and HTTP transport modes.
48
- >
50
+
49
51
  > **v0.6.3** — Unify stdio and HTTP modes into a single feature set. Removed
50
52
  > email watch (inbox polling, SSE push, notification buffer), agent
51
53
  > multi-tenancy (`agents.yaml`, `x-api-key` auth, per-agent allowlists), and
@@ -216,15 +218,6 @@ hypermail-mcp
216
218
  | `HYPERMAIL_GMAIL_REDIRECT_URI` | Hosted Gmail OAuth callback URI | Local loopback callback when unset |
217
219
  | `HYPERMAIL_TOOLS_ENABLED` | Comma-separated tool allowlist | Empty/unset means no filtering |
218
220
  | `HYPERMAIL_TOOLS_DISABLED` | Comma-separated tool blocklist | Empty/unset means no filtering |
219
- | `HYPERMAIL_WATCH_ENABLED` | Enable inbox polling: `true` or `false` | `false` |
220
- | `HYPERMAIL_WATCH_POLL_SECONDS` | Watcher polling cadence | `10` |
221
- | `HYPERMAIL_WATCH_WEBHOOK_URL` | Webhook delivery target | Required if watch is enabled and no notify command is set |
222
- | `HYPERMAIL_WATCH_WEBHOOK_RETRY_ATTEMPTS` | Webhook retry attempts | `5` |
223
- | `HYPERMAIL_WATCH_WEBHOOK_RETRY_DELAY_MS` | Webhook exponential-backoff base delay | `1000` |
224
- | `HYPERMAIL_WATCH_NOTIFY_COMMAND` | Shell command run with `EmailFull` JSON on stdin | Required if watch is enabled and no webhook is set |
225
- | `HYPERMAIL_WATCH_NOTIFY_TIMEOUT_MS` | Notify-command execution timeout | `30000` |
226
- | `HYPERMAIL_WATCH_NOTIFY_RETRY_ATTEMPTS` | Notify-command retry attempts | `5` |
227
- | `HYPERMAIL_WATCH_NOTIFY_RETRY_DELAY_MS` | Notify-command exponential-backoff base delay | `1000` |
228
221
 
229
222
  **Priority order:** selected CLI flags > `HYPERMAIL_*` env vars > hardcoded defaults.
230
223
 
@@ -247,6 +240,7 @@ account store.
247
240
  | `set_account_settings` | `account`, `signature?`, `signaturePath?`, `style?` | Set signature HTML (inline or via file path) and font preferences. |
248
241
  | `remove_account` | `email` | Deletes tokens for the account. |
249
242
  | `list_emails` | `account`, `folder?`, `limit?`, `unreadOnly?`, `skip?` | Defaults: folder=`inbox`, limit=25. Supports pagination via `skip` — response includes `hasMore`. |
243
+ | `get_new_emails` | `account?`, `limit?` | Pull new inbox emails not previously returned by this tool. `limit` defaults to 10 and is global when `account` is omitted. Returns full markdown bodies with attachment metadata; bodies may be truncated. |
250
244
  | `search_emails` | `account`, `query`, `limit?` | KQL on Outlook. |
251
245
  | `read_email` | `account`, `id`, `format?` | Returns full body + recipients + attachment metadata. `format`: `markdown` (default), `html`, or `text`. |
252
246
  | `read_attachment` | `account`, `messageId`, `attachmentId` | Download an attachment to a temporary file and return its path. |
@@ -264,44 +258,28 @@ account store.
264
258
  | `mark_read` | `account`, `id` | Mark a message as read. |
265
259
  | `mark_unread` | `account`, `id` | Mark a message as unread. |
266
260
 
267
- ## Email Watch
268
-
269
- When enabled, hypermail-mcp runs a background poll loop that scans inboxes for
270
- new messages and delivers each one via webhook POST and/or shell command.
271
- Intended for push-based email triage — downstream agents receive full email
272
- content without polling.
273
-
274
- ```bash
275
- HYPERMAIL_WATCH_ENABLED=true \
276
- HYPERMAIL_WATCH_POLL_SECONDS=10 \
277
- HYPERMAIL_WATCH_WEBHOOK_URL=http://localhost:3000/api/email-webhook \
278
- HYPERMAIL_WATCH_NOTIFY_COMMAND='node /path/to/email-handler.js' \
279
- hypermail-mcp
280
- ```
261
+ ## Pull new emails
281
262
 
282
- **Validation:** If `HYPERMAIL_WATCH_ENABLED=true`, startup requires at least one
283
- of `HYPERMAIL_WATCH_WEBHOOK_URL` or `HYPERMAIL_WATCH_NOTIFY_COMMAND`. Webhook
284
- URLs are syntax-validated, and notify commands must be non-empty. Startup does
285
- not test network reachability or execute the command.
263
+ `get_new_emails` is the replacement for server-side watch/push delivery. The
264
+ server does not run background cron jobs; agents or their harnesses call this
265
+ tool on their own schedule, for example every 30–60 seconds.
286
266
 
287
267
  **Behavior:**
288
- - Polls **all accounts** in the store, **inbox only**.
289
- - Detects new emails via `lastSeenIds` (capped at 200) stored in the encrypted
290
- account file no duplicate emits across restarts.
291
- - Two delivery modes (can be used together):
292
- - **Webhook:** One `POST` per email (full body as `EmailFull` JSON).
293
- - **Notify command:** Executes `HYPERMAIL_WATCH_NOTIFY_COMMAND` through the
294
- platform shell with the `EmailFull` JSON piped to stdin.
295
- - Both modes use exponential backoff (`baseDelay × 2^attempt`). Retries on
296
- failures (non-2xx for webhook, non-zero exit for command). Logs and moves on
297
- after `maxAttempts` exhausted never blocks the poll loop.
298
- - Command delivery is fire-and-forget the poll loop continues while delivery
299
- runs in the background.
300
- - Works in both **stdio** and **HTTP** transport modes — the poll interval
301
- fires normally alongside MCP message handling.
302
-
303
- **Rate limits:** Polling every 10s on a single inbox = 6 req/min = 0.6% of
304
- Microsoft Graph's 10,000 req/10min per-user limit. Safe for personal inboxes.
268
+ - Polls **inbox only**.
269
+ - `account` is optional. When omitted, the tool checks all registered accounts.
270
+ - `limit` defaults to `10`. In all-account mode, the limit is a global total
271
+ across accounts, selected by oldest `receivedAt` first.
272
+ - First use for an account initializes its checkpoint to the newest inbox email
273
+ and returns no emails for that account.
274
+ - Later calls return emails not previously returned by this tool, oldest first.
275
+ - Returned bodies are markdown and may be truncated around 20k characters; call
276
+ `read_email` for the full body when needed.
277
+ - Attachments are returned as metadata only; call `read_attachment` for content.
278
+ - The tool does not mark emails as read.
279
+ - `limit: 0` can initialize/check state without fetching message bodies.
280
+
281
+ All-account calls return partial failures as `errors: [{ account, message }]`
282
+ and still return successful accounts' emails.
305
283
 
306
284
  ## Add-account flows
307
285
 
@@ -407,15 +385,11 @@ src/
407
385
  client.ts # Gmail API (googleapis)
408
386
  index.ts # GmailProvider implementation
409
387
  shared/ # shared utilities across providers
410
- watcher/
411
- manager.ts # WatcherManager — inbox poll loop + dedup
412
- webhook.ts # HTTP POST with exponential backoff retry
413
- script.ts # shell-command delivery with retry/timeout
414
- index.ts # barrel export
415
388
  tools/
416
389
  index.ts # MCP tool registrations
417
390
  accounts.ts # list/add/remove/complete-add account tools
418
391
  browse.ts # list/search/read email tools
392
+ new-emails.ts # get_new_emails pull/checkpoint tool
419
393
  compose.ts # send/draft/edit/send-draft tools
420
394
  folders.ts # list/create/delete/rename folder tools
421
395
  organize.ts # archive/trash/move/mark-read/mark-unread tools