hypermail-mcp 0.7.13 → 0.7.15

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,24 @@
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.15** — Hardened IMAP draft creation: drafts now append directly to
7
+ > the Drafts mailbox, retry without the `\\Draft` flag when an IMAP server
8
+ > rejects flagged APPEND, and preserve IMAP reply/forward context in drafts the
9
+ > same way `send_email` does. IMAP operations for a single account are serialized
10
+ > to avoid shared-connection races, and IMAP write failures now include safe
11
+ > server response details instead of only `Command failed`. Account setup
12
+ > responses no longer expose stored provider tokens/passwords. Also rejects
13
+ > multiline plain text passed as `format: "html"`, and adds the Hermes
14
+ > `get_new_emails` poller example.
15
+ >
16
+ > **v0.7.14** — Added opt-in `HYPERMAIL_DEBUG` structured stderr logs with
17
+ > redaction for server startup, account-store locking/checkpoint writes, and
18
+ > `get_new_emails` candidate/claim flow. Hardened Outlook `edit_draft` body
19
+ > updates by requesting Graph's updated representation, re-reading with retries,
20
+ > and returning an error instead of `edited: true` if the requested body change
21
+ > is not observable; Outlook body edits also get one safe replay after attachment
22
+ > handling when the final read is stale.
23
+ >
6
24
  > **v0.7.13** — Hardened `get_new_emails` against duplicate delivery when
7
25
  > multiple MCP processes share the same encrypted account store. Store writes
8
26
  > now reload and merge under a cross-process lock, checkpoints are monotonic,
@@ -235,6 +253,7 @@ hypermail-mcp
235
253
  | `HYPERMAIL_GMAIL_REDIRECT_URI` | Hosted Gmail OAuth callback URI | Local loopback callback when unset |
236
254
  | `HYPERMAIL_TOOLS_ENABLED` | Comma-separated tool allowlist | Empty/unset means no filtering |
237
255
  | `HYPERMAIL_TOOLS_DISABLED` | Comma-separated tool blocklist | Empty/unset means no filtering |
256
+ | `HYPERMAIL_DEBUG` | Enable structured debug logs to stderr (`1`, `true`, `yes`, `on`, or `debug`) | Disabled by default |
238
257
 
239
258
  **Priority order:** selected CLI flags > `HYPERMAIL_*` env vars > hardcoded defaults.
240
259
 
@@ -251,8 +270,8 @@ account store.
251
270
  | Tool | Inputs | Notes |
252
271
  | --- | --- | --- |
253
272
  | `list_accounts` | — | Returns registered emails + provider, no secrets. |
254
- | `add_account` | `provider`, `email?`, `config?` | Starts the provider add flow. Outlook returns a device code; Gmail returns an OAuth URL. Returns `{handle, verification:{type, userCode, verificationUri, expiresAt, message}}`. |
255
- | `complete_add_account` | `provider`, `handle`, `authorizationResponse?`, `code?`, `state?` | Returns `pending` / `ready` / `expired` / `error`. Gmail accepts a pasted final redirected URL or raw code/state for remote-safe completion. |
273
+ | `add_account` | `provider`, `email?`, `config?` | Starts the provider add flow. Outlook returns a device code; Gmail returns an OAuth URL. Ready account responses include public metadata only and never return stored tokens/passwords. Returns `{handle, verification:{type, userCode, verificationUri, expiresAt, message}}` for pending flows. |
274
+ | `complete_add_account` | `provider`, `handle`, `authorizationResponse?`, `code?`, `state?` | Returns `pending` / `ready` / `expired` / `error`. Ready account responses include public metadata only and never return stored tokens/passwords. Gmail accepts a pasted final redirected URL or raw code/state for remote-safe completion. |
256
275
  | `get_account_settings` | `account` | Get signature (HTML) and style preferences for an account. |
257
276
  | `set_account_settings` | `account`, `signature?`, `signaturePath?`, `style?` | Set signature HTML (inline or via file path) and font preferences. |
258
277
  | `remove_account` | `email` | Deletes tokens for the account. |
@@ -264,9 +283,9 @@ account store.
264
283
  | `archive_email` | `account`, `id` | Move a message to the Archive folder. |
265
284
  | `trash_email` | `account`, `id` | Move a message to Deleted Items (trash). |
266
285
  | `move_email` | `account`, `id`, `destination` | Move to any folder by well-known name (`inbox`, `drafts`, etc.) or custom folder ID. |
267
- | `send_email` | `account`, `to[]`, `cc?`, `bcc?`, `subject`, `body`, `format`, `include_signature`, `inReplyTo`, `replyAll?`, `forwardMessageId?`, `attachments?` | Send an email. `format` (`"html"` or `"markdown"`) controls body format — Markdown is converted to HTML via `marked`. Appends signature when `include_signature` is true. `inReplyTo` sends as threaded reply; `forwardMessageId` sends as forward. `inReplyTo` is required — set to `false` for new emails. `attachments` is an optional array of `{filePath, name?}` — files are read from disk and encoded automatically. |
286
+ | `send_email` | `account`, `to[]`, `cc?`, `bcc?`, `subject`, `body`, `format`, `include_signature`, `inReplyTo`, `replyAll?`, `forwardMessageId?`, `attachments?` | Send an email. `format` (`"html"` or `"markdown"`) controls body format — Markdown is converted to HTML via `marked`; multiline plain text with `format: "html"` is rejected, so use `"markdown"` for paragraphs or add tags like `<p>`/`<br>`. Appends signature when `include_signature` is true. `inReplyTo` sends as threaded reply; `forwardMessageId` sends as forward. `inReplyTo` is required — set to `false` for new emails. `attachments` is an optional array of `{filePath, name?}` — files are read from disk and encoded automatically. |
268
287
  | `draft_email` | `account`, `to[]`, `cc?`, `bcc?`, `subject`, `body`, `format`, `include_signature`, `inReplyTo`, `replyAll?`, `forwardMessageId?`, `attachments?` | Save as draft instead of sending. Same params as `send_email` including `attachments`. Returns the draft message ID and HTML body (`draftHtml`). `inReplyTo` is required — set to `false` for new emails. |
269
- | `edit_draft` | `account`, `id`, `to?`, `cc?`, `bcc?`, `subject?`, `old_text?`, `new_text?`, `body?`, `format?`, `include_signature?`, `new_attachments?`, `remove_attachments?` | Edit an existing draft by ID. Body edits require exact selected-section replacement: copy `old_text` from the current draft HTML (`draftHtml` or `read_email` with `format: "html"`) and provide `new_text`; the match must occur exactly once, and unselected content such as reply/forward history is preserved. Deprecated `body` is only an alias for `new_text` when `old_text` is also provided; body-only full replacement is rejected. `new_attachments` adds files (`{filePath, name?}[]`); `remove_attachments` removes by attachment ID (`string[]`). Returns the updated draft ID, HTML body (`draftHtml`), and attachment metadata. |
288
+ | `edit_draft` | `account`, `id`, `to?`, `cc?`, `bcc?`, `subject?`, `old_text?`, `new_text?`, `body?`, `format?`, `include_signature?`, `new_attachments?`, `remove_attachments?` | Edit an existing draft by ID. Body edits require exact selected-section replacement: copy `old_text` from the current draft HTML (`draftHtml` or `read_email` with `format: "html"`) and provide `new_text`; the match must occur exactly once, and unselected content such as reply/forward history is preserved. Deprecated `body` is only an alias for `new_text` when `old_text` is also provided; body-only full replacement is rejected. Multiline plain-text replacements with `format: "html"` are rejected; use `"markdown"` for paragraphs or add tags like `<p>`/`<br>`. Body edits are re-read after saving; if the updated body is not observable after retries, the tool returns an error instead of reporting success. `new_attachments` adds files (`{filePath, name?}[]`); `remove_attachments` removes by attachment ID (`string[]`). Returns the updated draft ID, HTML body (`draftHtml`), and attachment metadata. |
270
289
  | `send_draft` | `account`, `id` | Send an existing draft email by ID. Use with draft IDs returned by `draft_email` or `edit_draft`. |
271
290
  | `list_folders` | `account`, `parentFolderId?` | List available mail folders. Returns top-level folders by default, or children of `parentFolderId`. |
272
291
  | `create_folder` | `account`, `displayName`, `parentFolderId?` | Create a new mail folder under root (default) or the given parent. |
@@ -298,6 +317,9 @@ tool on their own schedule, for example every 30–60 seconds.
298
317
  All-account calls return partial failures as `errors: [{ account, message }]`
299
318
  and still return successful accounts' emails.
300
319
 
320
+ See [`examples/hermes/`](examples/hermes/) for a Hermes scheduler integration
321
+ that polls this tool and hands new-email payloads to a Hermes agent.
322
+
301
323
  ## Add-account flows
302
324
 
303
325
  ### Outlook