Cloud Mail MCP
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Cloud Mail MCPsearch my inbox for emails about invoices and summarize the latest one"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Cloud Mail MCP
为 maillab/cloud-mail 提供 MCP 接入。Agent 使用专用邮箱用户的 HTTPS API 权限列出、搜索和读取邮件,管理本地草稿,发送/回复邮件,获取附件及标记已读。
使用 TypeScript 与官方 MCP SDK v2,通过 stdio 运行。服务支持 SDK 提供的 2025 协议兼容入口及 2026-07-28 协议入口。
Agent 的 MCP 客户端 → 本地 cloud-mail-mcp → 邮箱 HTTPS API
│ └→ Worker → D1 / R2 / Resend
└→ 用户隔离的本地草稿和发送回执安装与接入
需要 Node.js 22.16+(推荐使用部署环境已有的 Node.js 24)、npm,以及管理员创建的专用邮箱用户。
git clone https://github.com/Fluma-Intelligence/cloud-mail-mcp.git
cd cloud-mail-mcp
npm ci --ignore-scripts
npm run build
cp .env.example .env
chmod 600 .env在本机编辑 .env:设置 MAIL_BASE_URL 为邮箱应用域名,例如 https://mail.fluma.ai,并配置专用用户的 MAIL_EMAIL / MAIL_PASSWORD。也可以只设置 MAIL_TOKEN,其值为 /api/login 返回的原始用户 JWT。
将 examples/mcp.json 合并至支持 stdio 的 Agent 客户端配置,替换其中两处绝对路径:
{
"mcpServers": {
"cloud-mail": {
"command": "node",
"args": [
"--env-file=/absolute/path/to/cloud-mail-mcp/.env",
"/absolute/path/to/cloud-mail-mcp/dist/index.js"
]
}
}
}由 MCP 客户端启动进程并管理其生命周期。stdout 专用于协议消息;启动错误写入 stderr。
可以先运行只读连通性检查,输出工具数量和检查结果:
node --env-file=.env examples/smoke.mjs需要发送、回复或标记已读时,设置 MAIL_ENABLE_WRITE=true 后重启 MCP。管理员应为专用用户授予 account:query,发信时授予 email:send,并配置可用域名、发信模式和发送额度。
Related MCP server: imap-mcp
发信接入
MCP 发信工具包括 send_message(新邮件)、send_draft(发送本地草稿)和 reply_message(回复收件箱邮件),均支持附件。发件身份由当前用户的 accountId 决定,省略时使用主邮箱;其他发件地址的 ID 从 list_mailboxes 获取。
将 examples/mcp-send.json 合并到 Agent 的 MCP 配置,替换安装路径。此配置通过 env.MAIL_ENABLE_WRITE=true 开启发信;同名的 cloud-mail 连接应更新原配置。重启连接后调用 mail_status,确认邮箱身份与 mailboxWritesEnabled:true,并重新发现上述工具。写入开关也会开放 mark_read;实际发信仍需邮箱角色的 email:send 权限与可用额度。
运行发送示例
完成上面的源码安装后,也可通过示例客户端调用同一套 MCP 发信工具。在私密 .env 中设置 MAIL_ENABLE_WRITE=true,然后准备发送请求:
cp examples/send-message.example.json send.private.json
chmod 600 send.private.json在本机编辑 send.private.json 的收件人、主题、正文及附件,并将 operationKey 替换为本次发送的唯一标识,例如保存一次生成的 UUID。该文件包含真实邮件时保留在私密目录;仓库已忽略 *.private.json。
下面的命令会立即发送文件中的邮件,输出 API 受理回执:
node --env-file=.env examples/send.mjs send.private.jsonsend.mjs 也接受使用 send_draft 或 reply_message 的请求文件,参数见下文工具调用示例。附件 content 为标准 Base64;发送全部附件的解码总大小受 MAIL_MAX_ATTACHMENT_BYTES 限制。
按发送时保存的 operationKey 查询回执:
node --env-file=.env examples/send.mjs --status YOUR_SAVED_OPERATION_KEY回执查询可在关闭写入时使用。accepted 表示 API 已受理;最终投递需在收件端确认。发送超时或 pending 时先核对回执与发件箱;保留同一 operationKey 和状态目录,按下文恢复流程处理。
配套 Skills
仓库附带三个可独立安装的技能,每个目录包含 SKILL.md 与 agents/openai.yaml。技能指导 Agent 使用现有 MCP 工具;安装后仍需按上节配置连接与邮箱凭据。
Skill | 用途 | 调用示例 |
接入配置、权限检查、只读验证、更新与状态恢复 |
| |
邮箱选择、分页搜索、正文摘要、附件、按需标记已读 |
| |
本地草稿、附件发送、线程回复、回执核对 |
|
Multica 工作区
导入每个技能目录;默认遇到同名技能会报冲突,避免覆盖已有配置:
for skill in cloud-mail-setup cloud-mail-read cloud-mail-send; do
multica skill import \
--url "https://github.com/Fluma-Intelligence/cloud-mail-mcp/tree/main/skills/$skill" \
--output json || break
done导入成功后,技能出现在工作区技能库。需要指定 Agent 使用时,在其配置中添加技能并配置 MCP;也可使用 multica agent skills add <agent-id> --skill-ids <skill-id>,再以 multica agent skills list <agent-id> --output json 验证。ID 使用导入结果和 Agent 查询返回的实际值;add 保留已有技能。
本机 Codex
在仓库根目录执行以下命令,将完整技能目录复制到个人技能目录;已存在的同名目录会跳过:
mkdir -p "$HOME/.agents/skills"
for skill in cloud-mail-setup cloud-mail-read cloud-mail-send; do
if [ -e "$HOME/.agents/skills/$skill" ]; then
printf '已存在,跳过:%s\n' "$skill"
else
cp -R "skills/$skill" "$HOME/.agents/skills/"
fi
done重新打开会话,确认技能出现在可用技能列表。团队也可放到目标项目的 .agents/skills/;目录规则见 官方技能文档。其他支持 SKILL.md 的客户端按其安装规则导入完整目录。
技能包含搜索未完成时的续查、草稿版本冲突、回复线程及发送结果不确定时的处理。已读标记和发送遵循用户任务授权;邮件与附件内容按外部数据处理。
配置
参数 | 用途 | 默认值 |
| 邮箱应用 HTTPS origin;接受末尾 | 必填 |
| 专用用户登录 | 与 |
| 原始用户 JWT;同时提供密码时可在读取遇到会话失效后重新登录 | 空 |
| 暴露发信、回复、发送草稿和已读标记工具 |
|
| 允许发送的完整邮箱地址,逗号分隔;空值使用邮箱角色允许的范围 | 空 |
| 本地草稿、发送回执根目录;使用绝对路径便于备份 |
|
| 单次邮箱请求超时,100–120000 ms |
|
| 单个下载、一次发送全部附件的解码大小上限,最多 5 MiB |
|
服务只接受配置的邮箱 origin。HTTP 限于 loopback 本地测试;凭据请求和附件下载均不跟随重定向。
工具
默认提供 13 个工具,开启邮箱写入后共 17 个。
工具 | 功能与主要参数 |
| 当前邮箱身份、权限、写入开关和附件上限 |
| 列出当前用户的邮箱;使用返回的 |
|
|
|
|
|
|
| 指定邮件的附件元数据 |
| 指定邮件与 |
| 保存当前用户的本地草稿,支持附件 |
| 本地草稿摘要 |
| 按 |
| 使用当前 |
| 使用 |
| 根据 |
| 写入:立即发送邮件,必须提供 |
| 写入:回复收件箱邮件的发件人,保留上游线程关联 |
| 写入:发送指定草稿版本,保留本地草稿 |
| 写入:对当前邮箱内的 |
accountId 缺省使用当前用户主邮箱;folder 为 inbox 或 sent,缺省 inbox。所有邮件列表固定限制到所选邮箱。对其他用户的账号、邮件、附件的请求会被拒绝。
搜索使用普通用户的分页接口,在 MCP 内匹配主题、发件人、收件人及正文。每页至多 50 封,默认最多 5 页。exhausted=false 表示结果未覆盖全部剩余邮件;继续传入 nextBeforeId,直至 exhausted=true。正文搜索含原始 HTML。
读取单封邮件使用上游“严格小于 emailId”的游标规则定位,并核对返回 ID、用户和邮箱归属。正文文本和 HTML 各最多返回 100000 字符,超过时 bodyTruncated=true。
调用示例
以下对象可传给 MCP 客户端的 callTool。SDK 的完整只读调用示例见 examples/smoke.mjs。
列出最近邮件:
{"name":"list_messages","arguments":{"folder":"inbox","limit":20}}搜索主题并读取结果中的邮件 ID:
{"name":"search_messages","arguments":{"query":"项目进度","field":"subject","maxPages":5}}{"name":"get_message","arguments":{"emailId":123,"folder":"inbox"}}保存带有合成附件的草稿:
{
"name":"create_draft",
"arguments":{
"to":["test-recipient@example.com"],
"subject":"MCP 验证",
"text":"这是一封测试邮件。",
"attachments":[{"filename":"hello.txt","type":"text/plain","content":"aGVsbG8="}]
}
}发送草稿时,使用返回的 id 与 revision:
{"name":"send_draft","arguments":{"draftId":"00000000-0000-4000-8000-000000000000","revision":1,"operationKey":"mail-test-001"}}直接发送与回复:
{"name":"send_message","arguments":{"to":["test-recipient@example.com"],"subject":"测试","text":"测试内容","operationKey":"mail-test-002"}}{"name":"reply_message","arguments":{"emailId":123,"text":"已收到。","operationKey":"mail-reply-001"}}附件与已读标记:
{"name":"list_attachments","arguments":{"emailId":123}}{"name":"download_attachment","arguments":{"emailId":123,"attachmentId":7}}{"name":"mark_read","arguments":{"emailIds":[123]}}所有示例地址和 ID 都是占位值;执行发送示例前使用实际获授权的测试收件人和查询返回的 ID。
发送回执与恢复
operationKey 标识一封具体邮件的发送意图。同一个 key、同样内容的重试在已有成功回执时返回该回执;同 key 改变内容会被拒绝。此保护在共享同一状态目录的 MCP 进程之间生效。
发送前先原子创建 pending 记录,发送成功后保存 accepted 回执。连接断开、超时或进程异常可能留下 pending:此时工具返回 SEND_UNCERTAIN,并阻止再次发送。通过 get_send_status 查询,结合邮箱发件箱与服务商投递记录核实后再决定下一步。accepted 表示邮箱 API 受理,deliveryConfirmed=false 表示尚未验证最终投递。
更新与恢复步骤:
关闭使用该安装目录的 MCP 客户端,备份
.env和MAIL_STATE_DIR。切换到所需 Git 版本,执行
npm ci --ignore-scripts与npm run check。保留原状态目录,重启客户端并调用
mail_status。恢复时使用同一邮箱 origin 和用户,恢复其状态目录;核对
pending回执后再恢复发送。
草稿更新使用版本号防止覆盖其他编辑。若进程在编辑时异常退出留下 .lock 文件,维护者确认所有相关进程已停止并备份目录后,可删除对应锁文件;发送回执应保留用于核对。
开发与验证
npm run check
npm pack --dry-run集成测试启动真实 MCP 子进程,使用官方客户端进行握手、工具发现与调用,并连接本地模拟邮箱 HTTP 服务。测试覆盖两代协议入口、JWT/密码认证、分页搜索、归属校验、附件限制、草稿持久化和版本冲突、发送/回复、并发与重启后的重复发送防护、结果不确定时的处理、已读标记和业务错误。
源码契约基于上游 ec7a2bb 版本。持续集成在 Node.js 22 和 24 上执行构建与测试。
代码入口:src/client.ts 为邮箱 API 适配,src/server.ts 为 MCP 工具,src/store.ts 为本地草稿与回执,src/config.ts 为配置。
边界与安全
本版本为单个邮箱用户的本地 stdio 服务。远程 HTTP 托管、调用者登录与多租户身份映射属于后续扩展。
草稿属于本地 MCP 状态,不会出现在 cloud-mail 网页草稿箱。草稿目前要求至少一个收件人和正文;跨端共享草稿需要后端能力。
搜索是受限分页扫描;标记未读、回复全部和按任意服务商 URL 下载附件暂未提供。
当前测试使用合成邮件和模拟服务,真实 Cloudflare/Resend 环境的收发与附件链路需使用专用测试邮箱验收。
examples/smoke.mjs只验证登录和读取接口。上游 API 缺少端到端幂等键。不同状态目录、丢失回执、手工更换操作标识或底层存储故障仍可能造成重复投递;无法承诺服务商层面的 exactly-once。
凭据由环境变量或本地私密文件注入,不经工具参数传递。草稿含正文与附件,回执含邮件标识;数据文件默认
0600、用户目录0700,状态目录与备份按邮箱数据保护。权限、配额仍由邮箱角色控制。MCP 返回的邮件和附件是外部数据。发送需属于用户授权的任务范围;客户端应按工具的写入标注和自身权限策略执行。
许可证
MIT,见 LICENSE。MCP SDK 文档见 官方 TypeScript SDK。
Available Tools
13 toolscreate_draftCDestructive
Save a local draft for this user. Drafts persist across MCP restarts and are separate from browser drafts.
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | ||
| html | No | ||
| text | No | ||
| subject | Yes | ||
| accountId | No | ||
| attachments | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the write/safety profile (readOnlyHint=false, destructiveHint=true, idempotentHint=false, openWorldHint=false). The description adds genuinely useful context -- drafts persist across MCP restarts and are distinct from browser drafts -- but it omits why destructiveHint is set (e.g. overwrite behavior) or any auth/account requirements.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences with the core action front-loaded and no filler. It is well-sized, though the second sentence could be trimmed slightly without losing meaning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 6-parameter mutation tool with no output schema and zero parameter descriptions anywhere, the definition leaves critical gaps: required fields (to, subject), body content selection (html vs text), attachment handling, and the non-idempotent/destructive behavior are all unaddressed. Persistence is covered, but an agent lacks the information to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% across 6 parameters, including a nested attachments object with base64 content, and the description says nothing about any of them (to, subject, html/text body, accountId, attachments). With low coverage the description is expected to compensate, and it does not.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Save a local draft'), and the qualifier 'local' plus 'separate from browser drafts' clarifies the domain. It does not differentiate from the sibling write tools (update_draft, delete_draft), but the core purpose is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to use create_draft versus update_draft, or whether a draft should be created before sending. The persistence and browser-draft statements are contextual facts, not usage routing, so an agent gets no when-to-use/when-not signal.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_draftCDestructiveIdempotent
Delete a local draft using its current revision.
| Name | Required | Description | Default |
|---|---|---|---|
| draftId | Yes | ||
| revision | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, idempotentHint=true, and openWorldHint=false, so the safety profile is largely covered structurally. The phrase 'using its current revision' adds genuine behavioral context by implying optimistic-concurrency semantics, but the description never says what happens on a revision mismatch, whether deletion is recoverable, or that the operation is irreversible — gaps the agent would want filled for a destructive tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One short sentence with no filler, and the core action leads. It is arguably under-specified rather than verbose, but as a structural matter it is tight and front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive mutation with 0% parameter coverage, no output schema, and two required params, the description omits concurrency failure behavior, recoverability, and any post-delete state. The annotations supply the safety hints, but the description does not complete the picture an agent needs to invoke this safely.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden, and it only gestures at the 'revision' parameter ('its current revision') without specifying that it must match the draft's current revision or what a mismatch produces. The draftId parameter gets no explanation at all beyond the name, leaving both required params thinly documented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource, 'Delete a local draft', which is unambiguous against siblings like create_draft, get_draft, and update_draft. It adds the qualifier 'local draft' and the revision condition, but does not explicitly contrast itself with any sibling, so it falls short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no when-to-use guidance, no statement of prerequisites such as needing the latest revision fetched via get_draft, and no mention of alternatives. The only implied usage is that the draft must be local and have a revision.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
download_attachmentBRead-onlyIdempotent
Read an attachment from an owned message as Base64; subject to MAIL_MAX_ATTACHMENT_BYTES.
| Name | Required | Description | Default |
|---|---|---|---|
| folder | No | inbox | |
| emailId | Yes | ||
| accountId | No | ||
| attachmentId | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly=true, idempotent=true, destructive=false and openWorld=true, so safety is covered. The description adds genuinely new behavior: the payload comes back as Base64 and is bounded by MAIL_MAX_ATTACHMENT_BYTES, a size constraint the annotations do not express.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One front-loaded sentence carrying the action, encoding, and limit with zero filler. Every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read tool with no output schema and full annotation coverage, the description adequately covers format and size cap. It still leaves open what happens when the attachment exceeds MAIL_MAX_ATTACHMENT_BYTES (failure vs truncation) and leaves all four parameters unexplained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% across four parameters (emailId, attachmentId, folder, accountId), and the description compensates only faintly by implying an attachment belongs to a message it owns. It says nothing about the inbox/sent enum, the accountId scoping, or required-vs-optional behavior.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Read an attachment from an owned message') plus the return encoding (Base64), which is enough to distinguish it from list_attachments. It does not name or contrast any sibling explicitly, so it falls short of the 5 bar.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'from an owned message' hints at a scope prerequisite, but there is no statement of when to reach for this tool versus list_attachments (discover the attachmentId first) or get_message. No alternatives or exclusions are offered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_draftBRead-onlyIdempotent
Read a local draft including content and attachment data.
| Name | Required | Description | Default |
|---|---|---|---|
| draftId | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive and closed-world, so the safety profile is covered. The description adds that content and attachment data are included in the result, which is useful, but it says nothing about behavior for an unknown or deleted draftId, or whether attachments are inlined versus referenced.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One front-loaded sentence with no filler; the return payload is stated before any hypothetical detail. It is arguably too terse for the surrounding draft CRUD family, but nothing in it is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter read with no output schema, the description is minimally sufficient: it says what comes back, which is the main thing an agent cannot infer. It stops short of covering the not-found case and the local-versus-remote distinction that the sibling set makes relevant.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the sole parameter draftId carries only a uuid format and pattern in the schema. The description never explains that draftId is the local draft identifier or where to obtain it, but with a single self-evident ID parameter this is a minor gap rather than a blocking one.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Read') and resource ('a local draft') plus the payload the caller gets back ('content and attachment data'). The word 'local' distinguishes it from a server-side message fetch, though it never names list_drafts or get_message explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: 'local draft' plus a required draftId suggests fetching one known draft rather than enumerating, which is what list_drafts is for. There is no explicit when-to-use statement, no exclusions, and no mention of how this differs from get_message or create_draft/update_draft.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_messageARead-onlyIdempotent
Read one owned message including text and HTML. Does not mark it read. Folder defaults to inbox.
| Name | Required | Description | Default |
|---|---|---|---|
| folder | No | inbox | |
| emailId | Yes | ||
| accountId | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint=true, so the safety profile is covered. The description adds genuinely useful non-obvious behavior: it returns text and HTML content, and critically that reading does not mark the message read — an effect annotation hints at but does not state.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short, front-loaded sentences with no filler: purpose first, then the important side-effect disclosure, then the folder default. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only tool with no output schema and annotations covering safety, the description is adequate on behavior and content. The gap is parameter coverage: with 0% schema descriptions, emailId and accountId are undocumented anywhere, which matters for a tool needing to locate a specific message.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage and 3 parameters, the description carries the burden and does not meet it. The only parameter detail given ('folder defaults to inbox') merely repeats the schema's default value, and neither emailId nor accountId is explained at all, so an agent gets no guidance on identifying the message or selecting an account.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Read') and a precisely scoped resource ('one owned message including text and HTML'), which distinguishes it from list_messages and search_messages by signaling single-item retrieval. It does not name a sibling explicitly, so the differentiation is implied rather than stated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Read one owned message' implies this is the single-item lookup versus the list/search siblings, and the folder default hints at mailbox context. However, there is no explicit when-to-use or when-not-to-use guidance and no named alternative for scenarios like retrieving many messages.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_send_statusARead-onlyIdempotent
Read the local receipt for an operationKey. accepted means API acceptance; pending requires reconciliation before any retry.
| Name | Required | Description | Default |
|---|---|---|---|
| operationKey | Yes | Stable unique key for this exact send. Reuse for retries; never change it after an uncertain result. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, closed-world behavior, so the bar is lower. The description adds genuinely useful context beyond them: the receipt is local (not an authoritative server round-trip) and defines two return states, 'accepted' as API acceptance and 'pending' as requiring reconciliation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two dense sentences, zero filler, with the core action and the meaning of each status front-loaded in the order an agent needs them.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so the description should convey the return states; it explains 'accepted' and 'pending' but does not enumerate other possible states (e.g., rejected, unknown) or the staleness implications of reading a local receipt. For a one-parameter read tool this is close to complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the operationKey description already covers stability, reuse on retry, and immutability after uncertain results. The description confirms the key scopes a single send but adds no syntax or format detail beyond the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Read the local receipt for an operationKey') and the word 'local' implicitly contrasts with server/API status checks. It does not, however, name or differentiate itself from the sibling mail_status, which an agent could easily confuse with a send-status lookup.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives an operational rule tied to a result state ('pending requires reconciliation before any retry'), which implies this is the tool to call after an uncertain send. It never states when to prefer it over mail_status or what to do if the key is unknown, so selection guidance is only implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_attachmentsCRead-onlyIdempotent
List attachment metadata for an owned message.
| Name | Required | Description | Default |
|---|---|---|---|
| folder | No | inbox | |
| emailId | Yes | ||
| accountId | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false and openWorldHint=true, so the safety profile is fully covered. The description adds only that results are 'metadata' (not content) and that the message must be 'owned' — modest but non-redundant context; nothing is said about pagination, empty results, or ordering.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single efficient sentence with the resource front-loaded and zero filler. It is appropriately sized for a one-line tool, though its brevity contributes to the gaps noted elsewhere.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, no annotations gap on safety, and three parameters at 0% schema coverage, the description should describe what attachment metadata is returned (name, size, mime type, id) and how folder/accountId affect the lookup. It supplies none of this, leaving the agent unable to predict the response.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% and the description names none of the three parameters. The inbox/sent 'folder' enum and the 'accountId' scoping parameter are completely undocumented anywhere, and 'emailId' is only hinted at via 'owned message'. The description fails to compensate for the coverage gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List attachment metadata') and scopes it to an owned message, which implicitly contrasts with download_attachment's content retrieval. However, it never names the sibling or clarifies the metadata-vs-content boundary explicitly, so an agent must infer the differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No when-to-use guidance, no prerequisites (e.g. that an emailId from list_messages/get_message is required), and no mention of download_attachment as the alternative for retrieving actual file contents. The agent is left to infer the call context entirely.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_draftsARead-onlyIdempotent
List drafts stored locally for the authenticated user.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, non-destructive and closed-world, so the safety profile is fully covered. The description adds one genuinely useful behavioral fact — that the listing is limited to locally stored drafts — but says nothing about ordering, limits, or result size.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler; the scope qualifier arrives immediately after the verb and resource. Nothing in it is redundant with the title or schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter read tool with full annotation coverage this is close to sufficient, but there is no output schema, so the description is the only place an agent could learn what a 'draft' entry contains, in what order results come back, or whether the list is bounded.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is no parameter semantics for the description to carry; the baseline for a no-param tool is 4. The description adds no misleading input expectations.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List drafts') plus a scope qualifier ('stored locally for the authenticated user'), which separates it from server-side listing tools. It does not name the sibling it contrasts with (e.g., list_messages or get_draft), so an agent must infer the boundary from the resource noun alone.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied by the name and the 'local drafts' scoping — the description never says when to call this versus get_draft for a single draft or list_messages for the inbox. No prerequisites, no exclusions, no alternatives are named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_mailboxesCRead-onlyIdempotent
List owned mailbox addresses. Pass nextCursor fields for the next page.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| lastSort | No | ||
| afterAccountId | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint, so the safety profile is covered. The description adds useful pagination context ('pass nextCursor fields for the next page'), which annotations do not convey. However, it refers to 'nextCursor fields,' a name that appears nowhere in the schema, which muddies rather than clarifies the actual cursor fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences with the core action front-loaded and pagination second. No filler, though the second sentence is spent on a field name that does not exist.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so the description could have described the returned shape and how paging terminates, but it does not. With all three parameters undocumented and an incorrect cursor field reference, an agent lacks what it needs to page correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% and none of the three parameters (limit, lastSort, afterAccountId) are explained: no meaning, ranges, or defaults. The only nod to parameters is 'nextCursor fields,' which does not match any actual parameter name, so it does not compensate for the coverage gap and may actively mislead.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific verb and resource ('List owned mailbox addresses'), so an agent immediately knows this returns mailbox addresses rather than messages or drafts. It does not explicitly name a sibling or state how it differs from them, but the resource is distinctive enough within the sibling set to be unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when this tool should be chosen, no prerequisites, and no mention of alternatives among the many list_* siblings. The single pagination sentence is procedural, not routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_messagesARead-onlyIdempotent
List one mailbox folder, newest first. Reading does not mark messages as read.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| folder | No | inbox | |
| beforeId | No | ||
| accountId | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false, so the safety profile is covered. The description still adds two non-obvious behavioral facts the annotations do not: results are ordered newest first, and reading does not mark messages as read. It omits pagination/return-shape behavior, so not a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, zero filler, and the scope/ordering constraint is front-loaded before the side-effect note.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple list tool with all-optional parameters and no output schema, the description covers scope, ordering and read-state side effects, and annotations cover safety. It is still incomplete on paging (beforeId) and folder/account semantics, which an agent needs to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% and there are four parameters (limit, folder, beforeId, accountId), so the description carries the full burden. It says nothing about folder selection, result limits, beforeId-based paging, or account scoping, leaving every parameter semantically bare.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (list) and resource (messages in one mailbox folder) plus ordering, which distinguishes it from list_mailboxes and get_message. It does not explicitly differentiate from search_messages, so it falls short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the scope phrase 'one mailbox folder, newest first', which suggests a browsing/fetch-recent flow rather than a query. There is no explicit when-to-use, when-not-to-use, or named alternative such as search_messages.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mail_statusARead-onlyIdempotent
Get the authenticated mailbox identity, permissions and MCP configuration.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, openWorldHint, and destructiveHint=false, so the safety profile is covered. The description adds some value by scoping what is reported (identity, permissions, MCP configuration), but says nothing about auth requirements, cost, or failure modes for an open-world call.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler, restatement of the name, or trailing caveats. It is exactly the right size for a zero-parameter status tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description must convey what comes back; it does list the three categories of returned information, though only at a high level. For a parameterless read-only status call this is nearly complete, missing only a sense of when an agent should reach for it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing for the description to disambiguate beyond what the schema establishes. Baseline 4 applies for a parameterless tool; the description neither helps nor hurts here.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb ('Get') and a concrete set of resources: authenticated mailbox identity, permissions, and MCP configuration. It is unambiguous about what is returned, though it does not contrast itself with siblings like list_mailboxes or list_messages.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to call this tool versus the many sibling list/get tools, and no mention of prerequisites or typical contexts (e.g., verifying auth before other operations). Usage must be inferred entirely from the tool name and returned subject matter.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_messagesBRead-onlyIdempotent
Search owned mailbox pages by substring (case-insensitive). exhausted=false means partial results; continue with nextBeforeId. Body search includes raw HTML.
| Name | Required | Description | Default |
|---|---|---|---|
| field | No | all | |
| query | Yes | ||
| folder | No | inbox | |
| beforeId | No | ||
| maxPages | No | ||
| accountId | No | ||
| maxResults | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With readOnlyHint/idempotentHint already declaring the safety profile, the description still earns credit by disclosing pagination behavior (partial results signaled by exhausted=false, resume via nextBeforeId) and a real caveat that body search returns raw HTML. The cursor field is called 'nextBeforeId' while the schema parameter is 'beforeId', which introduces some naming ambiguity.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three dense sentences with zero filler; the core matching rule and the partial-result rule are front-loaded. Nothing is redundant with the title or the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description must carry return-value semantics, and it does explain the exhausted flag and the resume cursor but not the result shape or ordering. For a 7-parameter, open-world search tool, the missing field/folder/limit semantics leave it only minimally complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% across 7 parameters, so the description carries the burden but only covers the query semantics (case-insensitive substring) and body matching. Field, folder, maxPages, maxResults, beforeId, and accountId are left entirely unexplained, including their defaults and bounds, for a search tool where field/folder selection is the main scoping decision.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (search), resource (owned mailbox pages), and matching mechanism (case-insensitive substring), so the operation is immediately legible. It does not, however, differentiate itself from the sibling list_messages or get_message, so an agent must infer which retrieval tool fits which case.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no statement of when to use search_messages versus list_messages or get_message, and no prerequisites (e.g. whether accountId is required when multiple accounts exist). The continuation hint ('exhausted=false ... continue with nextBeforeId') is behavioral rather than a use-case guideline.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_draftBDestructive
Replace a local draft using its current revision to prevent lost edits.
| Name | Required | Description | Default |
|---|---|---|---|
| draftId | Yes | ||
| message | Yes | ||
| revision | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, readOnlyHint=false, and non-idempotency, so the safety profile is covered. The description adds genuine extra context by explaining that the revision is used for optimistic concurrency ('to prevent lost edits'), but it omits the failure mode when the revision is stale and the fact that the entire draft is overwritten.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no wasted words, and the concurrency rationale is embedded efficiently rather than padded out.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive mutation with three required parameters, a nested message object, and no output schema, the description is too thin. It does not say what happens on a revision conflict, whether the replacement is total, or how the nested message payload relates to the existing draft.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% for the top-level parameters, so the description carries the burden. It clarifies the purpose of 'revision' but says nothing about 'draftId' or the complex nested 'message' object (to/subject/html/attachments), leaving most parameters unexplained.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Replace a local draft'), which distinguishes it from the create_draft/delete_draft siblings. However, it does not name an alternative directly, and 'Replace' versus the tool name 'update_draft' creates mild ambiguity about full-replacement vs partial-update semantics.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no when-to-use guidance or routing to siblings such as create_draft or get_draft. The clause about 'current revision' hints at a concurrency workflow but does not tell the agent when to prefer update over create or what to do first.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
13 tool updates
v0.1.0- First observed
create_draft - First observed
delete_draft - First observed
download_attachment - First observed
get_draft - First observed
get_message - First observed
get_send_status - First observed
list_attachments - First observed
list_drafts - First observed
list_mailboxes - First observed
list_messages - First observed
mail_status - First observed
search_messages - First observed
update_draft
TDQS
Scored across 13 tools
Each tool targets a distinct resource and action: list vs get vs search for messages, metadata vs content for attachments, and complete CRUD separation for drafts. Minor overlaps (list_messages/search_messages, list_mailboxes/mail_status) are clearly differentiated by their descriptions.
Almost all tools follow a predictable snake_case verb_noun pattern (list_, get_, create_, update_, delete_, download_). The noun-first 'mail_status' is an outlier and is slightly inconsistent with 'get_send_status', but the overall convention is strong.
13 tools is well within the ideal 3-15 range for a mail server covering mailboxes, messages, attachments, drafts, and status. Each tool appears to earn its place with no obvious redundancy.
The surface lacks any send operation despite offering get_send_status for send receipts, and message management (delete, move, mark read/unread) is entirely absent. Attachment upload and draft sending are also missing, leaving significant gaps for a cloud mail server.
Maintenance
Related MCP Connectors
Hosted agent inboxes: read mail, send to owner-approved recipients. Mail is server-readable.
- MailowsOAuthcom.mailows
Give AI agents their own email inboxes: list, read and send mail via scoped, revocable OAuth grants.
1 Gmail, Outlook, iCloud, Fastmail and any IMAP mailbox for your agent. Scoped OAuth, approved sends.
Governed email for agents: Gmail, M365 and IMAP; per-mailbox permissions, send allowlist, audit log
Related MCP Servers
- AlicenseBqualityBmaintenanceEnables controlled Microsoft 365 mail workflows including search, read, thread, attachment, and managed draft operations through Microsoft Graph, without sending or modifying messages.9MIT
- AlicenseAqualityAmaintenanceEnables MCP clients to read, search, organise, and manage IMAP mailbox messages, including saving attachments and drafting replies, while treating mail content as untrusted and keeping write capabilities opt-in.6208 npm3MIT
- AlicenseNot gradedqualityCmaintenanceEnables a locally-running agent to read and organize email from Gmail, Microsoft 365, and IMAP mailboxes with restricted, audited access.GPL 3.0
- FlicenseNot gradedqualityBmaintenanceEnables read-only access to multiple email accounts, including Gmail via App Password and generic IMAP providers, so an agent can list accounts and folders, search messages, and fetch messages or attachments. All operations are strictly read-only, with no sending, writing, deleting, or moving.1-