![[FastMCP设计、原理与应用-07]FastMCP核心组件:资源和资源模板](http://pic.xiahunao.cn/yaotu/[FastMCP设计、原理与应用-07]FastMCP核心组件:资源和资源模板)
原语Primitive是MCP规范中最为核心的概念我们在“Primitive——MCP最核心的概念”的四大核心原语工具、静态资源、动态资源模板和提示词进行了系统介绍。FastMCP实现了这个四个原语并将它们统称为组件对应的类型以FastMCPComponent为基类本篇文章主要介绍与资源相关的两个组件。1. FastMCPComponent四个原语对应的组件类型都有一个共同的基类FastMCPComponent后者派生自FastMCPBaseModel。classFastMCPBaseModel(BaseModel):model_configConfigDict(extraforbid)classFastMCPComponent(FastMCPBaseModel):KEY_PREFIX:ClassVar[str]name:strversion:strtitle:str|Nonedescription:str|Noneicons:list[Icon]|Nonetags:set[str]meta:dict[str,Any]|Nonetask_config:TaskConfigFastMCPComponent利用类变量KEY_PREFIX作为与类型关联的前缀子类可以指定不同的前缀来解决一些命名或者主键冲突问题。上面列出来它所有的字段具体说明如下name组件名称作为唯一标识符version: 组件版本用于组件的版本管理方便在升级工具逻辑时进行兼容性追踪title:人类可读的标题在UI界面中展示的友好名称description: 功能描述。这是最重要的字段之一LLM 依靠它来理解何时以及如何使用这个组件;icons: 图标列表。定义该组件在客户端 UI 中显示的图标;tags: 标签集合用于对组件进行分类和检索;meta: 元数据字典。存放不属于标准协议的自定义信息提供扩展性task_config任务配置对象。定义该组件运行时的底层配置如超时时间、重试策略或并发限制。像name、title、description、icons和meta这些字段成员都可以在MCP原语中找到。task_config字段返回的TaskConfig与前面介绍的将同步等待转变为异步轮询的后台任务协议功能有关TaskConfig的mode字段返回的TaskMode与前面介绍的TaskExecutionMode完全对等。poll_interval资源用于设置跟踪任务状态的轮询间隔默认为5秒。TaskConfig的support_tasks方法确定组件是否支持后台任务协议返回值取决于mode是否被设置为forbidden。类方法from_bool则进行反向操作将指定的布尔值转换成TaskConfig对象True和Fals分别对应optional和forbidden模式。dataclassclassTaskConfig:mode:TaskModeoptionalpoll_interval:timedeltaDEFAULT_POLL_INTERVALclassmethoddeffrom_bool(cls,value:bool)-TaskConfigdefsupports_tasks(self)-boolTaskModeLiteral[forbidden,optional,required]DEFAULT_POLL_INTERVALtimedelta(seconds5)除了上面列出的字段FastMCPComponent类型还定义一些额外的方法和特性成员。classFastMCPComponent(FastMCPBaseModel):classmethoddefmake_key(cls,identifier:str)-strpropertydefkey(self)-strdefget_meta(self)-dict[str,Any]defcopy(self)-Selfdefregister_with_docket(self,docket:Docket)-Noneasyncdefadd_to_docket(self,docket:Docket,*args:Any,**kwargs:Any)-Executiondefget_span_attributes(self)-dict[str,Any]各成员说明如下make_key根据指定的identifier返回一个Key默认返回[{cls.KEY_PREFIX}:]{identifier}key特性方法。快捷返回当前实例的唯一键默认返回[{cls.KEY_PREFIX}:]{identifier}[{version}]get_meta返回元数据字典会在meta字段的基础上添加fastmcp的元数据copy调用model_copy方法创建一个拷贝get_span_attributes这个与OpenTelemetry的调用链跟踪有关用于返回代表操作的Span对象的属性。FastMCPComponent还定义了如下两方法它们与我们提过多次的后台任务协议有关。Docket就是FastMCP的任务调度器Scheduler如果某个组件需要以后台任务的方式调度执行必需先调用register_with_docket将自身注册到Docket对象上然后调用add_to_docket方法通知Docket实施调度这个后台执行的任务通过Execution对象返回。我们将在一个独立的章节中介绍这个重要的功能。classFastMCPComponent(FastMCPBaseModel):defregister_with_docket(self,docket:Docket)-Noneasyncdefadd_to_docket(self,docket:Docket,*args:Any,**kwargs:Any)-Execution2. 静态资源由固定URI标识的静态资源组件通过Resource类型表示下面给出该类型的部分成员。它通过定义KEY_PREFIX将基于该类型的KEY前缀设置为resource同时定义字段uri、name、mime_type和annotations表示资源的地址、名称、MIME类型和受众角色和优先级。classResource(FastMCPComponent):KEY_PREFIX:ClassVar[str]resourceuri:AnyUrl name:strmime_type:strannotations:Annotations|Noneauth:AuthCheck|list[AuthCheck]|Noneclassmethoddefset_default_mime_type(cls,mime_type:str|None)-strdefset_default_name(self)-Selfasyncdefread(self)-str|bytes|ResourceResultdefconvert_result(self,raw_value:Any)-ResourceResultdefto_mcp_resource(self,**overrides:Any,)-mcp.types.Resource定义的四个方法说明如下set_default_mime_type设置针对类型的默认MIME类型set_default_name将URI设置为默认的名称read读取资源的内容返回类型可以是字符串、字节数据和一个ResourceResult对象convert_resultResourceResult是FastMCP对资源读取结果的表达此方法将原始结果比如字符串和字节数据统一转换成ResourceResult类型to_mcp_resource将当前组件转换成mcp.types.Resource原语ResourceResult承载资源读取的结果。除了表示元数据字典的meta字段它还定义了contents字段提供一组ResourceContent对象来表示资源的内容。ResourceContent除了提供文本或者二进制内容外还提供了MIME类型和元数据字典。classResourceResult(pydantic.BaseModel):contents:list[ResourceContent]meta:dict[str,Any]|NoneNonedef__init__(self,contents:str|bytes|list[ResourceContent],meta:dict[str,Any]|NoneNone,)defto_mcp_result(self,uri:AnyUrl|str)-mcp.types.ReadResourceResultclassResourceContent(pydantic.BaseModel):content:str|bytesmime_type:str|NoneNonemeta:dict[str,Any]|NoneNonedef__init__(self,content:Any,mime_type:str|NoneNone,meta:dict[str,Any]|NoneNone,)defto_mcp_resource_contents(self,uri:AnyUrl|str)-mcp.types.TextResourceContents|mcp.types.BlobResourceContentsmcp库定义了类型Resource、ReadResourceResult、TextResourceContents和BlobResourceContents这四个类型它们分别用来表示资源原语、资源读取请求的结果和文本和二进制形式的资源内容所以FastMCP定义的这三个与资源相关的类型Resource、ResourceResult和ResourceContent都定义了对应的类型转换方法to_mcp_resource、to_mcp_result和to_mcp_resource_contents。2.1 FunctionResource在之前的演示中我们都是采用函数的形式来定义FastMCP的组件以这种方式定义的静态资源体现为一个FunctionResource对象。基类Resource的静态方法from_function作为创建FunctionResource的工厂方法该方法最终还是调用定义在FunctionResource中的类方法from_function完成FunctionResource对象的创建。classFunctionResource(Resource):fn:Callable[...,Any]classmethoddeffrom_function(cls,fn:Callable[...,Any],uri:str|AnyUrl|NoneNone,*,metadata:ResourceMeta|NoneNone,name:str|NoneNone,version:str|int|NoneNone,title:str|NoneNone,description:str|NoneNone,icons:list[Icon]|NoneNone,mime_type:str|NoneNone,tags:set[str]|NoneNone,annotations:Annotations|NoneNone,meta:dict[str,Any]|NoneNone,task:bool|TaskConfig|NoneNone,auth:AuthCheck|list[AuthCheck]|NoneNone,)-FunctionResourceasyncdefread(self,)-str|bytes|ResourceResultclassResource(FastMCPComponent):classmethoddeffrom_function(cls,fn:Callable[...,Any],uri:str|AnyUrl|NoneNone,*,metadata:ResourceMeta|NoneNone,name:str|NoneNone,version:str|int|NoneNone,title:str|NoneNone,description:str|NoneNone,icons:list[Icon]|NoneNone,mime_type:str|NoneNone,tags:set[str]|NoneNone,annotations:Annotations|NoneNone,meta:dict[str,Any]|NoneNone,task:bool|TaskConfig|NoneNone,auth:AuthCheck|list[AuthCheck]|NoneNone,)-FunctionResource值得一提的是FunctionResource的fn字段返回的函数是不包含注入参数的但是提供给类方法from_function的是原始的函数该函数可能包含数量和顺序不确定的注入参数所以类方法from_function会按照“为什么可以在MCP工具函数中以参数形式注入上下文”介绍的方式将原始函数转换成与Schema一致的函数以便直接利用提供的参数发起调用。2.2 其他静态资源除了FunctionResource这个用来描述利用函数定义的资源fastmcp.resources.types模块下还定义了其他类型的静态资源类型。如下所示的TextResource和BinaryResource将指定的文本和字节数组作为资源内容。classTextResource(Resource):text:strasyncdefread(self)-ResourceResultclassBinaryResource(Resource):data:bytesasyncdefread(self)-ResourceResult如下这个FileResource类型将指定文件对应表示文件路径的path字段的内容作为资源。我们可以利用is_binary指定文件是二进制还是文本默认为False文本文件。我们还可以指定利用mime_type和encoding指定MIME类型默认为text/plain和编码默认为utf-8。classFileResource(Resource):path:Path is_binary:boolmime_type:strencoding:str|Noneoverrideasyncdefread(self)-ResourceResult如下这个HttpResource会采用httpx远程读取url字段指定的网络内容作为资源内容我们可以利用mime_type字段指定MIME类型默认为application/jsonclassHttpResource(Resource):url:strmime_type:stroverrideasyncdefread(self)-ResourceResult如下这个DirectoryResource根据指定的目录对应path字段表示的绝对路径创建但是作为资源内容的并非该目录下相关文件的内容而只是文件的相对路径列表。我们可以利用recursive字段决定是否递归获取子目录下的文件默认为Falsepattern字段指定的文本用于文件过滤它遵循的是类似Shell命令行如ls *.py的Glob模式而不是正则表达式。mime_type字段用于自定MIME类型默认为application/json。classDirectoryResource(Resource):path:Path recursive:boolpattern:str|Nonemime_type:stroverrideasyncdefread(self)-ResourceResult:假设得到为文件相对路径列为file_list那么最终作为资源内容的文本是字典{files: file_list}以JSON序列化后的结果这就是为什么MIME类型的默认值被设置成application/json的原因。3. 动态资源模板通过URI模板表示的动态资源通过如下所示的ResourceTemplate类型表示它的KEY_PREFIX被设置为template。与Resource类型的不同之处体现在它利用uri_template字段表示的URI模板代表一组资源而parameters字段表示是动态资源函数输入参数的JSON Schema每个参数对应模板中一个占位符。classResourceTemplate(FastMCPComponent):KEY_PREFIX:ClassVar[str]templateuri_template:strmime_type:strparameters:dict[str,Any]annotations:Annotations|Noneauth:AuthCheck|list[AuthCheck]|Noneasyncdefread(self,arguments:dict[str,Any])-str|bytes|ResourceResultdefconvert_result(self,raw_value:Any)-ResourceResultasyncdefcreate_resource(self,uri:str,params:dict[str,Any])-Resourcedefto_mcp_template(self,**overrides:Any,)-mcp.types.ResourceTemplateclassmethoddeffrom_mcp_template(cls,mcp_template:mcp.types.ResourceTemplate)-ResourceTemplatestaticmethoddeffrom_function(fn:Callable[...,Any],uri_template:str,name:str|NoneNone,version:str|int|NoneNone,title:str|NoneNone,description:str|NoneNone,icons:list[Icon]|NoneNone,mime_type:str|NoneNone,tags:set[str]|NoneNone,annotations:Annotations|NoneNone,meta:dict[str,Any]|NoneNone,task:bool|TaskConfig|NoneNone,auth:AuthCheck|list[AuthCheck]|NoneNone,)-FunctionResourceTemplate:returnFunctionResourceTemplate.from_function(fnfn,uri_templateuri_template,namename,versionversion,titletitle,descriptiondescription,iconsicons,mime_typemime_type,tagstags,annotationsannotations,metameta,tasktask,authauth,)相关方法说明如下read利用指定参数arguments填充URI模板得到一个能够定位目标资源的URI然后读取对应的内容convert_result: 如果读取的内容不是ResourceResult对象则利用convert_result方法实施类型转换;to_mcp_template: 将自身组件转换成mcp.types.ResourceTemplate表示的资源模板原语from_mcp_template与to_mcp_template方法相反它将mcp.types.ResourceTemplate原语转换成ResourceTemplate组件create_resource: 根据指定的URI模板对应uri参数和填充参数对应params参数创建Resource定义在ResourceTemplate中的静态方法from_function会将资源模板函数转换成FunctionResourceTemplate对象最终调用的是FunctionResourceTemplate的同名类方法。FunctionResourceTemplate的实现原理与FunctionResource并无本质的差异。FunctionResourceTemplate还定义了create_resource根据指定的URI模板和填充参数创建Resource对象的方法该方法返回的是一个FunctionResource对象。classFunctionResourceTemplate(ResourceTemplate):fn:Callable[...,Any]asyncdefcreate_resource(self,uri:str,params:dict[str,Any])-Resourceasyncdefread(self,arguments:dict[str,Any])-str|bytes|ResourceResultclassmethoddeffrom_function(cls,fn:Callable[...,Any],uri_template:str,name:str|NoneNone,version:str|int|NoneNone,title:str|NoneNone,description:str|NoneNone,icons:list[Icon]|NoneNone,mime_type:str|NoneNone,tags:set[str]|NoneNone,annotations:Annotations|NoneNone,meta:dict[str,Any]|NoneNone,task:bool|TaskConfig|NoneNone,auth:AuthCheck|list[AuthCheck]|NoneNone,)-FunctionResourceTemplate