Pydantic AI 2.29.0 MCP SDK v2 迁移指南:FastMCP 3/4 兼容门禁
Pydantic AI v2.29.0 已经让同一套 MCPToolset API 同时面向 FastMCP 3 和 FastMCP 4 / MCP Python SDK v2。但“API 兼容”不等于“业务行为完全一致”。
核心判断:不要只改依赖上限。把 FastMCP 3 和 4 拆成两条 CI 测试线,再分别检查能力、Tasks 语义和回滚。

一、Pydantic AI 2.29.0 改了什么
官方 Release 把 FastMCP 4 / MCP SDK v2 支持带进了 MCPToolset,同时保留 FastMCP 3 兼容。实现上将 FastMCP 依赖范围放宽到 >=3.3.0,<5,并用兼容层处理字段命名和 Server Metadata 差异。
但官方 PR 也明确了边界:
- FastMCP 4 仍是需要显式选入的预发布线;
- 现代 Session 不按旧方式处理 Server-Initiated Sampling、Elicitation 和
log_level; - FastMCP 4 的 Tasks 走 SEP-2663,显式
use_task=True需要fastmcp-tasks/mcp-tasksExtra。
因此,只验证“能列出工具”或“能调一次 Tool”还不够。
二、先冻结两条测试线
| 检查项 | FastMCP 3 | FastMCP 4 / MCP SDK v2 | 迁移动作 |
|---|---|---|---|
| 安装 | 稳定默认线 | 预发布,显式选入 | 分开约束和 Lockfile |
Sampling / Elicitation / log_level | 旧协议路径 | 现代 Session 不按旧方式处理 | 业务依赖存在就先阻断 |
| Tasks | SEP-1686 | SEP-2663 | 重测创建、取消、超时和终态 |
| 显式 Task 扩展 | FastMCP 3 Tasks Extra | fastmcp-tasks | 单独安装与审计 |
| 回退 | 保留已验证版本 | 新线不达标即停 | 切流前演练 |
两条线要记录 Pydantic AI、FastMCP、MCP SDK 和 Tasks 扩展的完整解析结果。不设上限不是兼容策略,只是把决定权交给下一次安装。
include:
- lane: fastmcp3
fastmcp: ">=3.3,<4"
task_semantics: "SEP-1686"
- lane: fastmcp4
fastmcp: ">=4,<5"
prerelease: true
task_semantics: "SEP-2663"
三、四阶段迁移门禁
阶段 1:锁依赖
最小动作:分开两条约束、Lockfile 或 CI Matrix。
过关证据:每条线的日志都能输出完整版本组合。
适用边界:不用“在我电脑上解出了”代替锁定依赖。
阶段 2:盘能力
最小动作:枚举真实 Server 所用的 Sampling、Elicitation、Logging、Auth、Transport 和 Metadata。
过关证据:每项都有正常与拒绝 / 降级样本,警告能让 CI 失败。
适用边界:有业务依赖就先阻断切换,不强行绿灯。
阶段 3:分 Tasks
最小动作:把普通 Tool Call、Server 宣告的长任务和显式 use_task=True 拆成三组用例。
过关证据:任务创建、结果、取消、超时、重连和终态全部可观测。
适用边界:FastMCP 3 的 prefer_tasks 不能直接当成 FastMCP 4 的契约。
阶段 4:留回滚
最小动作:保留旧 Lockfile,将警告、错误率、Task 终态完整性和回退动作放进同一发布门禁。
过关证据:人为注入一个不兼容样本后,系统能停止扩量并切回旧线。
适用边界:回滚不能依赖临时重新解算依赖。
四、用失败关闭策略拦截误切换
下面不是 Pydantic AI 源码,而是一个本地发布门禁。它的任务是:FastMCP 4 新线仍要求旧能力,或显式 Task 调用缺少 Extra 时,直接阻断。
def evaluate(case: MigrationCase) -> GateResult:
match case.line:
case FastMCPLine.V3:
return GateResult(GateStatus.PASS, (), None)
case FastMCPLine.V4:
blockers: list[str] = []
if case.features.sampling:
blockers.append("sampling needs a separate compatibility decision")
if case.features.elicitation:
blockers.append("elicitation needs a separate compatibility decision")
if case.features.log_level:
blockers.append("log_level is not honored by the modern session")
if case.features.tasks and not case.tasks_extra_installed:
blockers.append("explicit task calls need the mcp-tasks extra")
status = GateStatus.BLOCK if blockers else GateStatus.PASS
return GateResult(status, tuple(blockers), None)
case unreachable:
assert_never(unreachable)
真实系统还要把警告、依赖解析结果和 MCP 互操测试接进 CI。
五、7 个本地策略样本
本地用 Python 3.13.5、pytest 8.4.2 验证了 FastMCP 3 基线、FastMCP 4 基本 Tool Call、三项旧能力阻断、Tasks Extra 缺失与存在共 7 个样本。
....... [100%]
7 passed in 0.01s
Ruff 0.16.3、BasedPyright 1.39.10、py_compile 和代码规则审计同时通过。这只能证明本地策略逻辑稳定,不能代替真实 MCP Server 互操。
六、发布前检查表
- FastMCP 3 / 4 的 Lockfile 和 CI 已分开;
- Sampling、Elicitation、Logging、Auth 和 Transport 已盘点;
- 警告能阻断发布,不把连接成功当能力一致;
- SEP-1686 与 SEP-2663 的 Tasks 分别回归;
- 显式 FastMCP 4 Task 已安装并审计
fastmcp-tasks; - 真实 Server / Transport 互操通过;
- 旧 Lockfile 回退已演练。
官方来源:Pydantic AI v2.29.0、FastMCP 4 / MCP SDK v2 支持 PR、Pydantic AI MCP Client 文档。
验证边界:事实基于 2026-08-14 对官方 Release、PR 与文档的核验;2026-08-20 续跑时官方站点被网络层阻断,因此不声称
v2.29.0仍是当前最新版。未安装 FastMCP 4 / MCP SDK v2,未执行真实 Tasks、Sampling、Elicitation 或 Transport 互操。
更多推荐

所有评论(0)