智能体能调用的 API 和智能体知道怎么调用的 API 之间,存在真实的差别。 一个 REST 端点要求模型在上下文中记住基础 URL、认证头的格式、JSON 请求体和响应结构, 并且一次性把这四样全部做对。而工具定义通过协议免费把这些交给它。
这就是在这里使用 MCP 的全部理由。收件箱的接口面足够小,工具列表本身就是文档。
接入方式
apumail 在 /.well-known/mcp.json 提供 MCP 描述文件。对于能读取描述文件的客户端,
指向这个源地址就够了:
https://api.apumail.com/.well-known/mcp.json
无需安装步骤,无需拉取包,也无需事先开通密钥——需要认证的收件箱工具,使用
create_inbox 返回的收件箱令牌。
9 个工具
它们分为三组,而这种分组就是思维模型:
获取地址
create_inbox— 开通一个随机名称的收件箱,返回地址及其令牌。无需认证。这是入口。get_inbox— 收件箱元数据和 TTL 状态。
接收
list_mails— 收件箱中当前的所有邮件。read_mail— 单封邮件,完整正文,已净化。wait_for_mail— 最重要的一个。阻塞直到有邮件到达。 正是它让智能体不必每次轮询都消耗一次模型往返。extract_latest_otp— 最新一封邮件中的验证码,已在服务端提取好。
发送
send_mail— 从同一地址回复。from被强制设为已认证的收件箱, 因此泄露的令牌无法冒充任何人。
另外,付费套餐还提供 wait_for_sms 和 extract_latest_sms_otp,
它们的作用和对应的邮件工具完全一样——同样的等待/提取形态,只是把地址换成了电话号码。
以工具形式呈现的流程
在那篇 OTP 文章里需要三次 curl 调用的注册流程,压缩成了这样:
create_inbox→ 智能体获得vivid-llama-4a2c@apumail.com- 智能体把这个地址填入它正在处理的表单
wait_for_mail→ 阻塞,确认邮件到达时返回extract_latest_otp→"482910"
这里面没有任何针对 apumail 的推理。模型不需要知道 apumail 是什么——它只需要知道
有一个叫 wait_for_mail 的工具,而协议已经告诉它了。
何时不用 MCP
坦白说:如果你在写测试套件,就用 REST API。当调用方是一个在决定下一步做什么的模型时,
MCP 才物有所值。当调用方是运行既定脚本的 CI 流水线时,端点更简单,也没有协议挡在中间。
两者访问的是同一个后端,所以混用完全没问题——在 fixture 中通过 REST 开通,把地址交给智能体,
再让它通过 MCP 执行 wait_for_mail。
描述文件就是文档
如果你想在接入任何东西之前先了解接口面,三个 URL 就能回答所有问题:
- /.well-known/mcp.json — MCP 描述文件
- /openapi.json — REST 部分的 OpenAPI 3.1
- /llms.txt — 同样的内容的 Markdown 版本,专为模型从头到尾阅读而写