Anthropic 的 MCP 课程,止步于规范的硬性规则
采样和传输讲得清楚,但干净的 stdout、Origin 校验和采样人工审批,仍要自己实现并测试。
要点速览
- Anthropic 的课程涵盖 MCP 的采样、传输和生产部署,默认学员已掌握 Python、异步编程、JSON/HTTP 和 SSE。
- 采样把模型选择和权限留在客户端,服务器只发送偏好和提示。
- 无状态 HTTP 易于扩展但有取舍,而且 Python SDK 仍有与规范不一致之处,需要自己测试。
2026 年 4 月 19 日,MCP Python SDK 仓库里出现了一个 issue。内容很短:配置了 stateless_http=True 的 Streamable HTTP 服务器仍然接受 GET /mcp,与规范不符。这个 bug 不大,但它说明即便是官方库,也并不总是遵循规范。
学习“Model Context Protocol: Advanced Topics”也应该抱着这种态度。这是 Anthropic 在 Anthropic Academy(托管于 Skilljar)上开设的课程,重点是服务器与客户端通信、传输机制,以及生产部署中需要注意的问题。课程页面只写了 © 2026,没有给出发布日期或时长。
对前线部署工程师(FDE)来说,这些都是客户现场的实际问题。MCP 服务器跑在哪里?模型密钥由谁持有?放到负载均衡器后面会怎样?课程回答了其中大部分,剩下的要靠自己从规范里弄清楚。
谁适合学,按什么顺序学?
课程默认学员已掌握 Python、异步编程、JSON/HTTP 以及 SSE 基础。如果还不能熟练编写异步 Python,先把这一关过了。否则传输部分的课程会很吃力,因为要同时学协议和语法。
比较合理的顺序是:先学完课程,再读 2025-06-18 版规范中的 Sampling 和 Transports 两页,最后再去看上面那个 SDK issue。这样就能从概念走到强制规则,再看到真实代码在哪里仍未达标。有三点值得记住。
服务器借用客户端的模型
按照课程的说法,采样(sampling)是 MCP 服务器通过所连接的客户端请求调用语言模型的机制。MCP 规范讲明了好处:服务器无需自己的 API 密钥就能获得 AI 能力,而访问、模型选择和权限仍由客户端控制。
服务器也不会写死模型名称。它告诉客户端自己对成本、速度和模型质量各有多看重,并附上几个模型名称提示。规范强调,这些提示只是建议,最终决定权在客户端。
设想要为客户构建一个汇总工单的服务器。有了采样,就不必再向客户为服务器单独申请密钥,客户的安全团队仍能决定使用哪个模型。
但规范附带一条建议:始终应有人能够拒绝采样请求。如果客户端是你写的,这个审批环节就是你的责任。
stdout 只留给 MCP 消息
规范定义了两种标准传输:stdio 和 Streamable HTTP,并建议客户端尽可能支持 stdio。stdio 有一条强制规则:服务器不得向 stdout 写入任何非有效 MCP 消息的内容,日志写入 stderr。
自己写服务器时很容易犯这个错。一个调试用的 print 就会污染消息流,让客户端收到无法解析的数据。所以搭建服务器的第一件事,在写任何工具之前,就是配置 logger:
import logging, sys
logging.basicConfig(stream=sys.stderr, level=logging.INFO)
log = logging.getLogger("mcp-server")
log.info("服务器启动中") # 输出到 stderr,绝不触碰 stdout
预期结果:每行日志都出现在 stderr 上,stdout 只承载 MCP 消息。为保险起见,可以故意加一句 print("debug"),观察客户端的反应,下次就能认出这种症状。
状态决定扩展方式
课程最有价值的部分,是教你根据部署需求、所需功能和扩展限制来选择传输方式,包括何时使用无状态 HTTP,在负载均衡器后做水平扩展。
按照规范,Streamable HTTP 中的会话是可选的。服务器可以在初始化时通过 Mcp-Session-Id 请求头分配一个 ID,此后客户端必须在每个请求中回传这个 ID。
设想客户在负载均衡器后运行三个实例。实例 A 发放了会话并持有状态,但下一个请求落到了实例 B,而 B 对这个会话一无所知。无状态运行可以避免这个问题,但并非没有代价。
课程指出,这些配置标志会影响服务器发起的请求和流式传输。采样恰恰是服务器发起的请求,所以需要确认它在所选配置下依然可用。
还有两条规则应直接写进测试套件,每条单独一个命令,这样请求被拒时就能确切知道是哪条规则拦下的。把下面的地址换成你的服务器地址。
第一个命令检查 SDK issue 中提出的不一致:向运行 stateless_http=True 的服务器发送一个不带其他请求头的 GET。
curl -i -X GET http://localhost:8000/mcp
该 issue 建议无状态服务器对此请求返回 405。如果你的服务器仍然接受它,记录下来,并在自己的层面拦截,而不是指望库来处理。
第二个命令检查 Origin 请求头的强制规则:Streamable HTTP 服务器必须在每个连接上校验它,以防范 DNS 重绑定攻击。这里用 POST,避免和上面的 GET 测试混在一起:
curl -i -X POST http://localhost:8000/mcp \
-H "Origin: http://evil.example" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"ping"}'
需要看到的结果是请求被拒绝。然后去掉 Origin 这一行重跑同一命令:如果只有带外部 Origin 的版本被拦截,就说明 Origin 校验在起作用,请求不是因为其他原因失败的。
把课程变成简历上的证据
不要只在简历上列出结业证书,而要附上一个能证明你真正动手做过的小仓库。
构建一个服务器:同时支持 stdio 和 Streamable HTTP,日志写入 stderr,有一个拒绝外部 Origin 的测试,有一套在两个实例后运行的无状态配置,并配一个包含采样审批环节的客户端。
在 README 里写一小段话,说明为什么选择有状态或无状态。
当 FDE 岗位描述提到 MCP、Agent 集成或生产部署时,这段话就是面试时要带去的东西。要准备好讲清其中的取舍,比如为什么会话 ID 会让负载均衡变复杂,而不只是列出调用过哪些 API。
学完这门课的人会很多,但亲手向自己的服务器发过 GET /mcp、看看会返回什么的人要少得多。
这篇文章对你有帮助吗?
感谢你的反馈!