从写代码到过 DNS 认证进官方注册中心,全程踩坑记录。
在线服务:https://savantcat.cn/mcp | 注册名:cn.savantcat/answers
起因
2026 年 9 月 1 日,GB/T 47746—2026《顾客联络服务 人工与智能客户服务协同要求》正式实施。
我把它的合规要点整理成了一份结构化的问答库:哪些场景必须自动转人工、上线要走备案还是登记、知识库怎么切分……每条答案带条款依据。
整理完发现一个问题:它是文档,只有人能读。 而企业里越来越多的活是 Agent 在干。
所以决定把它暴露成 MCP,让任何 Agent 直接调用。
一、技术选型
MCP 官方 Python SDK,用 streamable-http 传输、无状态模式。
mcp >= 1.9 transport: streamable-http (stateless)
选无状态的原因:远程部署时不需要维护 session,任何客户端一次 POST 就能拿到结果,横向扩展也简单。
启动态形:
server.run(
transport="http",
host="127.0.0.1",
port=8765,
stateless=True,
)
Nginx 侧只需要一条精确匹配,把 /mcp 转发进去:
location = /mcp {
proxy_pass http://127.0.0.1:8765;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_buffering off; # SSE 必须关,否则响应被缓冲住
}
proxy_buffering off 是关键。streamable-http 返回的是 text/event-stream,开着缓冲会导致客户端一直等不到数据。
二、踩坑一:421 Invalid Host header
服务本地跑得好好的,域名访问直接:
421 Invalid Host header
原因:MCP SDK 内置了 DNS rebinding 防护。默认只信任 localhost,请求头里的 Host 不是它认识的,一律拒绝。
这是好事,说明 SDK 默认是安全的。修法是显式声明信任的域名:
from mcp.server.transport_security import TransportSecuritySettings
server.run(
transport="http",
host="127.0.0.1",
port=8765,
stateless=True,
transport_security=TransportSecuritySettings(
allowed_hosts=["savantcat.cn", "www.savantcat.cn"],
allowed_origins=["https://savantcat.cn"],
),
)
别图省事放开成 *。 显式白名单才是这段防护存在的意义。
三、踩坑二:mcp 2.x 的 API 变了
如果你照 1.x 的教程写,会遇到一连串报错:
| from mcp.server.fastmcp import FastMCP | from mcp.server.mcpserver import MCPServer |
| mcp.settings.port = 8765 | 模块级 settings 已移除 |
| 端口靠 settings 注入 | run() 直接接收 host / port / path / stateless |
我第一次部署就中招了——服务起来了,但监听在 8000 而不是 8765,因为传进去的端口没地方接。
另外客户端侧有属性名变更:2.x 用蛇形 server_info,写代码时建议做个双取兼容:
info = getattr(resp, "server_info", None) or getattr(resp, "ServerInfo", None)
四、怎么发布到官方 MCP Registry
这里是最值得说的部分,中文资料目前极少。
先说结论:纯远程服务不需要发 npm 包。 官方 Registry 支持 remotes 字段,你只要有一个能被公网访问的 MCP 端点,就能发布。
4.1 命名空间
注册名格式是 <namespace>/<server-name>。命名空间可以走 GitHub 账号,也可以走域名。
我选域名:cn.savantcat/answers。比 GitHub 命名空间更有品牌辨识度,而且不依赖任何第三方账号体系。
4.2 server.json
按官方 schema 写清单,关键是 remotes:
{
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
"name": "cn.savantcat/answers",
"title": "AI 客服国标合规知识库 (GB/T 47746—2026)",
"description": "中国 AI 客服国标合规问答库:必须自动转人工的场景、强制自查项、上线备案要求。",
"version": "1.0.0",
"websiteUrl": "https://savantcat.cn/mcp/",
"remotes": [
{ "type": "streamable-http", "url": "https://savantcat.cn/mcp" }
]
}
两个容易踩的点:
- schema 地址别用过期的,官方已经升到 2025-12-11
- description 硬限 100 字符,超了直接校验失败。中文表达力强,用中文写更容易压进去
先本地校验:
mcp-publisher validate
# server.json is valid
4.3 DNS 认证
发布需要一个 ed25519 私钥(hex 格式),工具会算出对应的公钥,让你把它作为 TXT 记录挂到域名上:
mcp-publisher login dns –domain example.com –private-key <HEX>
它会打印出需要添加的记录,形如:
v=MCPv1; k=ed25519; p=<base64 公钥>
在域名解析商那边加一条 根域的 TXT 记录,值为上面整串(注意分号、等号、加号都要带上)。
别把私钥写进代码或者提交到仓库,.gitignore 里加一条。
解析生效后(我这边大约几分钟,可以用公共 DNS 反复查确认),登录会自动通过:
✓ Successfully authenticated
4.4 发布
mcp-publisher publish
# ✓ Successfully published
# ✓ Server cn.savantcat/answers version 1.0.0
验证不要只看命令输出,直接打官方 API 回读:
curl "https://registry.modelcontextprotocol.io/v0/servers?search=cn.savantcat%2Fanswers"
返回里 _meta 节点带状态:
{
"io.modelcontextprotocol.registry/official": {
"status": "active",
"publishedAt": "2026-09-11T08:48:35.682965Z",
"isLatest": true
}
}
看到 status: active 才算真的进去了。
五、一个有意思的发现
发布前我在官方公开库里搜了几个词:
| customer service | 0 |
| 客服 | 0 |
| GB/T | 0 |
| call center | 0 |
公共服务领域 + 中文行业标准这个交叉位置,在官方库基本是空白。
这说明一件事:MCP 生态现在偏开发者工具,行业知识型的服务还很少。 而这恰恰是国内企业最需要的那类能力。
六、给想动手的人的几点建议
最后
标准是给专家看的,但执行标准的是企业。
中间那层"把标准翻译成机器能懂、能直接用的形式"的工作,现在几乎没人做。
谁做,谁就占住一个位置。
本文提到的服务已上线公开测试,注册名 cn.savantcat/answers。



