资源(Resources)将服务器中的数据和内容暴露给大语言模型(LLMs)
在模型上下文协议(MCP)中,资源是一个核心基本元素,允许服务器将数据和内容暴露给客户端,并作为LLM交互的上下文使用。资源的设计是应用程序控制的,这意味着客户端应用程序可以决定何时以及如何使用这些资源。不同的MCP客户端可能会以不同的方式处理资源,例如:
- Claude Desktop 目前要求用户显式选择资源后才能使用。
- 其他客户端可能会根据启发式方法自动选择资源。
- 某些实现甚至可能允许AI模型本身决定使用哪些资源。
服务器作者在实现资源支持时应准备好处理这些交互模式。为了自动向模型暴露数据,服务器作者应使用模型控制的工具(如Tools)。
概述
资源代表MCP服务器希望向客户端提供的任何类型的数据。这可以包括:
每个资源由一个唯一的URI标识,并且可以包含文本或二进制数据。
资源URI
资源使用以下格式的URI进行标识:
[协议]://[主机]/[路径]
例如:
file:///home/user/documents/report.pdf
postgres://database/customers/schema
screen://localhost/display1
协议和路径结构由MCP服务器实现定义。服务器可以定义自己的自定义URI方案。
资源类型
资源可以包含两种类型的内容:
文本资源
文本资源包含UTF-8编码的文本数据,适用于:
- 源代码
- 配置文件
- 日志文件
- JSON/XML数据
- 纯文本
二进制资源
二进制资源包含以base64编码的原始二进制数据,适用于:
- 图像
- PDF文件
- 音频文件
- 视频文件
- 其他非文本格式
资源发现
客户端可以通过两种主要方法发现可用资源:
直接资源
服务器通过resources/list
端点暴露具体的资源列表。每个资源包括:
{
"uri": "string", // 资源的唯一标识符
"name": "string", // 人类可读的名称
"description": "string", // 可选的描述
"mimeType": "string" // 可选的MIME类型
}
资源模板
对于动态资源,服务器可以暴露URI模板,客户端可以使用这些模板构建有效的资源URI:
{
"uriTemplate": "string", // 遵循RFC 6570的URI模板
"name": "string", // 此类型的名称
"description": "string", // 可选的描述
"mimeType": "string" // 所有匹配资源的可选MIME类型
}
读取资源
客户端通过发送resources/read
请求并附带资源URI来读取资源。服务器响应包含资源内容列表:
{
"contents": [
{
"uri": "string", // 资源的URI
"mimeType": "string", // 可选的MIME类型
"text": "string", // 文本资源的内容
"blob": "string" // 二进制资源的内容(base64编码)
}
]
}
服务器可能会在一次resources/read
请求中返回多个资源,例如读取目录时返回目录中的所有文件。
资源更新
MCP支持通过两种机制进行资源的实时更新:
列表变化
服务器可以通过notifications/resources/list_changed
通知客户端可用资源列表的变化。
内容变化
客户端可以订阅特定资源的更新:
- 客户端发送
resources/subscribe
请求并附带资源URI。 - 服务器在资源更新时发送
notifications/resources/updated
通知。 - 客户端可以通过
resources/read
获取最新内容。 - 客户端可以通过
resources/unsubscribe
取消订阅。
示例实现
以下是一个简单的MCP服务器资源支持实现示例:
const server = new Server({
name: "example-server",
version: "1.0.0"
}, {
capabilities: {
resources: {}
}
});
// 列出可用资源
server.setRequestHandler(ListResourcesRequestSchema, async () => {
return {
resources: [
{
uri: "file:///logs/app.log",
name: "Application Logs",
mimeType: "text/plain"
}
]
};
});
// 读取资源内容
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
const uri = request.params.uri;
if (uri === "file:///logs/app.log") {
const logContents = await readLogFile();
return {
contents: [
{
uri,
mimeType: "text/plain",
text: logContents
}
]
};
}
throw new Error("Resource not found");
});
总结
资源是MCP中的核心概念,允许服务器将数据和内容暴露给客户端,并作为LLM交互的上下文。资源的设计灵活,支持多种数据类型和交互模式。通过URI标识资源,客户端可以发现、读取和订阅资源的变化。服务器作者应根据不同的客户端需求实现资源支持,并考虑使用模型控制的工具来自动暴露数据。