内容
# imap-mcp
一款专注于安全性的[模型上下文协议][mcp]服务器,负责在严格且可审计的策略下,协调LLM访问IMAP邮箱。适用于需要读取、分类、移动和存档邮件的代理,但必须防止它们读取不应读取的内容、移动不应移动的内容或留下任何操作痕迹。
## 状态
**V1 — 241个BDD场景通过,0个跳过。** 服务器可以通过stdio和HTTP/SSE传输运行。支持Gmail(带有RFC 6154的本地化文件夹名称解析)和标准IMAP提供商。可选的OpenTelemetry跟踪与Jaeger。
## 快速入门
```bash
# 通过pipx安装(推荐 — 独立环境,全球CLI)
pipx install "sc-imap-mcp[tracing]"
# 或通过pip
pip install sc-imap-mcp[tracing]
# 不带跟踪
pipx install sc-imap-mcp
# 从源代码
cd server && pip install -e ".[tracing]"
# 升级
pipx upgrade sc-imap-mcp
```
### 配置
```bash
mkdir -p ~/.config/imap-mcp/{policies,secrets/accounts/my-account}
# 创建accounts.yaml、callers.yaml、policies/*.yaml
# (参见下面的配置部分)
# 存储IMAP密码或OAuth刷新令牌
echo -n 'your-password' > ~/.config/imap-mcp/secrets/accounts/my-account/password
```
### 在stdio上运行(适用于Claude Desktop、Claude Code、Cline)
```bash
IMAP_MCP_CONFIG_DIR=~/.config/imap-mcp \
IMAP_MCP_CALLER_ID=my-agent \
imap-mcp --transport stdio
```
### 注册到Claude Code
```bash
claude mcp add --scope user imap-mcp \
--env IMAP_MCP_CONFIG_DIR=$HOME/.config/imap-mcp \
--env IMAP_MCP_CALLER_ID=my-agent \
-- imap-mcp --transport stdio
```
### 在HTTP上运行(适用于多代理设置)
```bash
IMAP_MCP_CONFIG_DIR=~/.config/imap-mcp \
imap-mcp --transport http --host 127.0.0.1 --port 8080
```
## 架构
```
┌──────────────────────────┐
│ LLM代理(MCP客户端) │
└────────────┬─────────────┘
│ MCP(stdio或HTTP/SSE)
┌────────────▼─────────────────────────────────────────┐
│ imap-mcp │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 策略决策点 — 默认拒绝 │ │
│ │ 删减/透明度层 │ │
│ │ 事务管理器(WAL + saga) │ │
│ │ IMAP核心 · 批量获取 · OAuth2适配器 │ │
│ │ 可插拔的秘密存储 │ │
│ │ 仅追加审计日志,带有哈希链 │ │
│ │ OpenTelemetry跟踪(可选) │ │
│ └─────────────────────────────────────────────────┘ │
└─────────┬───────────────────┬────────────────────────┘
│ IMAP/IMAPS │ IMAP/IMAPS
┌─────────▼────┐ ┌──────────▼────┐
│ 账户A │ │ 账户B │
│ (例如Gmail) │ │ (例如Dovecot)│
└──────────────┘ └───────────────┘
```
## 配置
服务器从由`IMAP_MCP_CONFIG_DIR`指向的YAML文件目录中读取其配置。
```
config/
├── accounts.yaml # IMAP账户、秘密存储、审计、WAL
├── callers.yaml # MCP调用者和它们的身份验证
└── policies/
├── invoice-agent.yaml
└── overview-bot.yaml
```
### accounts.yaml
定义服务器可以连接到的每个IMAP账户,以及秘密存储后端、审计日志和WAL配置。
```yaml
accounts:
- id: company-mail
provider: imap-standard # 或"google"表示Gmail
host: imap.example.com
port: 993
auth:
type: password # 或"xoauth2"
secret_ref: secret://accounts/company-mail/password
token_cache: memory_only # 或"persist_all"(仅限OAuth)
- id: gmail-work
provider: google
host: imap.gmail.com
port: 993
auth:
type: xoauth2
secret_ref: secret://accounts/gmail-work/refresh_token
oauth_scope: https://mail.google.com/
token_cache: persist_all
- id: accounting@company.com
host: imap.company.com
port: 993
user: mail2223 # 显式IMAP登录(当!= id时)
auth:
type: password
secret_ref: secret://accounts/accounting@company.com/password
secret_store:
backend: file_dir # 或"env_var"或"gpg_file"
path: /home/user/.config/imap-mcp/secrets
audit:
directory: /home/user/.config/imap-mcp/audit
hot_days: 90 # 压缩前的天数
warm_days: 275 # 附加天数作为.gz
delete_after_days: 365 # 删除前的总天数
wal:
path: /home/user/.config/imap-mcp/wal.db
```
#### 账户字段
| 字段 | 必需 | 默认值 | 描述 |
|---|---|---|---|
| `id` | 是 | — | 策略中引用的唯一标识符。对于使用OAuth的Gmail,请使用电子邮件地址(例如`user@company.com`) |
| `provider` | 否 | `imap-standard` | `imap-standard`、`google`或`google-mock` |
| `host` | 否 | `127.0.0.1` | IMAP服务器主机名 |
| `port` | 否 | `143` | IMAP端口。使用`993`表示IMAPS(Gmail,大多数提供商) |
| `user` | 否 | 从`id`派生 | 显式IMAP登录用户名。当IMAP用户与账户ID不同时使用(例如`mail2223`表示`accounting@example.com`) |
| `auth.type` | 是 | — | `password`或`xoauth2` |
| `auth.secret_ref` | 是 | — | 对秘密存储的引用(例如`secret://accounts/x/password`) |
| `auth.oauth_scope` | 否 | — | xoauth2账户的OAuth2范围 |
| `token_cache` | 否 | `memory_only` | `memory_only`(仅内存中的访问令牌)或`persist_all`(也持久化) |
#### 秘密存储后端
| 后端 | 描述 | 配置字段 |
|---|---|---|
| `file_dir` | 明文文件;通过周围系统(git-crypt、SOPS、LUKS)进行保密 | `path` |
| `env_var` | 仅限环境变量只读。 | — |
| `gpg_file` | 每文件GPG解密,使用操作员的密钥 | `path`、`recipient`、`gnupghome` |
秘密引用使用`secret://path/segments`格式。对于`file_dir`,这解析为`{path}/path/segments`。
### callers.yaml
定义可能连接到服务器的每个MCP调用者(代理)。
```yaml
callers:
- id: my-agent
policy: my-policy
auth:
type: stdio_trusted
- id: invoice-bot
policy: invoice-policy
auth:
type: shared_token
token_secret_ref: secret://callers/invoice-bot/token
```
#### 调用者身份验证类型
| 类型 | 传输 | 机制 |
|---|---|---|
| `stdio_trusted` | 仅限stdio | 调用者ID通过编排器设置`IMAP_MCP_CALLER_ID`环境变量。 |
| `shared_token` | stdio + HTTP | 带有恒定时间比较的Bearer令牌验证。在HTTP上:`Authorization: Bearer <token>`头。 |
调用者身份在会话期间不可变。没有伪装原语。
### policies/\<name\>.yaml
每个策略文件定义了一个调用者可以看到和执行的操作。
```yaml
name: my-policy
accounts:
company-mail:
- path: INBOX
mode: blacklist
default: ENVELOPE
mark_seen: true
rules: []
gmail-work:
- path: INBOX
mode: whitelist
default: NONE
mark_seen: true
move_out: true
rules:
- match: { from_domain: hornbach.de }
grant: FULL
- match: { from_domain: amazon.de }
grant: FULL
- path: Archive
mode: whitelist
default: NONE
accept_incoming: true
rules: []
```
#### 文件夹策略字段
| 字段 | 必需 | 默认值 | 描述 |
|---|---|---|---|
| `path` | 是 | — | IMAP文件夹路径(例如`INBOX`、`INBOX/Invoices`、`[Gmail]/All Mail`) |
| `mode` | 是 | — | `whitelist`(默认=NONE,规则授予访问权限)或`blacklist`(默认>NONE,规则限制访问) |
| `default` | 是 | — | 当没有规则匹配时的默认可见性级别 |
| `rules` | 否 | `[]` | 发送者特定的覆盖(见下文) |
| `mark_seen` | 否 | `false` | 可以切换`\Seen`标志 |
| `mark_tagged` | 否 | `false` | 可以设置关键词和`\Flagged` |
| `move_out` | 否 | `false` | 可以从此文件夹中删除消息 |
| `accept_incoming` | 否 | `false` | 可以接收移动/复制的消息 |
| `draft_append` | 否 | `false` | 可以追加新的草稿 |
#### 可见性级别
每个规则授予以下层次结构中的一个级别:
```
NONE < COUNT < METADATA < ENVELOPE < HEADERS < BODY < FULL
```
| 级别 | 暴露内容 |
|---|---|
| `NONE` | 无(消息不可见) |
| `COUNT` | 仅消息数量(`folder_stats`) |
| `METADATA` | UID、大小、标志(`search`) |
| `ENVELOPE` | 发件人、收件人、主题、日期(`fetch_envelope`、`list_messages`) |
| `HEADERS` | 完整的RFC 5322头部块(`fetch_headers`) |
| `BODY` | 明文和HTML正文(`fetch_body`) |
| `FULL` | 包括附件在内的所有内容(`fetch_attachment`) |
#### 发送者规则语法
规则使用一组封闭的谓词。同一规则内的谓词通过AND组合;文件夹中的多个规则通过OR组合。
| 谓词 | 类型 | 示例 |
|---|---|---|
| `from` | 精确邮箱 | `alice@example.com` |
| `from_domain` | 域名(不区分大小写,容忍尾随点) | `hornbach.de` |
| `to` | 精确邮箱 | `billing@company.com` |
| `to_contains` | 子字符串 | `team` |
| `subject_contains` | 子字符串(不区分大小写,NFC标准化) | `rechnung` |
| `has_attachment` | 布尔值 | `true` |
| `flagged` | 布尔值 | `true` |
| `newer_than` | 时长 | `30d` |
| `older_than` | 时长 | `90d` |
| `size_gt` | 字节 | `10000` |
| `size_lt` | 字节 | `1500` |
在`whitelist`模式下,规则使用`grant: <level>`。在`blacklist`模式下,规则使用`cap: <level>`。在一个文件夹中混合使用两者是一个解析时错误。
`flagged`谓词与IMAP `\Flagged`标志(Gmail中为星标)匹配,从而实现类似“授予对所有星标消息的完全访问权限”的规则:
```yaml
- path: INBOX
mode: whitelist
default: NONE
rules:
- match: { flagged: true }
grant: FULL
```
## MCP工具表面
十九种工具,每种工具都受到一个可见性级别或一个能力的限制。
### 读取工具(10)
| 工具 | 最低可见性 | 描述 |
|---|---|---|
| `list_accounts` | — | 列出可见账户 + `hidden_accounts_count` |
| `list_folders` | COUNT | 列出可见文件夹 + `hidden_folders_count` |
| `list_labels` | COUNT | 仅限Gmail:列出带有标志的标签 |
| `list_messages` | ENVELOPE | **主要读取邮件工具。** 返回每条消息的发件人、主题、日期。支持条件和分页。 |
| `folder_stats` | COUNT | 按可见性级别显示消息数量 |
| `search` | METADATA | 使用`matched_total` / `matched_visible` / `filtered_out`搜索UID |
| `fetch_envelope` | ENVELOPE | 获取单个消息的发件人、收件人、主题、日期,UID |
| `fetch_headers` | HEADERS | 完整的RFC 5322头部 |
| `fetch_body` | BODY | 明文和HTML正文 |
| `fetch_attachment` | FULL | MIME附件字节 |
### 写入工具(6)
| 工具 | 所需能力 | 描述 |
|---|---|---|
| `mark_seen` | `mark_seen` | 切换单个消息的`\Seen`标志 |
| `bulk_mark_seen` | `mark_seen` | 切换所有匹配条件的消息的`\Seen`标志 |
| `mark_tagged` | `mark_tagged` | 添加/删除关键词 |
| `move` | `move_out` + `accept_incoming` | 移动消息(账户内:原生MOVE;跨账户:传奇) |
| `copy` | `accept_incoming` | 复制消息到目标文件夹 |
| `create_draft` | `draft_append` | 追加RFC 5322草稿 |
### 元工具(3)
| 工具 | 描述 |
|---|---|
| `describe_policy` | 调用者的策略配置文件(账户、文件夹、能力、隐藏计数)。永远不会泄露规则模式或其他调用者。 |
| `get_caller_identity` | 当前会话的已解析`caller_id` |
| `get_transaction_status` | 跨账户传奇的WAL状态 |
### 故意缺失
`delete`、`expunge`、`raw_imap_command`、`fetch_raw_rfc822`、跨账户搜索、MCP资源订阅、文件夹CRUD、通过MCP策略重载。参见[ADR 0018](docs/adr/0018-non-goal-tool-surface.md)。
## 环境变量
| 变量 | 必需 | 描述 |
|---|---|---|
| `IMAP_MCP_CONFIG_DIR` | 是 | 配置目录的路径 |
| `IMAP_MCP_CALLER_ID` | 仅限stdio_trusted | stdio传输的调用者身份 |
| `IMAP_MCP_OAUTH_CLIENT_ID` | xoauth2账户 | 来自GCP控制台的OAuth2客户端ID |
| `IMAP_MCP_OAUTH_CLIENT_SECRET` | xoauth2账户 | 来自GCP控制台的OAuth2客户端密钥 |
| `IMAP_MCP_HTTP_HOST` | 否 | HTTP的绑定地址(默认:`127.0.0.1`) |
| `IMAP_MCP_HTTP_PORT` | 否 | HTTP的端口(默认:`0` = 临时) |
| `IMAP_MCP_APPEND_TIMEOUT` | 否 | IMAP追加的超时秒数 |
| `OTEL_EXPORTER_OTLP_ENDPOINT` | 否 | 跟踪的OTLP端点(例如`http://localhost:4317`) |
## OAuth2启动
对于具有`auth.type: xoauth2`的账户(例如Gmail),请为每个账户运行交互式启动以获取刷新令牌:
```bash
IMAP_MCP_CONFIG_DIR=~/.config/imap-mcp \
IMAP_MCP_OAUTH_CLIENT_ID=your-client-id.apps.googleusercontent.com \
IMAP_MCP_OAUTH_CLIENT_SECRET=your-client-secret \
imap-mcp-oauth-bootstrap --account user@company.com
```
这会打印一个URL。在浏览器中打开它,完成Google同意流程,然后将重定向URL粘贴回终端。成功后,刷新令牌存储在秘密存储中。然后服务器会自动用它交换访问令牌。
### 设置GCP OAuth客户端
1. 前往 https://console.cloud.google.com/apis/credentials
2. 创建凭证 > OAuth客户端ID > 桌面应用
3. 复制客户端ID和客户端密钥
4. 将它们用作`IMAP_MCP_OAUTH_CLIENT_ID`和`IMAP_MCP_OAUTH_CLIENT_SECRET`
## 跟踪(可选)
安装时带有跟踪支持,并启动Jaeger:
```bash
pip install sc-imap-mcp[tracing]
cd ops/tracing && docker compose up -d
# 添加到MCP服务器配置:
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
```
打开 http://localhost:16686 访问Jaeger UI。每个MCP工具调用都会创建一个带有嵌套IMAP连接和身份验证跨度的轨迹。
## 策略重载
向正在运行的服务器进程发送`SIGHUP`。服务器重新解析整个配置目录,验证它,并原子地交换内存状态。解析或验证错误保留先前的策略,并写入带有错误的审计记录。
```bash
kill -HUP $(pidof imap-mcp)
```
## Gmail支持
具有`provider: google`的账户具有明确的Gmail语义:
- 可用的`list_labels`工具(仅限Gmail)
- 搜索结果包括`canonical_all_mail_uid`用于跨标签重复数据删除
- 账户内的`move`实现为标签交换(非物理MOVE)
- 跨账户传奇从`[Gmail]/All Mail`中确定性地获取
- `[Gmail]/Trash`、 `[Gmail]/Drafts`等是策略可寻址的文件夹
- 本地化文件夹名称(例如德语中的`[Gmail]/Entwürfe`)通过RFC 6154特殊用途标志解析为规范路径
## 审计日志
仅追加JSONL,带有SHA-256哈希链,每个UTC日一个文件。严格的无内容泄漏规则:DENY记录中没有消息正文、主题、附件文件名、OAuth令牌或明文发件人地址。
## 实现栈
- **语言:** Python 3.11+
- **IMAP:** `aioimaplib`(IMAP4和IMAP4_SSL)
- **MCP:** 官方`mcp`SDK(stdio + HTTP/SSE)
- **存储:** `aiosqlite`用于WAL;YAML用于配置
- **验证:** `pydantic` v2(严格模式)
- **OAuth:** `httpx` +第一方流程实现
- **跟踪:** OpenTelemetry(可选,通过`[tracing]`额外功能)
- **测试:** `pytest`(属性测试)+ `behave`(BDD,241个场景)
## 测试
```bash
# BDD套件(需要Docker进行IMAP固件)
cd bdd && docker compose -f docker/docker-compose.yml up -d
.venv/bin/behave --no-color --format=progress features/
# 服务器属性测试
cd server && .venv/bin/pytest tests/policy/ -q
```
## 文档
设计在 [`docs/adr/`](docs/adr/) 下的23个ADR中捕获。限制记录在 [`docs/limitations/`](docs/limitations/) 下。错误路径分析在
[`docs/error_path_analysis.md`](docs/error_path_analysis.md)。
## 许可
GPL-3.0-or-later。参见 [`LICENSE`](LICENSE)。
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器