Skip to content

feat(sms): 新增无状态短信 MCP API 服务 - #434

Merged
cuericlee merged 2 commits into
volcengine:mainfrom
shaynecc:feat/sms-mcp-api
Sep 18, 2026
Merged

cuericlee merged 2 commits into
volcengine:mainfrom
shaynecc:feat/sms-mcp-api

Conversation

@shaynecc

@shaynecc shaynecc commented Sep 14, 2026 •

Copy link
Copy Markdown
Contributor

新增 mcp-server-sms 独立包,将现有短信 OpenAPI 暴露为 26 个 MCP 工具,覆盖消息组、资质、签名、模板、发送、普通群发和结果查询。每个业务工具接收完整参数,直接调用对应接口;客户端负责交互和用户确认,短信服务负责业务校验及业务数据。

实现

  • 支持 MCP 2026-07-28、stdio 和 Stateless Streamable HTTP;包版本为 0.1.0,接入仓库现有构建与 PyPI 发布流程。
  • 不依赖 Skill、SQLite/PostgreSQL、业务缓存、草稿、存储式预览或通用 prepare/execute;生产代码共 5 个文件。
  • 使用官方 SDK 完成 V4 签名;HTTP 每次请求独立传递短信凭据,不回退到进程默认账号。HTTP 连接池由 MCP 服务生命周期管理,服务关闭时释放,不保留跨调用者的响应 Cookie。
  • 保留参数校验、结构化结果、公开错误码、HTTP 状态码与 RequestId;不自动重试 API,不承诺跨请求去重。400/401/403 等明确拒绝不会被标为结果未知;超时、服务端异常及缺少关键结果的写响应仍保留 outcome_unknown。
  • 上传接口顶层 Result.url 保持完整,包括签名中的 AK/STS 参数;其他结果字段继续脱敏。
  • 材料使用现有短信材料引用,MCP 不托管文件或提供页面。群发创建与启动保持为两个独立业务操作。不包含特殊通知群发、验证码群发或国际短信。

验证

  • Python 3.11 和 3.12 各 57 项测试通过,覆盖参数映射、凭据隔离、未知写结果、CSV 响应和协议通信;新增签名上传 URL、纯文本 HTTP 拒绝响应、连接池生命周期和跨调用者 Cookie 隔离回归测试。
  • Python 3.11 直接安装本次构建的 wheel 运行测试,标准 MCP 客户端验证协议版本 2026-07-28、26 个工具以及缺少凭据时的明确拒绝。
  • Ruff、格式检查、git diff --check、wheel/sdist 构建及 Twine 检查通过。
  • 2026-09-14 的提交 152ded3 已完成真实账号只读验收,消息组、资质要求、资质、签名、模板、二级模板、发送日志共 7 项成功。本次修复完成了模拟 API 和本地协议测试,尚未重复真实账号验收。

待验收

  • 新实现的资质/签名/模板申请、验证码、短信发送和群发尚未进行真实写入验收,目前由模拟 API 测试覆盖。
  • 云端托管平台的请求头、HTTPS 和私密材料渠道仍需实际联调。

仓库中不含验收账号、手机号、凭据或材料。

@shaynecc
shaynecc marked this pull request as ready for review September 14, 2026 11:09

@cuericlee cuericlee left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. safe_result 会破坏 GetUploadTosURL 返回的签名上传 URL

client.py 的 safe_result 会把结果中所有字符串里出现的 credentials.access_key / secret_key / session_token 子串替换为 [REDACTED]。而短信服务 GetUploadTosURL 返回的 TOS 预签名 URL(如 ...?X-Tos-Credential=/...&X-Tos-Signature=...)明文包含 AccessKeyId,经过 safe_result 后 URL 会被替换成 [REDACTED],客户端拿到的地址是坏的 —— 这直接断掉 README 主推的"群发 CSV 上传"流程。

测试里 mock 的 url 是 https://upload.example/fixture.csv?signature=opaque,不含 AK,所以没暴露。建议:
对签名 URL 类字段(url/fileUrl)跳过子串替换,或只对查询参数里的凭证字段做解析脱敏;
补一条"上传 URL 含 AK 时不被破坏"的单测。
🟠 中优先级建议
2. 4xx 写操作被误标为 outcome_unknown

decode() 中非 JSON body 的 401/403/400(网关直接返回纯文本错误)会落入 not response.is_success 分支 → 写操作返回 outcome_unknown=True。鉴权失败/参数错误是确定性失败,标成"结果未知"会误导客户端(例如重复提交、错误排查)。建议:4xx 一律 outcome_unknown=False(明确失败),只有 5xx/超时/连接断开才标未知。

  1. 每次 API 调用新建 httpx.AsyncClient,无连接复用

SmsClient.call() 每次请求都 async with httpx.AsyncClient(...),等于每次重新建连接/TLS 握手。短信是高吞吐场景,建议把 AsyncClient 提升为实例/模块级共享(用 transport 注入测试不受影响)。

  1. 资质扩展 Action 属于"按契约假设"接入,需真实账号联调确认

GetOCRLicenseForAgent、ThreeElement*CheckForAgent、ApplySignatureIdentificationForAgent 等不在官方 volcengine-python-sdk 的 volcsms 覆盖内(README 也承认)。建议合并前至少用真实账号跑一遍只读接口(list_message_groups / list_qualifications / get_qualification_requirements),或在 README 里明确标注这些工具为 experimental。

@cuericlee cuericlee left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/lgtm

@cuericlee
cuericlee merged commit e04858e into volcengine:main Sep 18, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants