FastMCP 3.0 组件发现方法整合:从 get_* 到统一 list_* API 的重构实践

FastMCP 3.0 组件发现方法整合:从 get_* 到统一 list_* API 的重构实践 FastMCP 3.0 组件发现方法整合从 get_* 到统一 list_* API 的重构实践【免费下载链接】fastmcp The fast, Pythonic way to build MCP servers and clients.项目地址: https://gitcode.com/GitHub_Trending/fa/fastmcpFastMCP 在 3.0 版本中对组件发现component discoveryAPI 做了一次系统性重构将服务端并行的get_tools()/_list_tools()、get_resources()/_list_resources()、get_prompts()/_list_prompts()、get_resource_templates()/_list_resource_templates()两套几乎重复的实现合并为单一、规范的list_*方法族并彻底删除旧的复数get_*方法与内部_list_*方法。这篇技术文章基于 dev-docs/v3-notes/get-methods-consolidation.md 的设计记录结合当前仓库源码拆解这次重构的背景、两阶段演进过程、返回类型与中间件语义的变化以及带给开发者的实际收益帮助你快速掌握 v3 API 并平滑完成迁移。背景两套并行的组件列举实现在 FastMCP 2.x 及更早版本中服务端针对每一类 MCP 组件工具、资源、提示词、资源模板都维护了两套列举方法公开 APIget_tools()、get_resources()、get_prompts()、get_resource_templates()面向应用开发者内部实现_list_tools()、_list_resources()、_list_prompts()、_list_resource_templates()被 MCP 协议处理器内部调用。问题在于这两套方法的功能几乎完全相同——都要做组件聚合、去重、可见性过滤最后返回组件集合——却在去重键dedup key、日志输出、返回类型等细节上存在微妙的差异。这带来三个直接后果重复维护成本任何行为调整如新增可见性过滤规则都要同步修改两处实现行为漂移风险去重键、日志、返回类型的不一致导致公开 API 与协议处理器看到的结果可能不同心智负担开发者需要理解get_*与_list_*的差异才能正确使用。解决方案两阶段演进为统一的 list_* 方法这次整合并非一步到位而是在源码中分两个阶段推进最终对齐到新的Provider抽象接口第一阶段Consolidation2025 年 12 月——先合并为一套 get_*将get_*与_list_*合并为单一的get_*方法同时引入apply_middleware参数让公开方法可以显式选择是否执行中间件链取代原先独立的_list_*_middleware()内部方法。第二阶段Rename2026 年 1 月——对齐 Provider 接口重命名为 list_*当FastMCP被重构为继承Provider基类之后方法名从get_*改为list_*与Provider接口保持一致apply_middleware参数也随之更名为run_middleware默认值为True。最终形态的规范方法签名如下async def list_tools(self, *, run_middleware: bool True) - Sequence[Tool]: Canonical method for listing tools. ...关键变更一返回类型从 dict 改为 list旧版get_*返回按名称索引的字典dict而dict的键实际上是冗余信息——组件对象本身已经带有.name工具、提示词或.uri资源、资源模板属性。因此 v3.0 统一改为返回Sequence列表需要按名称查找时由调用方自行完成# Before (v2.x) tools await server.get_tools() tool tools[my_tool] # After (v3.0) tools await server.list_tools() tool next(t for t in tools if t.name my_tool)这一改动消除了键与对象属性不一致的可能也让返回类型在四类组件间保持统一Sequence[Tool]、Sequence[Resource]、Sequence[Prompt]、Sequence[ResourceTemplate]。关键变更二中间件通过参数显式控制run_middleware: bool True参数默认开启负责是否执行中间件链替代了旧版独立的_list_*_middleware()方法。这让“列举组件”这一行为也进入统一的中间件体系。从当前仓库源码可以看到四个list_*方法在 fastmcp_slim/fastmcp/server/server.py 中遵循完全一致的模板创建MiddlewareContext携带对应的 MCP 协议方法名如tools/list、resources/list、resources/templates/list、prompts/list若run_middlewareTrue调用_dispatch_component_middleware()将“不执行中间件的自身调用”作为call_next传入中间件执行完毕后进入核心逻辑调用super().list_*()从 Provider 聚合组件应用会话级 transforms过滤is_enabled()的组件最后执行组件级鉴权检查。以list_tools为例server.py 中第 834 行起async def list_tools(self, *, run_middleware: bool True) - Sequence[Tool]: List all enabled tools from providers. Overrides Provider.list_tools() to add enabled filtering, auth filtering, and middleware execution. Returns all versions (no deduplication). Protocol handlers deduplicate for MCP wire format. async with fastmcp.server.context.Context(fastmcpself) as ctx: if run_middleware: mw_context MiddlewareContext( messagemcp_types.ListToolsRequest(methodtools/list), sourceclient, typerequest, methodtools/list, fastmcp_contextctx, ) return await self._dispatch_component_middleware( contextmw_context, call_nextlambda context: self.list_tools(run_middlewareFalse), ) # ... 核心逻辑聚合、会话 transforms、enabled 过滤、鉴权这里有一个值得注意的实现细节_dispatch_component_middleware的call_next是对自身方法以run_middlewareFalse的递归调用。这样做既保证了中间件链on_message→on_request→ 对应协议方法钩子能够完整观察这一次列举操作又避免了无限递归——核心逻辑只在run_middlewareFalse的分支执行一次。_dispatch_component_middleware定义于 server.py 第 579 行其 docstring 说明它会一次性跑完整个 FastMCP 中间件链并通过mark_interior_dispatched()防止根分发对同一 wire 消息二次观察。关键变更三去重职责的明确分工合并后的list_*方法文档中明确写明“返回所有版本不去重协议处理器负责为 MCP wire 格式去重”Returns all versions (no deduplication). Protocol handlers deduplicate for MCP wire format.。这意味着职责边界被清晰化FastMCP.list_*()公开 API 层提供全量、经过过滤与鉴权的组件视图供应用代码使用协议处理器_on_list_tools、_on_list_resources等在 fastmcp_slim/fastmcp/server/mixins/mcp_operations.py 中负责按name、uri或uri_template去重后再序列化为 wire 消息。# mcp_operations.py 中的协议处理器调用模式 list(await self.list_tools()), lambda t: t.name # tools/list 按 name 去重 list(await self.list_resources()), lambda r: str(r.uri) # resources/list 按 uri 去重Provider 基类list_* 接口的定义与重写重构的另一个关键点在于FastMCP继承自Provider四个list_*方法实际上是在重写 Provider 接口Provider.list_tools()等接口定义于 fastmcp_slim/fastmcp/server/providers/base.py第 142、238、278、321 行FastMCP在 server.py 中重写这些方法叠加 FastMCP 特有的行为enabled 过滤、会话级 transforms、Prefab 渲染器 URI 重写_rewrite_prefab_uris、合成资源追加synthesize_prefab_resources以及组件级鉴权run_auth_checks。这一设计让FastMCP.list_tools()与Provider.list_tools()构成清晰的“接口 增强实现”关系任何实现了Provider接口的组件源如文件系统 Provider、SQLite Provider、OpenAPI Provider 等都能复用统一的列举语义而FastMCP作为聚合层AggregateProvider负责汇总与增强。重构收益设计文档总结了这次整合的五点收益结合源码可以进一步印证收益说明源码印证单一事实来源每个组件类型只有一套列举方法不再存在双实现漂移四个list_*方法均位于 server.py无_list_*残留行为一致四类组件共享相同的去重语义、可见性过滤与鉴权流程每个方法体遵循同一模板super().list_*()→ 会话 transforms →is_enabled()→run_auth_checks()API 更清晰公开方法带显式run_middleware开关中间件行为可预期签名统一为*, run_middleware: bool True对齐 ProviderFastMCP.list_*()重写Provider.list_*()接口统一见 providers/base.py 与 server.py 中的 override更少代码删除了约 200 行重复实现合并前每个组件类型有两套方法合并后仅剩一套迁移指南从 v2 到 v3对升级到 FastMCP 3.0 的开发者代码迁移路径非常明确1. 方法重命名get_tools()→list_tools()get_resources()→list_resources()get_prompts()→list_prompts()get_resource_templates()→list_resource_templates()2. 返回类型适配旧版按名称索引的dict访问方式需要改为线性查找。如果代码中大量使用了tools[my_tool]这种访问模式可以封装一个小的辅助函数def find_tool(tools, name): return next((t for t in tools if t.name name), None)3. 中间件语义确认默认run_middlewareTrue会执行完整的中间件链行为与旧版协议路径一致若在自定义流程中希望跳过中间件直接获取原始组件列表显式传入run_middlewareFalse即可。这与旧版直接调用内部_list_*方法的效果等价但现在是通过公开 API 的参数完成的不再需要访问私有方法。涉及文件一览fastmcp_slim/fastmcp/server/server.py四个规范的list_*方法list_tools位于第 834 行、list_resources位于第 971 行、list_resource_templates位于第 1106 行、list_prompts位于第 1242 行以及_dispatch_component_middleware第 579 行fastmcp_slim/fastmcp/server/providers/base.pyProvider基类定义list_*接口fastmcp_slim/fastmcp/server/mixins/mcp_operations.py协议层_on_list_*处理器负责按name/uri/uri_template去重后返回 wire 格式dev-docs/v3-notes/get-methods-consolidation.md本次重构的设计决策记录本文的直接依据dev-docs/v3-notes/v3-features.mdFastMCP 3.0 整体特性笔记可对照了解重构在版本中的定位。总结FastMCP 3.0 的组件发现方法整合是一次典型的“接口收敛”重构通过两阶段演进先合并为get_*、再随Provider抽象重命名为list_*消除了公开 API 与内部协议路径的双实现统一了返回类型dict→Sequence、中间件语义run_middleware参数与去重职责协议层负责 wire 去重。对开发者而言迁移成本集中在方法重命名与返回类型适配上而收益是更一致、更可预期、更易维护的组件列举 API。【免费下载链接】fastmcp The fast, Pythonic way to build MCP servers and clients.项目地址: https://gitcode.com/GitHub_Trending/fa/fastmcp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考