资源是模型上下文协议(MCP)中的一种核心基本元素,它使服务器能够公开数据和内容,这些数据和内容可供客户端读取,并用作大语言模型(LLM)交互时的上下文信息。
官方文档:https://modelcontextprotocol.io/docs/concepts/resources
一、资源简介
(一)概述
资源代表着模型上下文协议(MCP)服务器希望向客户端提供的任何类型的数据。这可以包括:
- 文件内容
- 数据库记录
- 应用程序编程接口(API)响应数据
- 实时系统数据
- 屏幕截图和图像
- 日志文件
- 以及更多其他数据
每个资源都由一个唯一的统一资源标识符(URI)来标识,并且可以包含文本数据或二进制数据。
(二)资源统一资源标识符(URI)
资源通过遵循以下格式的 URI 来进行标识:
[协议]://[主机]/[路径]
例如:
file:///home/user/documents/report.pdf
postgres://database/customers/schema
screen://localhost/display1
协议和路径结构由 MCP 服务器的实现来定义。服务器可以定义它们自己的自定义 URI 方案。
(三)资源类型
资源可以包含两种类型的内容:
文本资源
文本资源包含以 UTF-8 编码的文本数据。它们适用于以下场景:
- 源代码
- 配置文件
- 日志文件
- JSON/XML 数据
- 纯文本
二进制资源
二进制资源包含以 Base64 编码的原始二进制数据。它们适用于以下场景:
- 图像
- PDF 文件
- 音频文件
- 视频文件
- 其他非文本格式的文件
二、开发实践
源码仓库:https://gitee.com/fangjunjie/mcp-resources-demo
(一)MCP Server 关键代码解析
直接资源注册
// 直接资源
let appConfig = "一些配置内容"
mcpServer.resource(
"config",
"config://app",
async (uri) => ({
contents: [{
uri: uri.href,
text: appConfig
}]
})
);
注册资源的名称、地址、内容返回。
模板资源注册
// 模板资源
const userProfileResources = [{
uri: 'users://1001/profile',
name: 'user-1001-profile'
}]
// 注册模板资源
mcpServer.resource(
"user-profile",
new ResourceTemplate("users://{userId}/profile", {
list: async () => ({
resources: userProfileResources
})
}),
async (uri, {userId}) => ({
contents: [{
uri: uri.href,
text: `用户 ${userId} 的个性化配置`
}]
})
);
注册资源的名称、地址模板、内容返回。
ResourceTemplate
对象定义类资源模板。这里的 userId
就是一个动态参数。这里的 list
函数定义了可能的所有模板资源,如果不需要被客户端查询到所有资源列表,可以直接设置为 null
。
内容返回函数中的 contents
是一个内容对象数组。内容对象可以是文本内容也可以是二进制内容,对应 text
或 blob
字段。
资源更新时通知客户端
// 模拟资源动态更新
setInterval(async () => {
// 修改配置内容
appConfig = `一些配置内容${new Date().getTime()}`
// 随机增加一个用户配置
const userId = new Date().getTime()
userProfileResources.push({
uri: `users://${userId}/profile`,
name: `user-${userId}-profile`
})
if (transport) {
// 通知客户端资源列表更新
await mcpServer.server.notification({method: "notifications/resources/list_changed"});
// 通知客户端资源内容更新
await mcpServer.server.notification({method: "notifications/resources/updated", params: {uri: "config://app"}});
}
}, 5000)
notifications/resources/list_changed
为资源列表更新通知。
notifications/resources/updated
为资源内容更新通知,可以通过 params
参数传递具体资源信息。
(二)MCP Client 关键代码解析
获取资源列表
const resources = await client.listResources();
console.log("列出所有资源:")
console.log(resources)
读取资源内容
const resource = await client.readResource({uri: uri});
console.log("读取指定资源:")
console.log(resource)
订阅服务器通知
// 订阅资源更新
client.fallbackNotificationHandler = async (notification) => {
console.log("接收到通知:")
console.log(notification)
if (notification.method === "notifications/resources/list_changed") {
console.log("收到资源列表更新通知,读取资源列表。")
await listResources()
}
if (notification.method === "notifications/resources/updated") {
console.log("收到资源内容更新通知,读取资源内容。")
await readResource(notification.params!.uri as string)
}
};