[FastMCP设计、原理与应用-12]Provider——组件装载机,为框架按需配置功能单元与底层设施
2026/4/22 23:24:18 网站建设 项目流程

当客户端连接到您的服务器并询问“您有哪些组件(工具、资源、提示词和任务等)?”时,FastMCP会向每个Provider询问该问题并将结果汇​​总。当客户端调用某个工具读取指定资源时,FastMCP会查找哪个Provider拥有该工具或者资源,并将调用委托给该它。我们可以将Provider视为组件的来源,一个FastMCP服务器可以注册多个Provider。现在我们来介绍作为组件提供者的Provider

1. 两种添加Transform的方式

我们可以将注册的Transform列表作为参数调用构造函数来创建Provider对象,特性transforms返回注册的Transform列表。

classProvider:def__init__(self)->None:self._transforms:list[Transform]=[]@propertydeftransforms(self)->list[Transform]:returnlist(self._transforms)defadd_transform(self,transform:Transform)->None:self._transforms.append(transform)defwrap_transform(self,transform:Transform)->Provider:fromfastmcp.server.providers.wrapped_providerimport_WrappedProviderreturn_WrappedProvider(self,transform)

add_transformwrap_transform体现了两种不同的Transform添加方式:

  • add_transform:将指定的Transform对象添加当前ProviderTransform列表列表中,意味着Provider对象的状态发生了改变;
  • wrap_transform:它利用当前Provider和指定的Transform创建并返回一个新的Provider(类型为_WrappedProvider),当前Provider对象的状态保持不变;

2. 组件的提供与转换

对于FastMCP支持的四大组件(工具、资源、提示词和任务),它一共提供了九个基本操作(由于FastMCP并不支持任务作为一个专门的组件类型来创建,只能将其他三种组件以后台任务的形式执行,所以没有list_tasks操作)。我们来看看几个与工具相关方法的实现:

classProvider:asyncdeflist_tools(self)->Sequence[Tool]:tools=awaitself._list_tools()fortransforminself.transforms:tools=awaittransform.list_tools(tools)returntoolsasyncdefget_tool(self,name:str,version:VersionSpec|None=None)->Tool|None:asyncdefbase(n:str,version:VersionSpec|None=None)->Tool|None:returnawaitself._get_tool(n,version)chain=basefortransforminself.transforms:chain=partial(transform.get_tool,call_next=chain)returnawaitchain(name,version=version)asyncdef_list_tools(self)->Sequence[Tool]:return[]asyncdef_get_tool(self,name:str,version:VersionSpec|None=None)->Tool|None:tools=awaitself._list_tools()matching=[tfortintoolsift.name==name]ifversion:matching=[tfortinmatchingifversion.matches(t.version)]ifnotmatching:returnNonereturnmax(matching,key=version_sort_key)

定义在Provider中涉及工具的有如下四个方法:

  • _list_tools:提供所有工具列表,默认返回空列表,子类需要通过重写此方法提供具体的工具列表;
  • _get_tool:根据指定的名称和版本从_list_tools方法返回的列表中提取目标对象,如果没有指定版本,默认选择最高版本。如果没有匹配的工具,返回None;
  • list_tools: 调用_list_tools方法得到工具列表,然后应用所有的Transform;
  • get_tool:利用所有Transformget_tools方法和自身的_get_tool方法构建一个调用链,然后传入参数执行此调用链,这样便形成了如下所示的于Middleware一样的调用关系。

Provider针对其他三种组件也定义了类似的四个方法(对于任务没有list_tasks方法,只有get_task方法)。当我们自定义Provider的时候,我们基本上只会重写以下划线为前缀的_list_get方法。如果我们直接重写listget方法,意味着我们丢弃了注册的Transform(除非你自行添加应用Transform的代码)。

3. 生命周期管理

除此之外,它还定义了如下这个lifespan方法。

classProvider:@asynccontextmanagerasyncdeflifespan(self)->AsyncIterator[None]:yield

这个lifespan方法是一个异步上下文管理器,它的核心作用是管理Provider的生命周期资源(如数据库连接、API 客户端、线程池等):

  • 启动时:在服务器启动、Provider准备就绪前执行。用于建立连接、加载缓存或初始化重量级对象;
  • 运行时:通过yield将控制权交给服务器,此时Provider正常工作;
  • 关闭时:在服务器关闭时自动触发yield之后的代码。用于优雅地关闭连接、保存状态或清理临时文件;

如下这个演示实例清晰地体现了lifespan方法的作用。我们定义了一个需要全程连接数据库的DbProvider, 重写的lifespan方法确保Provider被使用的时候,数据库连接被开启,FastMCP服务关闭后,数据库连接被关闭。

fromcontextlibimportasynccontextmanagerfromtypingimportSelffromfastmcp.server.providersimportProviderfromfastmcpimportFastMCPfromfastmcp.clientimportClient log=[]classFakeDbConnection:asyncdefopen(self)->Self:log.append("DbConnection opened.")returnselfasyncdefclose(self):log.append("DbConnection closed.")classDbProvider(Provider):@asynccontextmanagerasyncdeflifespan(self):self.db=awaitFakeDbConnection().open()try:yieldfinally:awaitself.db.close()asyncdefmain():mcp=FastMCP("Server",providers=[DbProvider()])asyncwithClient(mcp)asclient:...assertlog==["DbConnection opened.","DbConnection closed."]

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询