内容
# hypermail-mcp
**模型上下文协议**服务器,允许代理通过单一、统一的工具界面操作用户的任意邮箱。
> **v0.7.16** — 强化`draft_email`:在成功创建草稿后,如果保存后读取失败,工具现在返回创建的草稿ID,并附带`warning`和`draftReadbackError`,而不是在错误后丢失草稿。撰写操作还会发出经过净化的`HYPERMAIL_DEBUG`阶段日志,IMAP草稿现在使用服务器公布的`\\Drafts`邮箱,当存在时,CLI支持`--version`。
>
> **v0.7.15** — 强化IMAP草稿创建:草稿现在直接追加到草稿邮箱,重试时不带`\\Draft`标志,如果IMAP服务器拒绝标记为标志的APPEND,保留IMAP回复/转发上下文到草稿中,与`send_email`相同。单个帐户的IMAP操作序列化以避免共享连接竞争,IMAP写入失败现在包括安全的服务器响应详细信息,而不仅仅是`Command failed`。帐户设置响应不再公开存储的提供商令牌/密码。还拒绝作为`format: "html"`传递的多行纯文本,并添加Hermes `get_new_emails`轮询器示例。
>
> **v0.7.14** — 添加了选择加入的`HYPERMAIL_DEBUG`结构化stderr日志,适用于服务器启动、帐户存储锁定/检查点写入和`get_new_emails`候选人/声明流程。强化Outlook `edit_draft`正文更新,通过请求Graph的更新表示,重新读取并重试,并返回错误而不是`edited: true`,如果请求的正文更改不可观察;Outlook正文编辑在附件处理后也获得一次安全的重放,当最终读取时已过时。
>
> **v0.7.13** — 在多个MCP进程共享同一个加密帐户存储时,加强`get_new_emails`以防止重复投递。存储写入现在在跨进程锁下重新加载和合并,检查点是单调的,新邮件批次在返回前原子性地声明。`trash_email`现在也使用Gmail和IMAP垃圾箱别名的提供商原生垃圾箱操作。
>
> **v0.7.12** — 在Microsoft Graph标签生成的线程历史记录标记为HTML但返回纯/非结构化文本时,加强Outlook回复/转发草稿格式化。此类历史记录现在进行防御性规范化,带有转义内容和换行符,以便引用的消息保持可读。
>
> **v0.7.11** — 通过转义它们并将草稿修补为HTML,修复了Outlook回复/转发草稿的引用的正文为纯文本的问题,以便新编写的HTML回复不再呈现为原始文本。
>
> **v0.7.10** — 修复了一个帐户存储竞争,其中Gmail/Outlook令牌刷新可能会覆盖`get_new_emails`检查点。检查点更新现在保留令牌数据并合并传递的ID在同一时间戳。`edit_draft`正文编辑现在需要精确的选定部分替换(`old_text` + `new_text`),以便保留回复/转发历史记录而不是覆盖。
>
> **v0.7.9** — 用基于拉取的`get_new_emails`工具替换了服务器端的电子邮件监视/网络钩子/脚本投递。代理计划自己的重复调用并获取有界的新收件箱电子邮件批次。
>
> **v0.7.8** — 默认Gmail循环重定向URI从随机端口`/oauth2callback`更改为固定`http://127.0.0.1:33333/callback`(仍然可以通过`HYPERMAIL_GMAIL_REDIRECT_URI`覆盖)。`.data/`加密密钥目录添加到`.gitignore`。
>
> **v0.7.7** — 仅限环境配置。运行时配置现在来自平面`HYPERMAIL_*`环境变量和选定的CLI覆盖。配置文件和旧提供商环境名称不再读取。托管Gmail OAuth回调通过`HYPERMAIL_GMAIL_REDIRECT_URI`支持;本地循环和手动完成仍然有效。
>
> **v0.7.6** — Gmail设置使用OAuth授权URL而不是Google的废弃设备代码流用于Gmail API范围。`complete_add_account`接受最终重定向的URL或原始`code`/`state`,提供商凭证使用专用的`HYPERMAIL_GMAIL_*` / `HYPERMAIL_OUTLOOK_*`环境变量。
>
> **v0.7.5** — 通过文件路径附加`send_email`/`draft_email`(`attachments`参数)。`edit_draft`获得`new_attachments`和`remove_attachments` — `add_attachment_to_draft`被删除(23个工具现在)。草稿编辑使用多策略线程边界检测,以实现更可靠的引用线程保留。发布的CLI安装MCP SDK依赖项,以便全局/npx运行不会因缺少SDK模块而失败。
>
> **v0.7.4** — `inReplyTo`现在是`send_email`和`draft_email`的必需参数(以前是可选的)。将其设置为`false`以创建新电子邮件,或传递消息ID以线程回复。这强制代理做出明确的选择,而不是静默地将回复视为新对话。
>
> **v0.7.3** — `edit_draft`现在在编辑Outlook回复/转发草稿时保留引用的线程历史记录。以前,编辑草稿正文会覆盖整个内容 — 包括引用的线程。现在,只有答案部分(在分隔符上方)被替换。
>
> **v0.7.1** — 现在每个配置字段都可以通过专用的`HYPERMAIL_*`环境变量设置。旧提供商环境变量不再被接受。有关完整参考,请参见[环境变量](#environment-variables)。
>
> **v0.6.3** — 将stdio和HTTP模式统一为单个功能集。删除了电子邮件监视(收件箱轮询、SSE推送、通知缓冲区)、代理多租户(`agents.yaml`、`x-api-key`身份验证、每代理允许列表)和`check_notifications`工具。删除了`js-yaml`依赖项。Dockerfile简化为单个`install → build → prune`步骤。
>
> **v0.6.2** — 版本源真实性修复:`version.ts`现在直接从`package.json`导入,而不是硬编码,防止两个文件之间的版本漂移。
>
> **v0.6.1** — Docker部署(独立Dockerfile与HEALTHCHECK)、电子邮件通知错误修复(基于ID的重复、分页上限、动态重新扫描)、Node 22基础镜像、删除docker-compose。
>
> **v0.5.0** — 用必需的`format`参数(`"html"` | `"markdown"`)替换了可选的`isHtml`布尔值,用于`send_email`、`draft_email`和`edit_draft`。Markdown正文通过`marked`转换为HTML,以便收件人始终看到干净的HTML。
>
> **v0.4.3** — 升级到Zod v4.4.3。通过将所有工具模式包装在`z.object()`中并替换区分的联合输出模式来修复MCP SDK v1.29.0兼容性,这些模式导致`validateToolOutput`崩溃。
代理不关心地址是工作Outlook帐户、个人Microsoft帐户、个人IMAP邮箱还是Gmail — 它只是调用`list_emails`、`search_emails`、`read_email`、`send_email`并将电子邮件地址作为`account`参数传递。服务器路由到正确的后端。
**v1状态:** Outlook / Microsoft 365(个人+工作)通过Microsoft Graph完全支持。IMAP(任何IMAP服务器)通过`imapflow` + `nodemailer`支持。Gmail通过Google OAuth授权码流与本地循环或托管回调加远程安全手动完成支持。
## 为什么
- 现有的Outlook/M365 MCP服务器(例如`@softeria/ms-365-mcp-server`)公开约200个原始Graph端点,并且与单个登录用户绑定。
- 该项目包装相同的经过验证的堆栈(`@azure/msal-node`用于身份验证,`@microsoft/microsoft-graph-client`用于HTTP),但公开一个小的、与提供商无关的电子邮件API,并支持多个帐户同时使用,按电子邮件地址索引。
## 安装/运行
```bash
npm install -g hypermail-mcp # 或 pnpm / npx
hypermail-mcp --help
```
作为stdio MCP服务器运行(默认)- 将其连接到MCP主机:
### Claude Desktop / Claude Code
```jsonc
{
"mcpServers": {
"hyper-email": {
"command": "npx",
"args": ["-y", "hypermail-mcp"]
}
}
}
```
或通过CLI:
```bash
claude mcp add hypermail -- npx -y hypermail-mcp
```
### 作为托管HTTP服务器
```bash
hypermail-mcp --http --port 3000 --host 0.0.0.0
# 端点:http://<host>:3000/mcp (可流式传输的HTTP传输,感知会话)
```
当托管时,设置`HYPERMAIL_KEY`,以便帐户文件在重启和重新部署时可重复解密。
### Docker
```bash
# 构建
docker build -t hypermail-mcp .
# 运行
# 从您的shell或部署环境中传递秘密值;不要提交它们。
docker run -d \
--name hypermail-mcp \
-p 3000:3000 \
-e HYPERMAIL_KEY \
-e HYPERMAIL_OUTLOOK_CLIENT_ID \
-e HYPERMAIL_OUTLOOK_TENANT_ID \
-v hypermail-data:/var/lib/mcp \
hypermail-mcp
```
镜像在端口3000上以HTTP模式运行服务器,并具有30秒的健康检查,针对`/mcp`。数据通过Docker卷在`/var/lib/mcp`处持久化。
### 开发
在本地测试HTTP服务器:
```bash
# 终端1:自动重新构建TypeScript
pnpm dev
# 终端2:使用环境变量/CLI配置启动HTTP服务器
pnpm dev:http
```
服务器在`http://127.0.0.1:3000/mcp`监听。
## 运行时和提供商配置
Hypermail使用平面`HYPERMAIL_*`环境变量作为事实来源。没有运行时配置文件。CLI标志仅覆盖单个调用的传输、主机、端口和数据目录。
CLI标志:`--http`、`--port`、`--host`、`--data-dir`、`--version`、`--help`。
子命令:`hypermail-mcp generate-key` — 为`HYPERMAIL_KEY`生成一个base64 32字节密钥。
### 本地CLI / 环境变量示例
```bash
export HYPERMAIL_KEY="$(hypermail-mcp generate-key)"
export HYPERMAIL_DATA_DIR="$HOME/.local/share/hypermail-mcp"
export HYPERMAIL_OUTLOOK_CLIENT_ID="<your-client-id>"
hypermail-mcp
```
### 通用MCP客户端JSON示例
```jsonc
{
"mcpServers": {
"hypermail": {
"command": "npx",
"args": ["-y", "hypermail-mcp"],
"env": {
"HYPERMAIL_KEY": "${HYPERMAIL_KEY}",
"HYPERMAIL_DATA_DIR": "${HYPERMAIL_DATA_DIR}",
"HYPERMAIL_OUTLOOK_CLIENT_ID": "${HYPERMAIL_OUTLOOK_CLIENT_ID}"
}
}
}
}
```
### 环境变量
| 环境变量 | 目的 | 默认值/行为 |
| --- | --- | --- |
| `HYPERMAIL_DATA_DIR` | 帐户/令牌存储位置 | `${XDG_DATA_HOME:-~/.local/share}/hypermail-mcp` |
| `HYPERMAIL_KEY` | 32字节AES-256-GCM密钥(十六进制/ base64)或通过SHA-256派生的任何密码 | 如果未设置,则生成并持久化本地密钥并打印启动警告 |
| `HYPERMAIL_TRANSPORT` | 运行时传输:`stdio`或`http` | `stdio`;`--http`覆盖为`http` |
| `HYPERMAIL_HTTP_PORT` | HTTP绑定端口 | `3000`;无效的HTTP模式值警告并回退 |
| `HYPERMAIL_HTTP_HOST` | HTTP绑定主机 | `127.0.0.1`;无效的HTTP模式值警告并回退 |
| `HYPERMAIL_OUTLOOK_CLIENT_ID` | 自定义Azure/Entra公共客户端ID(可选) | 内置公共客户端 |
| `HYPERMAIL_OUTLOOK_TENANT_ID` | Outlook租户/权限选择器(可选) | `common` |
| `HYPERMAIL_GMAIL_CLIENT_ID` | Google OAuth客户端ID(必填) | 添加Gmail帐户时必填 |
| `HYPERMAIL_GMAIL_CLIENT_SECRET` | Google OAuth客户端密钥(当客户端类型颁发时) | 未设置 |
| `HYPERMAIL_GMAIL_REDIRECT_URI` | 托管Gmail OAuth回调URI | 未设置时使用本地循环回调 |
| `HYPERMAIL_TOOLS_ENABLED` | 以逗号分隔的工具允许列表 | 空/未设置表示无过滤 |
| `HYPERMAIL_TOOLS_DISABLED` | 以逗号分隔的工具阻止列表 | 空/未设置表示无过滤 |
| `HYPERMAIL_DEBUG` | 启用结构化调试日志到stderr(`1`、`true`、`yes`、`on`或`debug`) | 默认情况下禁用 |
**优先级顺序:** 选定的CLI标志 > `HYPERMAIL_*`环境变量 > 硬编码默认值。
每个工具的过滤(`HYPERMAIL_TOOLS_ENABLED` / `HYPERMAIL_TOOLS_DISABLED`)允许操作员提供最小的代理面对的界面。如果两个非空列表都已设置,或者任一列表包含未知工具名称,则启动失败。
## 工具
所有“电子邮件”工具都带有`account`参数 - 要操作的收件箱的电子邮件地址。服务器从加密的帐户存储中解析正确的提供商。
| 工具 | 输入 | 备注 |
| --- | --- | --- |
| `list_accounts` | — | 返回注册的电子邮件+提供商,无密钥。 |
| `add_account` | `provider`, `email?`, `config?` | 启动提供商添加流程。Outlook返回设备代码;Gmail返回OAuth URL。准备好的帐户响应仅包括公共元数据,从不返回存储的令牌/密码。返回 `{handle, verification:{type, userCode, verificationUri, expiresAt, message}}`用于待处理流程。 |
| `complete_add_account` | `provider`, `handle`, `authorizationResponse?`, `code?`, `state?` | 返回 `pending` / `ready` / `expired` / `error`。准备好的帐户响应仅包括公共元数据,从不返回存储的令牌/密码。Gmail接受粘贴的最终重定向URL或原始代码/状态用于远程安全完成。 |
| `get_account_settings` | `account` | 获取帐户的签名(HTML)和样式首选项。 |
| `set_account_settings` | `account`, `signature?`, `signaturePath?`, `style?` | 设置签名HTML(内联或通过文件路径)和字体首选项。 |
| `remove_account` | `email` | 删除帐户的令牌。 |
| `list_emails` | `account`, `folder?`, `limit?`, `unreadOnly?`, `skip?` | 默认值:folder=`inbox`,limit=25。支持分页 - 响应包括`hasMore`。 |
| `get_new_emails` | `account?`, `limit?` | 拉取新的收件箱电子邮件,此工具之前未返回。 `limit`默认为10且全局时省略`account`。返回完整的markdown正文和附件元数据;正文可能被截断。 |
| `search_emails` | `account`, `query`, `limit?` | Outlook上的KQL。 |
| `read_email` | `account`, `id`, `format?` | 返回完整的正文 + 收件人 + 附件元数据。 `format`: `markdown`(默认)、`html`或`text`. |
| `read_attachment` | `account`, `messageId`, `attachmentId` | `account`, `messageId`, `attachmentId` | 将附件下载到临时文件并返回其路径。 |
| `archive_email` | `account`, `id` | 将消息移动到存档文件夹。 |
| `trash_email` | `account`, `id` | 将消息移动到已删除邮件(垃圾箱)。 |
| `move_email` | `account`, `id`, `destination` | 移动到任何文件夹(按已知名称(`inbox`、`drafts`等)或自定义文件夹ID)。 |
| `send_email` | `account`, `to[]`, `cc?`, `bcc?`, `subject`, `body`, `format`, `include_signature`, `inReplyTo`, `replyAll?`, `forwardMessageId?`, `attachments?` | 发送电子邮件。 `format`(`"html"` 或 `"markdown"`)控制正文格式 - Markdown 通过 `marked` 转换为 HTML;多行纯文本且 `format: "html"` 被拒绝,因此对于段落使用 `"markdown"` 或添加标签,如 `<p>`/`<br>`。当 `include_signature` 为 true 时追加签名。 `inReplyTo` 发送为线程回复; `forwardMessageId` 发送为转发。 `inReplyTo` 为必填项 - 设置为 `false` 以创建新邮件。 `attachments` 为可选的 `{filePath, name?}` 数组 - 文件从磁盘读取并自动编码。 |
| `draft_email` | `account`, `to[]`, `cc?`, `bcc?`, `subject`, `body`, `format`, `include_signature`, `inReplyTo`, `replyAll?`, `forwardMessageId?`, `attachments?` | 保存为草稿而不是发送。参数与 `send_email` 相同,包括 `attachments`。返回草稿消息ID,当读取回执成功时,返回HTML正文(`draftHtml`)。如果草稿创建但读取回执失败,则返回草稿ID并附带`warning`和`draftReadbackError`,以便调用者可以重试`read_email`或继续使用`send_draft`。 `inReplyTo` 为必填项 - 设置为 `false` 以创建新邮件。 |
| `edit_draft` | `account`, `id`, `to?`, `cc?`, `bcc?`, `subject?`, `old_text?`, `new_text?`, `body?`, `format?`, `include_signature?`, `new_attachments?`, `remove_attachments?` | 通过ID编辑现有草稿。 正文编辑需要精确的选定部分替换:复制草稿HTML中的`old_text`(`draftHtml`或`read_email`,格式为`html`)并提供`new_text`;匹配必须恰好发生一次,未选定的内容(如回复/转发历史记录)将被保留。弃用的`body`仅在`old_text`也提供时才是`new_text`的别名;仅替换整个正文被拒绝。多行纯文本替换时,`format: "html"`被拒绝;使用`markdown`进行段落处理或添加标签,如`<p>`/`<br>`。编辑后会重新读取正文;如果更新后的正文在重试后仍然不可观察,则工具返回错误而不是报告成功。 `new_attachments` 添加文件(`{filePath, name?}[]`);`remove_attachments` 通过附件ID(`string[]`)删除。返回更新的草稿ID,HTML正文(`draftHtml`)和附件元数据。 |
| `send_draft` | `account`, `id` | 通过ID发送现有草稿电子邮件。使用draft IDs由`draft_email`或`edit_draft`返回的。 |
| `list_folders` | `account`, `parentFolderId?` | 列出可用的邮件文件夹。默认情况下返回顶级文件夹,或`parentFolderId`的子文件夹。 |
| `create_folder` | `account`, `displayName`, `parentFolderId?` | 在根目录(默认)或给定的父目录下创建新的邮件文件夹。 |
| `delete_folder` | `account`, `folderId` | 通过ID删除邮件文件夹。 |
| `rename_folder` | `account`, `folderId`, `newName` | 重命名现有的邮件文件夹。 |
| `mark_read` | `account`, `id` | 将消息标记为已读。 |
| `mark_unread` | `account`, `id` | 将消息标记为未读。 |
## 拉取新邮件
`get_new_emails` 是服务器端监视/推送投递的替代工具。服务器不会运行后台的定时任务;代理或其运行环境会按照自己的时间表调用此工具,例如每 30-60 秒一次。
**行为:**
- 仅轮询 **收件箱**。
- `account` 是可选的。如果省略此参数,工具将检查所有已注册的账户。
- `limit` 默认值为 `10`。在所有账户模式下,限制是跨账户的全局总数,首先选择 `receivedAt` 最旧的邮件。
- 首次使用某个账户时,会将该账户的检查点初始化为收件箱中最新的邮件,并且不会为该账户返回任何邮件。
- 后续调用将返回此前未由该工具返回的邮件,按最旧的邮件优先。
- 返回的邮件正文是 markdown 格式,可能在大约 20k 字符处被截断;如有需要,可以调用 `read_email` 获取完整的正文。
- 附件仅作为元数据返回;如需获取内容,可以调用 `read_attachment`。
- 该工具不会将邮件标记为已读。
- `limit: 0` 可以初始化/检查状态,而无需获取邮件正文。
所有账户调用返回的部分失败结果为 `errors: [{ account, message }]`,并且仍然返回成功的账户的邮件。
参见 [`examples/hermes/`](examples/hermes/) 获取 Hermes 调度器集成示例,该集成会轮询此工具并将新邮件的有效载荷交给 Hermes 代理。
## 添加账户流程
### Outlook
1. 代理调用 `add_account({ provider: "outlook" })`。
2. 服务器返回:
```json
{
"status": "pending",
"handle": "…uuid…",
"verification": {
"type": "device_code",
"userCode": "ABCD-EFGH",
"verificationUri": "https://microsoft.com/devicelogin",
"expiresAt": "2025-…",
"message": "要登录,请使用网页浏览器打开 …"
}
}
```
3. 用户打开 URL 并输入代码。
4. 代理轮询 `complete_add_account({ provider: "outlook", handle })`,直到
它返回 `{ "status": "ready", "account": {...} }`。
5. 从此以后,可以使用 `account: "<that-email>"` 调用任何工具。
### Gmail
Gmail 使用 Google OAuth 2.0,与官方 Gmail MCP 模型相匹配。Google 的设备代码端点拒绝 Gmail API 作用域,因此 Hypermail 使用带有真实回调的授权 URL。服务账户仅适用于 Google Workspace 域范围的委托;它们不授予服务器到服务器访问消费级 `@gmail.com` 收件箱的权限。
对于本地 stdio/桌面 OAuth 客户端,Hypermail 会自动启动一个临时的 `127.0.0.1` 回环回调服务器。对于托管的 HTTP 部署,请设置 `HYPERMAIL_GMAIL_REDIRECT_URI` 并在 Google Auth 平台中注册确切的 URI,例如:
```bash
HYPERMAIL_TRANSPORT=http
HYPERMAIL_GMAIL_REDIRECT_URI=https://mail.example.com/oauth/gmail/callback
```
1. 配置 `HYPERMAIL_GMAIL_CLIENT_ID` 和(当由您的 Google 客户端类型颁发时)`HYPERMAIL_GMAIL_CLIENT_SECRET`。对于本地回环,请使用桌面客户端;对于托管的 HTTP 回调,请使用 Web 客户端。
2. 代理调用 `add_account({ provider: "gmail" })`。
3. 服务器返回一个 OAuth URL:
```json
{
"status": "pending",
"handle": "…uuid…",
"verification": {
"type": "oauth_url",
"userCode": "",
"verificationUri": "https://accounts.google.com/o/oauth2/v2/auth?...",
"expiresAt": "2025-…",
"message": "在浏览器中打开此 URL 以授权 Gmail 访问权限..."
}
}
```
4. 用户打开 `verificationUri` 并授予访问权限。如果可达的回调已配置,浏览器将显示一个小成功页面,代理可以轮询 `complete_add_account({ provider: "gmail", handle })`,直到准备就绪。
5. 如果浏览器无法访问回调,仍然可以使用手动回退:复制浏览器地址栏中的最终重定向 URL,然后调用:
```json
{
"provider": "gmail",
"handle": "…uuid…",
"authorizationResponse": "http://127.0.0.1:54321/oauth2callback?code=...&state=..."
}
```
6. `complete_add_account` 验证状态,交换代码以获取令牌,存储账户,并返回 `{ "status": "ready", "account": {...} }`。
## 路线图
- 线程/对话。
- 日历集成。
## 项目布局
```
src/
cli.ts # 参数解析 + 入口
server.ts # MCP 服务器,stdio + HTTP 传输,会话管理
version.ts # 版本常量
config.ts # 仅限环境配置类型 + 解析
store/
account-store.ts # 加密多账户存储(AES-256-GCM)
crypto.ts # AES-256-GCM 加密/解密,密钥解析,原子写入
providers/
types.ts # EmailProvider 接口 + 共享 DTO
registry.ts # 路由账户电子邮件 → 提供商
outlook/
auth.ts # msal-node 设备代码流程
client.ts # @microsoft/microsoft-graph-client 工厂
index.ts # OutlookProvider 实现
imap/index.ts # IMAP 提供商(imapflow + nodemailer)
gmail/
auth.ts # Google OAuth 授权码流程
client.ts # Gmail API(googleapis)
index.ts # GmailProvider 实现
shared/ # 提供商间的共享实用程序
tools/
index.ts # MCP 工具注册
accounts.ts # 列表/添加/删除/完成添加账户工具
browse.ts # 列表/搜索/阅读电子邮件工具
new-emails.ts # get_new_emails 拉取/检查点工具
compose.ts # 发送/草稿/编辑/发送草稿工具
folders.ts # 列表/创建/删除/重命名文件夹工具
organize.ts # 存档/垃圾箱/移动/标记为已读/标记为未读工具
shared.ts # 共享工具助手
```
## 许可证
MIT
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器