FastMCP MCPMixin 组件化指南用类方法与装饰器批量注册 Tool / Resource / Prompt【免费下载链接】fastmcp The fast, Pythonic way to build MCP servers and clients.项目地址: https://gitcode.com/GitHub_Trending/fa/fastmcp本文以 fastmcp_slim/fastmcp/contrib/mcp_mixin/README.md 为核心讲解 FastMCP 提供的MCPMixin基类与mcp_tool、mcp_resource、mcp_prompt三个装饰器开发者可以在普通类中定义方法然后一次性把它们注册为 MCP Server 上的工具、资源和提示词。读完本文你将掌握基于类的组件化开发方式、enabled/exclude_args/annotations/meta等高级配置以及用prefix和分隔符解决多实例命名冲突的完整方案。MCPMixin 解决什么问题常规 FastMCP 开发中工具、资源和提示词分散在模块级函数上通过FastMCP.tool()、FastMCP.resource()、FastMCP.prompt()装饰器逐个挂到 server 上。当组件数量变多或者需要把一组相关能力例如一个数据组件同时暴露查询工具、配置资源与分析提示词组织成可复用的单元时Mixin 模式更具优势用类把相互关联的方法聚合在一起天然获得命名空间与复用能力用装饰器在方法定义处声明注册意图无需手动调用 server 的注册 API通过register_all()等注册方法一次把整类的方法批量挂到FastMCP实例上支持prefix前缀多个同类实例可以共存而不产生名称冲突。MCPMixin的实现位于 mcp_mixin.py对外导出见init.py为from fastmcp.contrib.mcp_mixin import MCPMixin, mcp_tool, mcp_resource, mcp_prompt快速上手第一个 MCPMixin 组件继承MCPMixin在方法上使用装饰器然后调用register_all()注册即可from mcp_types import ToolAnnotations from fastmcp import FastMCP from fastmcp.contrib.mcp_mixin import MCPMixin, mcp_tool, mcp_resource, mcp_prompt class MyComponent(MCPMixin): mcp_tool(namemy_tool, descriptionDoes something cool.) def tool_method(self): return Tool executed! mcp_resource(uricomponent://data) def resource_method(self): return {data: some data} mcp_prompt(namegreeting) def prompt_method(self, name): return fWhats up {name}? mcp_server FastMCP() component MyComponent() component.register_all(mcp_server, prefixmy_comp) # 注册后 # - 工具名为 my_comp_my_tool # - 资源 URI 为 my_compcomponent://data # - 提示词名为 my_comp_greeting如果不传prefix则直接使用装饰器中指定的原始名称 / URIcomponent.register_all(mcp_server) # 注册为 my_tool / component://data / greeting装饰器 API 与参数说明三个装饰器在行为上保持一致的设计它们并不立即把方法注册到任何 server而是把注册参数以属性形式标记在函数对象上等待register_*方法在遍历类方法时读取。因此所有参数最终都会转发给底层工厂方法装饰器底层工厂方法必填参数关键可选参数mcp_toolTool.from_function无默认使用方法名name、description、enabled、exclude_args、annotations、meta、tags、auth、timeout、version、title、icons、output_schema、task、run_in_threadmcp_resourceResource.from_functionuriname、enabled、title、description、mime_type、tags、annotations、meta、auth、version、iconsmcp_promptPrompt.from_function无默认使用方法名name、enabled、title、description、tags、meta、auth、version、icons其中enabled是 Mixin 体系新增的标志位底层工厂方法并没有这个参数用来在注册阶段过滤方法其余参数直接透传给from_function。三个工厂方法的完整签名可分别查看 Tool.from_function、Resource.from_function 与 Prompt.from_function。装饰器参数校验未知参数立即报错三个装饰器都会在装饰时校验关键字参数是否合法而不是等到注册时才报错。它们依据底层from_function的签名自动推导合法参数集合例如 mcp_mixin.py 中的实现_TOOL_VALID_KWARGS: frozenset[str] frozenset( p for p in inspect.signature(Tool.from_function).parameters if p ! fn )一旦传入未识别的参数立即抛出TypeError错误信息会列出所有合法参数。相关行为在 tests/contrib/test_mcp_mixin.py 的TestMCPMixinValidation中有完整覆盖with pytest.raises(TypeError, matchunexpected keyword argument): mcp_tool(definitely_not_a_real_paramoops) def my_tool(self): passTool注解、禁用与参数排除使用enabledFalse禁用工具enabledFalse的方法不会在注册阶段被挂载客户端自然也无法调用mcp_tool(namemy_tool, descriptionDoes something cool., enabledFalse) def disabled_tool_method(self): return Youll never get here!从源码看enabled被存放在一个专用的哨兵键_mixin_enabled中避免与from_function的任何参数冲突注册时通过registration_info.pop(_MIXIN_ENABLED_KEY, True)取出并判断见 mcp_mixin.py。enabled默认值为True不传即正常注册这一行为在TestMCPMixinEnabled测试类中得到了验证。使用exclude_args排除危险参数某些内部参数不希望暴露给 MCP 客户端时用exclude_args把它们从工具的 JSON Schema 中剔除mcp_tool( namemy_tool, descriptionDoes something cool., enabledFalse, exclude_args[delete_everything], ) def excluded_param_tool_method(self, delete_everythingFalse): # MCP 客户端永远无法传入 delete_everything 参数 if delete_everything: return Nothing to delete, I bet youre not a tool :) return You might be a tool if...使用annotations指导 LLM 行为ToolAnnotations用于向 LLM 客户端声明工具的调用语义是否只读、是否破坏性、是否幂等帮助模型决定调用顺序与方式mcp_tool( namemy_tool, descriptionDoes something cool., annotationsToolAnnotations( titleAttn LLM, use this tool first!, readOnlyHintFalse, destructiveHintFalse, idempotentHintFalse, ) ) def tool_method(self): return Tool executed!组合全部能力enabled、exclude_args与annotations可以同时使用mcp_tool( namemy_tool, descriptionDoes something cool., enabledTrue, exclude_args[delete_all], annotationsToolAnnotations( titleAttn LLM, use this tool first!, readOnlyHintFalse, destructiveHintFalse, idempotentHintFalse, ) ) def tool_method(self, delete_allFalse): if delete_all: return 99 records deleted. I bet youre not a tool :) return Tool executed, but you might be a tool!使用meta附加自定义元数据meta可以携带任意键值对版本、分类、作者等会原样写入工具对象供服务端或客户端消费mcp_tool( namedata_tool, descriptionFetches user data from database, meta{version: 2.0, category: database, author: dev-team} ) def data_tool_method(self, user_id: int): return fFetching data for user {user_id}测试 test_tool_with_title_and_meta 验证了annotations.title与meta都会完整透传到注册后的工具对象上assert tool.annotations.title My Tool Title assert tool.meta {version: 1.0, author: test}ResourceURI 注册、禁用与元数据资源通过uri标识支持enabled、title、meta等配置# 基础资源 mcp_resource(uricomponent://data) def resource_method(self): return {data: some data} # 禁用资源 mcp_resource(uricomponent://data, enabledFalse) def resource_method(self): return {data: some data} # 带 title 与 meta 的资源 mcp_resource( uricomponent://config, titleData resource Title, meta{internal: True, cache_ttl: 3600, priority: high} ) def config_resource_method(self): return {config: data}注意资源注册时的enabledFalse处理与工具一致通过pop(_MIXIN_ENABLED_KEY, True)判断后直接continue跳过见 mcp_mixin.py。test_resource_with_meta测试则验证了meta与title会写入最终的FunctionResource对象。Prompt名称、禁用与上下文提示提示词用于定义可复用的 prompt 模板方法返回值将作为用户消息内容# 基础 prompt mcp_prompt(nameA prompt) def prompt_method(self, name): return fWhats up {name}? # 禁用 prompt mcp_prompt(nameA prompt, enabledFalse) def prompt_method(self, name): return fWhats up {name}? # 带 title、description 与 meta 的 prompt mcp_prompt( nameanalysis_prompt, titleData Analysis Prompt, descriptionAnalyzes data patterns, meta{complexity: high, domain: analytics, requires_context: True} ) def analysis_prompt_method(self, dataset: str): return fAnalyze the patterns in {dataset}test_prompt_with_title_and_meta测试确认了title与meta会被正确透传。用 prefix 与分隔符解决多实例命名冲突register_all的prefix参数是可选的。当同一个类被实例化多次并需要同时注册时例如为两组配置分别暴露组件前缀可以避免工具名、资源 URI 与提示词名互相覆盖component.register_all(mcp_server, prefixmy_comp)register_all的完整签名如下见 mcp_mixin.pydef register_all( self, mcp_server: FastMCP, prefix: str | None None, tool_separator: str _, # 工具名默认分隔符 resource_separator: str , # 资源名/URI 默认分隔符 prompt_separator: str _, # 提示词名默认分隔符 ) - None它内部依次调用register_tools、register_resources、register_prompts并把各自的separator传递下去。各注册方法对前缀的处理方式为工具f{prefix}{separator}{original_name}例如my_comp_my_tool资源名称与 URI 都会被加前缀f{prefix}{separator}{original_name}与f{prefix}{separator}{original_uri}例如my_compcomponent://data提示词f{prefix}{separator}{original_name}例如my_comp_greeting。三种类型使用不同的默认分隔符工具_、资源、提示词_既保持了各自生态的惯例资源 URI 通常用连接也可以通过register_all的tool_separator/resource_separator/prompt_separator参数按类型单独定制。仓库自带的 example.py 演示了多实例场景——同一个Sample类创建两个实例用不同前缀注册组件名称互不干扰first_sample Sample(First) second_sample Sample(Second) first_sample.register_all(mcp_servermcp, prefixfirst) second_sample.register_all(mcp_servermcp, prefixsecond)TestMCPMixin测试类用参数化用例系统验证了三种组合无前缀、默认分隔符、自定义分隔符工具-、资源::、提示词.并断言前缀后的名称/URI 精确匹配预期值见 test_mcp_mixin.py。注册流程MCPMixin 是如何工作的从源码结构看注册机制分三步标记阶段mcp_tool/mcp_resource/mcp_prompt在装饰时把注册参数含name、uri及全部透传 kwargs以属性形式附加到方法上分别对应_mcp_tool_registration、_mcp_resource_registration、_mcp_prompt_registration三个属性见 mcp_mixin.py。收集阶段_get_methods_to_register()遍历dir(self)筛选出带有对应标记属性的可调用方法返回(方法, 注册信息副本)列表。注册阶段register_tools/register_resources/register_prompts依次完成——应用前缀与分隔符 → 弹出enabled哨兵键并跳过False的方法 → 调用Tool/Resource/Prompt.from_function(fnmethod, **registration_info)构建组件 → 通过mcp_server.add_tool/add_resource/add_prompt挂载。由于合法 kwargs 集合在导入时直接从from_function签名推导_TOOL_VALID_KWARGS等当底层工厂方法新增参数如auth、timeout、version时装饰器无需手工同步即可透传新参数。TestMCPMixinKwargsSync测试类专门断言了这两者始终一致TestMCPMixinNewParams则端到端验证了authrequire_scopes(...)、timeout5.0、version2.0等参数都能经装饰器正确转发到注册后的组件上见 tests/contrib/test_mcp_mixin.py。进阶组合与完整示例把上述能力组合起来一个完整的数据服务组件可以同时提供带注解的安全工具、带元数据的资源与带描述的分析提示词from fastmcp import FastMCP from fastmcp.contrib.mcp_mixin import MCPMixin, mcp_tool, mcp_resource, mcp_prompt from mcp_types import ToolAnnotations class DataComponent(MCPMixin): mcp_tool( namequery_users, descriptionQuery users from the database, annotationsToolAnnotations(readOnlyHintTrue, destructiveHintFalse), meta{version: 1.0, owner: data-team}, timeout30.0, ) def query_users(self, limit: int 10): return fSELECT * FROM users LIMIT {limit} mcp_resource( uricomponent://config, titleComponent Configuration, meta{cache_ttl: 3600}, ) def config(self): return {feature_flags: [search, export]} mcp_prompt( nameaudit_report, titleAudit Report Prompt, descriptionGenerates an audit report for a user, ) def audit_report(self, user_id: int): return fGenerate an audit report for user {user_id} server FastMCP(data-service) DataComponent().register_all(server) # 无前缀注册若需要同时挂载多个同类实例改用prefix即可避免命名空间冲突再配合tool_separator/resource_separator/prompt_separator调整命名风格。小结MCPMixin把 FastMCP 的函数式注册升级为类化组件化注册核心收益有三点方法即组件装饰器声明 批量注册、声明即配置enabled/exclude_args/annotations/meta全部在装饰器内声明、实例即命名空间prefix 按类型分隔符解决多实例冲突。配合装饰器在导入期自动与from_function签名同步的能力新参数可以零成本透传开发者只需要关注类方法本身的实现即可。核心实现mcp_mixin.py完整示例example.py测试覆盖tests/contrib/test_mcp_mixin.py相关能力文档Tools、Resources、Prompts【免费下载链接】fastmcp The fast, Pythonic way to build MCP servers and clients.项目地址: https://gitcode.com/GitHub_Trending/fa/fastmcp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
