如何用 FastMCP 组件版本化与 VersionFilter 从同一份代码同时提供 v1 和 v2 API?

发布时间:2026/9/13 11:46:38
如何用 FastMCP 组件版本化与 VersionFilter 从同一份代码同时提供 v1 和 v2 API? 如何用 FastMCP 组件版本化与 VersionFilter 从同一份代码同时提供 v1 和 v2 API【免费下载链接】fastmcp The fast, Pythonic way to build MCP servers and clients.项目地址: https://gitcode.com/GitHub_Trending/fa/fastmcp如果你的同一个工具tool、资源resource或提示词prompt有多个实现且 v2 在 v1 的基础上新增了参数又不想为 v1、v2 客户端维护两套独立部署FastMCP 的组件版本化component versioning可以解决这个问题给每个组件注册多个版本再用VersionFilter从同一份组件定义中切出不同的 API 表面。v1 表面只暴露低版本实现v2 表面只暴露高版本实现两个服务共享同一个 provider。这套机制适用于 FastMCP 3.0.0 及以上版本文档以VersionBadge version3.0.0 /标注。以下是完整的操作路径相关文档见 docs/servers/versioning.mdx。准备环境FastMCP 要求 Python 3.10 及以上见 pyproject.toml 中的requires-python 3.10。安装方式见 docs/getting-started/installation.mdxuv add fastmcp或者用 pippip install fastmcp安装完成后运行以下命令确认安装成功fastmcp version能打印出 FastMCP version、MCP version、Python version 等信息即为正常安装文档中展示的输出版本号仅作为文档示例你的实际版本号以安装结果为准。第一步在同一 provider 上注册 v1 和 v2 组件给组件装饰器加version参数即可声明版本。FastMCP 把版本存为字符串并按组件标识符分组——工具tool和提示词prompt按名称分组资源resource按 URI 分组。推荐的组织方式是把版本化组件定义在一个共享的LocalProvider上而不是直接挂在各个服务上from fastmcp import FastMCP from fastmcp.server.providers import LocalProvider from fastmcp.server.transforms import VersionFilter # 定义版本化组件到共享 provider 上 components LocalProvider() components.tool(version1.0) def calculate(x: int, y: int) - int: Add two numbers. return x y components.tool(version2.0) def calculate(x: int, y: int, z: int 0) - int: Add two or three numbers. return x y z同一个名称calculate注册了两个版本两个实现都保留在 provider 中由后续的过滤器决定每个服务暴露哪一个。资源和提示词的写法同理例如mcp.resource(config://app, version1.0)、mcp.prompt(version1.0)。注意一条硬约束同一个名称下要么全部版本化要么全部不版本化。把一个未版本化的calculate和一个带version的calculate注册到同一个服务上会在注册时抛出ValueError错误信息为 Cannot add versioned tool calculate (version2.0): an unversioned tool with this name already exists. Either version all components or none.第二步用 VersionFilter 创建两个 API 表面创建两个FastMCP服务让它们共享同一个 provider各自挂载不同的VersionFilter# 创建共享 provider、但过滤器不同的两个服务 api_v1 FastMCP(API v1, providers[components]) api_v1.add_transform(VersionFilter(version_lt2.0)) api_v2 FastMCP(API v2, providers[components]) api_v2.add_transform(VersionFilter(version_gte2.0))VersionFilter只有两个关键字参数均为 keyword-only对应比较运算符version_gte版本大于等于该值时通过version_lt版本小于该值时通过两者至少指定一个都不指定会在构造时抛ValueError两个参数可以同时使用以表示闭开区间例如VersionFilter(version_gte2.0, version_lt3.0)表示[2.0, 3.0)只命中 v2.x。一个容易被忽略的行为未版本化的组件默认不会被过滤掉。也就是说如果 provider 里同时有版本化和未版本化的组件加不加VersionFilter未版本化的组件在两个表面上都可见。这是为了避免给混合了版本化/未版本化组件的服务加过滤器时意外隐藏组件。如果你的 API 表面要求严格的版本隔离需要显式传入include_unversionedFalse把它们排除。这样连接api_v1的客户端看到的是两参数版本的calculate连接api_v2的客户端看到的是三参数版本。两个服务共享同一份组件定义。第三步验证两个表面暴露的版本用 FastMCP 的Client分别连接两个服务先列组件、再实际调用即可核对过滤是否生效from fastmcp import Client async with Client(api_v1) as client_v1: tools await client_v1.list_tools() for tool in tools: if tool.meta: fastmcp_meta tool.meta.get(fastmcp, {}) # 当前返回的版本默认为过滤后的最高版本 print(fVersion: {fastmcp_meta.get(version)}) # 该组件的全部可用版本 print(fAvailable: {fastmcp_meta.get(versions)}) async with Client(api_v1) as client_v1, Client(api_v2) as client_v2: r1 await client_v1.call_tool(calculate, {x: 1, y: 2}) r2 await client_v2.call_tool(calculate, {x: 1, y: 2, z: 10})验证时看两点列表元数据客户端列出组件时每个版本化组件的meta.fastmcp中version字段是当前返回的版本默认是可见范围内最高版本versions字段按从高到低列出全部已注册版本例如[2.0, 1.0]。未版本化的组件完全没有这两个字段。实际调用对同一个calculate调用通过api_v1走的是 v1.0 实现不接受z参数通过api_v2走的是 v2.0 实现z有默认值 0。如果 v1 表面意外返回了三参数版本说明过滤器没有挂上或参数写错。仓库中带完整输出的示例脚本是 examples/versioning/version_filters.py它定义了process的 1.0/2.0/3.0 三个版本加一个未版本化的health工具创建version_lt2.0、version_gte2.0, version_lt3.0、version_gte3.0三个表面最后用Client逐个打印每个表面可见的工具及其版本并对每个表面执行同一个调用做对照。运行方式uv run python examples/versioning/version_filters.py脚本会打印三个表格每个表面对应的 Tool / Version 列表和一段 Same call through different APIs 对照输出你可以直接用它核对过滤行为是否符合预期。另一个更完整的版本化示例工具、资源、提示词三类组件各两个版本是 examples/versioning/versioned_components.py。版本比较规则与限制配置过滤器时版本字符串的比较方式值得了解否则区间可能切错PEP 440 风格的版本如1.0、2.1.3、1.0a1按语义比较数字段按数值比较1.9 1.10预发布版本排在正式版之前1.0a1 1.0b1 1.0。其他格式如日期、自定义方案按字符串字典序比较ISO 日期这类天然可排序的格式结果正确2025-01-15 2025-02-01。比较前会去掉v前缀因此v1.0和1.0视为相等。此外还有一个针对挂载mount场景的说明如果你在父服务上挂载了子服务再对父服务加VersionFilter过滤器同样作用于挂载服务的组件——区间过滤在 provider 层完成子服务不需要知道父服务的版本约束父服务按命名空间namespace后的组件名做过滤但仍基于版本本身。可选的后续操作完成双版本上线后文档给出了两个直接的延伸操作均见 docs/servers/versioning.mdx按版本调用特定实现FastMCP 客户端的call_tool、read_resource、get_prompt都接受可选version参数例如await client.call_tool(calculate, {x: 1, y: 2}, version1.0)请求不存在的版本会抛NotFoundError不会静默回退到别的版本。对于没有内建版本支持的通用 MCP 客户端可以在请求参数的_meta.fastmcp.version字段里传版本号组件实现本身看不到_meta。迁移完成后清理旧版本mcp.local_provider.remove_tool(process_data, version1.0)只删除指定版本其余版本保持注册不带version参数则删除该组件的全部版本。这两个操作加上本文的双表面配置就构成 FastMCP 文档中描述的完整迁移流程旧实现标上 v1.0、新实现作为 v2.0 并行上线、客户端默认看到 v2.0、确认无误后移除 v1.0。【免费下载链接】fastmcp The fast, Pythonic way to build MCP servers and clients.项目地址: https://gitcode.com/GitHub_Trending/fa/fastmcp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考