在MCP框架中,资源(Resources)是一种强大的机制,允许AI应用访问和管理各种类型的数据。本文将深入探讨MCP的资源系统,展示如何创建和使用不同类型的资源,包括静态文本、模板化内容、结构化数据和文件资源。通过这些示例,你将了解如何为AI应用提供丰富的数据访问能力,使其能够获取所需的信息来完成复杂任务。
资源系统简介
MCP的资源系统允许开发者以统一的方式定义和访问各种数据源。每个资源都通过唯一的URI标识,客户端可以使用这些URI来请求资源内容。资源系统的主要特点包括:
- 统一访问接口:所有资源通过相同的API进行访问多种数据类型支持:文本、JSON、二进制数据等动态内容生成:基于参数动态生成资源内容MIME类型控制:指定资源的内容类型
资源类型与实现
1. 静态URI文本资源
最简单的资源类型是静态文本资源,它返回预定义的文本内容:
@mcp.resource("data://static/text")def get_static_text(): """一个简单的静态URI文本资源示例""" return """这是一个静态URI文本资源。它使用简单的纯文本格式,没有特殊的格式化。适用于提供简单的文本信息。"""
这种资源适用于提供固定的说明文档、帮助信息或其他不需要动态生成的文本内容。
2. 模板化URI资源
模板化URI资源允许在URI中包含参数,从而根据请求动态生成内容:
@mcp.resource("data://template/{name}")def get_template(name: str): """一个带参数的模板化URI资源示例""" return f"""你好,{name}!这是一个针对你定制的模板化资源。模板化URI允许根据URI参数动态生成内容。"""
通过在URI路径中使用花括号定义参数,MCP会自动解析这些参数并传递给资源函数。这对于创建个性化内容或基于输入参数返回不同数据非常有用。
3. JSON数据资源
对于结构化数据,可以使用JSON格式并指定适当的MIME类型:
@mcp.resource("data://json", mime_type="application/json")def get_json_data(): """一个包含JSON格式数据的资源示例""" data = { "name": "JSON资源示例", "type": "结构化数据", "features": ["易于解析", "支持嵌套", "广泛应用"], "timestamp": datetime.now().isoformat(), "metadata": { "version": "1.0", "author": "MCP示例" } } return json.dumps(data, ensure_ascii=False, indent=2)
通过指定mime_type="application/json"
,客户端可以知道这是JSON数据,从而进行适当的处理。
4. 二进制数据资源
MCP也支持二进制数据资源,通常以Base64编码字符串的形式返回:
@mcp.resource("data://binary", mime_type="application/octet-stream")def get_binary_data(): """一个包含二进制数据的资源示例""" # 生成二进制数据 ("Hello MCP" 的ASCII码) binary_data = bytes([0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x4D, 0x43, 0x50]) # 将二进制数据编码为Base64字符串返回 return base64.b64encode(binary_data).decode('ascii')
对于二进制数据,我们使用mime_type="application/octet-stream"
,并将数据编码为Base64字符串。
5. 文件资源
MCP提供了FileResource
类,用于直接从文件系统加载资源内容:
# 使用绝对路径创建FileResourcemcp.add_resource(FileResource( uri="file://demo.txt", name="demo.txt", path=Path(data_html_path), # 使用绝对路径 encoding="utf-8" # 显式指定UTF-8编码))
文件资源特别适合提供较大的文本文件、配置文件或其他需要从文件系统加载的内容。
客户端访问资源
在客户端,我们可以使用session.read_resource()
方法来访问资源:
# 列出所有可用资源resources = await session.list_resources()# 读取静态文本资源result = await session.read_resource("data://static/text")# 读取带参数的模板化资源result = await session.read_resource("data://template/张三")# 读取JSON数据资源result = await session.read_resource("data://json")# 读取二进制数据资源result = await session.read_resource("data://binary")# 读取文件资源result = await session.read_resource("file://demo.txt")
输出的结果如下:
data.html 文件绝对路径: D:\svn\github.com\ai-learning\mcp\..\demo.txt=== 可用资源列表 ===资源列表类型: <class 'mcp.types.ListResourcesResult'>resources 属性类型: <class 'list'>资源列表内容:meta=None nextCursor=None resources=[Resource(uri=AnyUrl('data://static/text'), name='get_static_text', description='一个简单的静态 URI 文本资源示例', mimeType='text/plain', size=None, annotations=None), Resource(uri=AnyUrl('data://json'), name='get_json_data', description='一个包含 JSON 格式数据的资源示例', mimeType='application/json', size=None, annotations=None), Resource(uri=AnyUrl('data://binary'), name='get_binary_data', description='一个包含二进制数据的资源示例', mimeType='application/octet-stream', size=None, annotations=None), Resource(uri=AnyUrl('file://demo.txt/'), name='demo.txt', description=None, mimeType='text/plain', size=None, annotations=None)]资源对象属性: meta: None nextCursor: None resources: [Resource(uri=AnyUrl('data://static/text'), name='get_static_text', description='一个 简单的静态 URI 文本资源示例', mimeType='text/plain', size=None, annotations=None), Resource(uri=AnyUrl('data://json'), name='get_json_data', description='一个包含 JSON 格式数据的资源示例', mimeType='application/json', size=None, annotations=None), Resource(uri=AnyUrl('data://binary'), name='get_binary_data', description='一个包含二进制数据的资源示例', mimeType='application/octet-stream', size=None, annotations=None), Resource(uri=AnyUrl('file://demo.txt/'), name='demo.txt', description=None, mimeType='text/plain', size=None, annotations=None)]资源对象可用方法和属性: meta: NoneD:\svn\github.com\ai-learning\mcp\02_resource_examples.py:120: PydanticDeprecatedSince211: Accessing the 'model_computed_fields' attribute on the instance is deprecated. Instead, you should access this attribute from the model class. Deprecated in Pydantic V2.11 to be removed in V3.0. attr_value = getattr(resources, attr_name) model_computed_fields: {} model_config: {'extra': 'allow'} model_extra: {}D:\svn\github.com\ai-learning\mcp\02_resource_examples.py:120: PydanticDeprecatedSince211: Accessing the 'model_fields' attribute on the instance is deprecated. Instead, you should access this attribute from the model class. Deprecated in Pydantic V2.11 to be removed in V3.0. attr_value = getattr(resources, attr_name) model_fields: {'meta': FieldInfo(annotation=Union[dict[str, Any], NoneType], required=False, default=None, alias='_meta', alias_priority=2), 'nextCursor': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'resources': FieldInfo(annotation=list[Resource], required=True)} model_fields_set: {'resources'} nextCursor: None resources: [Resource(uri=AnyUrl('data://static/text'), name='get_static_text', description='一个 简单的静态 URI 文本资源示例', mimeType='text/plain', size=None, annotations=None), Resource(uri=AnyUrl('data://json'), name='get_json_data', description='一个包含 JSON 格式数据的资源示例', mimeType='application/json', size=None, annotations=None), Resource(uri=AnyUrl('data://binary'), name='get_binary_data', description='一个包含二进制数据的资源示例', mimeType='application/octet-stream', size=None, annotations=None), Resource(uri=AnyUrl('file://demo.txt/'), name='demo.txt', description=None, mimeType='text/plain', size=None, annotations=None)]继续测试各个资源...=== 测试静态 URI 文本资源 ===结果类型: <class 'mcp.types.ReadResourceResult'>内容:meta=None contents=[TextResourceContents(uri=AnyUrl('data://static/text'), mimeType='text/plain', text='这是一个静态 URI 文本资源。\n它使用简单的纯文本格式,没有特殊的格式化。\n适用于提供简单的文本 信息。')]=== 测试模板化 URI 资源 ===内容:meta=None contents=[TextResourceContents(uri=AnyUrl('data://template/%E5%BC%A0%E4%B8%89'), mimeType='text/plain', text='你好,%E5%BC%A0%E4%B8%89!\n这是一个针对你定制的模板化资源。\n模板化 URI 允许 根据 URI 参数动态生成内容。')]=== 测试 JSON 数据资源 ===结果: meta=None contents=[TextResourceContents(uri=AnyUrl('data://json'), mimeType='application/json', text='{\n "name": "JSON 资源示例",\n "type": "结构化数据",\n "features": [\n "易于解析",\n "支持嵌套",\n "广泛应用"\n ],\n "timestamp": "2025-06-22T19:07:40.470767",\n "metadata": {\n {"version": "1.0",\n "author": "MCP 示例"\n }\n}')]\n "version": "1.0",\n "author": "MCP 示例"\n }\n}')]n "支持嵌套",\n "广泛应用"\n ],\n "timestamp": "2025-06-22T19:07:40.470767",\n "metadata": {\n "version": "1.0",\n "author": "MCP 示例"\n }\n}')] tet-st=== 测试二进制数据资源 ===结果: meta=None contents=[TextResourceContents(uri=AnyUrl('data://binary'), mimeType='application/octet-stream', text='SGVsbG8gTUNQ')] , text=== 测试文件资源 ===结果: meta=None contents=[TextResourceContents(uri=AnyUrl('file://demo.txt/'), mimeType='text/plain', text='this is demo file content')]
资源的返回值可能是简单的字符串,也可能是包含内容和MIME类型的元组,具体取决于MCP的实现版本。
资源使用最佳实践
- 合理组织URI命名空间:使用有意义的前缀和路径结构,如
data://
、file://
等提供清晰的资源描述:为每个资源函数添加详细的文档字符串适当使用MIME类型:为不同类型的内容指定正确的MIME类型处理异常情况:在资源函数中添加适当的错误处理考虑资源缓存:对于不经常变化的大型资源,考虑实现缓存机制