Model Context Protocol(MCP)是一个为语言模型提供上下文的标准化协议。在与模型交互时,我们常常需要提供文件、数据、甚至是应用状态等外部信息,以获得更精准的回答。MCP 通过其核心概念 Resources,为这种需求提供了一套标准化的解决方案。
简单来说,Resources 是服务器向客户端暴露数据的一种方式。这些数据可以是文件、数据库模式、API 描述或任何能为语言模型提供上下文的信息。每一个资源都通过一个唯一的 URI (Uniform Resource Identifier) 来标识。
什么是 Resources?
在 MCP 中,Resources 的设计遵循“应用驱动”的原则。这意味着协议本身不强制规定用户界面(UI)应该如何呈现或使用这些资源,而是将决定权交给了宿主应用。
应用可以根据自身的需求,以多种方式整合 Resources。例如,一个代码编辑器可以通过一个树状视图展示项目中的所有文件,让用户手动选择需要作为上下文的文件。一个数据分析工具可能会提供搜索和筛选功能,帮助用户从大量的数据库表中找到相关的几个。也有些应用可能会基于某些启发式规则,或者根据 AI 模型自身的判断,自动将相关资源包含在上下文中。
这种设计的灵活性确保了 Resources 能够适应不同应用的特定场景,而不是将所有应用都限制在单一的交互模式里。协议只负责定义“如何暴露和获取资源”,而“如何使用资源”则由应用开发者决定。
如何与 Resources 交互?
客户端与服务器之间关于 Resources 的交互遵循一套明确的协议消息。整个过程从发现资源开始,到读取内容,再到处理可能的变更。
声明能力
在客户端使用 Resources 功能之前,服务器必须首先在 capabilities 中声明自己支持此功能。这是一个初始握手步骤,用于告知客户端服务器具备哪些能力。
一个支持 Resources 的服务器会在其能力声明中包含 resources 对象:
{
"capabilities": {
"resources": {
"subscribe": true,
"listChanged": true
}
}
}
resources 对象内有两个可选的布尔值字段,subscribe 和 listChanged,它们分别表示两种额外的能力。
| 字段 | 类型 | 含义 |
|---|---|---|
subscribe |
boolean |
true 表示客户端可以订阅单个资源,以便在该资源内容发生变化时收到通知。 |
listChanged |
boolean |
true 表示当可用的资源列表发生变化(如新增或删除资源)时,服务器会主动发送通知。 |
服务器可以根据自身实现,选择支持其中一个、两个或全都不支持。例如,一个只读的文件系统可能就不需要支持任何变更通知。
列出可用资源
客户端要发现服务器提供了哪些资源,需要发送一个 resources/list 请求。这个操作支持分页,允许客户端逐页获取完整的资源列表。
请求的格式很简单:
{
"jsonrpc": "2.0",
"id": 1,
"method": "resources/list",
"params": {
"cursor": "optional-cursor-value"
}
}
服务器会返回一个包含资源列表的响应。如果资源过多,nextCursor 字段会提供一个用于获取下一页数据的凭证。
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resources": [
{
"uri": "file:///project/src/main.rs",
"name": "main.rs",
"title": "Rust Software Application Main File",
"description": "Primary application entry point",
"mimeType": "text/x-rust"
}
],
"nextCursor": "next-page-cursor"
}
}
响应中的每个 resource 对象都包含了描述资源的基本信息,如 uri、name(名称)、title(用于展示的标题)、description(描述)和 mimeType(媒体类型)。
读取资源内容
当客户端确定了想要获取其内容的资源后,就可以通过该资源的 uri 发送一个 resources/read 请求。
请求中只需指定目标的 uri:
{
"jsonrpc": "2.0",
"id": 2,
"method": "resources/read",
"params": {
"uri": "file:///project/src/main.rs"
}
}
服务器收到请求后,会返回该资源的内容。资源的内容可以是文本(text)或二进制(blob)数据。二进制数据会以 Base64 编码的字符串形式提供。
这是一个返回文本内容的示例:
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"contents": [
{
"uri": "file:///project/src/main.rs",
"mimeType": "text/x-rust",
"text": "fn main() {\n println!(\"Hello world!\");\n}"
}
]
}
}
如果资源是一个图片文件,响应可能会是这样:
{
"uri": "file:///example.png",
"mimeType": "image/png",
"blob": "base64-encoded-data"
}
通过 resources/list 和 resources/read 这两个核心请求,客户端就完成了一次完整的“发现-获取”流程。

更高级的用法
除了基本的读写,MCP Resources 还提供了一些高级功能,以应对更复杂的场景,如动态资源和内容变更通知。
使用资源模板
有时,资源不是静态的,而是需要通过参数动态生成。例如,访问项目中的任意文件。如果为每个文件都创建一个静态资源,列表会变得非常冗长。Resource Templates(资源模板)就是为了解决这类问题。它使用 URI 模板(RFC 6570)来定义一类可参数化的资源。
客户端可以通过 resources/templates/list 请求获取所有可用的资源模板:
{
"jsonrpc": "2.0",
"id": 3,
"method": "resources/templates/list"
}
服务器返回的模板列表中,uriTemplate 字段定义了模板格式,例如 file:///{path},其中 {path} 就是一个需要客户端填充的参数。
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"resourceTemplates": [
{
"uriTemplate": "file:///{path}",
"name": "Project Files",
"title": "📁 Project Files",
"description": "Access files in the project directory"
}
]
}
}
订阅资源变更
对于内容可能频繁变动的资源,例如一个正在被编辑的文件或一个实时更新的日志,反复轮询 resources/read 是低效的。如果服务器在能力声明中设置了 subscribe: true,客户端就可以订阅特定资源的变更。
客户端发送 resources/subscribe 请求来订阅一个资源:
{
"jsonrpc": "2.0",
"id": 4,
"method": "resources/subscribe",
"params": {
"uri": "file:///project/src/main.rs"
}
}
订阅成功后,一旦该资源的内容发生变化,服务器就会主动向客户端发送一个 notifications/resources/updated 通知。
{
"jsonrpc": "2.0",
"method": "notifications/resources/updated",
"params": {
"uri": "file:///project/src/main.rs"
}
}
收到通知后,客户端就可以再次调用 resources/read 来获取最新的资源内容。
使用注解提供线索
为了帮助客户端更好地理解和使用资源,MCP 允许在资源、资源模板和内容块中添加 annotations(注解)。这些注解提供了一些额外的元数据,作为给客户端的“提示”。
常见的注解包括:
audience: 一个数组,表明资源的目标受众,可选值为"user"和"assistant"。priority: 一个从 0.0 到 1.0 的数字,表示资源的重要性。1.0 表示最重要。lastModified: 一个 ISO 8601 格式的时间戳,表示资源最后修改的时间。
一个带有注解的资源定义如下:
{
"uri": "file:///project/README.md",
"name": "README.md",
"annotations": {
"audience": ["user"],
"priority": 0.8,
"lastModified": "2025-01-12T15:00:58Z"
}
}
客户端可以利用这些注解来实现更智能的功能,比如根据 priority 优先选择包含哪些上下文,或者根据 lastModified 显示文件的最近修改时间。
注意事项
在使用 Resources 时,还有一些重要的实践和规范需要注意。
关于 URI 方案
URI 是 Resources 的核心标识。协议推荐了几种常见的 URI 方案,但并不局限于此。
https://: 用于表示可通过 Web 直接访问的资源。只有当客户端能够自行获取资源时才应使用。file://: 用于标识行为类似文件系统的资源,但不一定映射到物理文件系统。git://: 用于 Git 版本控制集成。
应用也可以定义自己的 custom URI schemes,只要它们符合 RFC 3986 规范即可。
错误处理
MCP 使用标准的 JSON-RPC 错误码。例如,当请求的资源不存在时,服务器应该返回 -32002 错误码。
{
"jsonrpc": "2.0",
"id": 5,
"error": {
"code": -32002,
"message": "Resource not found",
"data": {
"uri": "file:///nonexistent.txt"
}
}
}
安全考虑
最后,安全是不可忽视的一环。服务器必须对所有传入的资源 URI 进行验证,防止路径遍历等攻击。对于敏感资源,应实现严格的访问控制。同时,在处理二进制数据时,必须确保其被正确编码和解码,以防范安全风险。
开发必备:API 全流程管理神器 Apifox
介绍完上文的内容,我想额外介绍一个对开发者同样重要的效率工具 —— Apifox。作为一个集 API 文档、API 调试、API 设计、API 测试、API Mock、自动化测试等功能于一体的 API 管理工具,Apifox 可以说是开发者提升效率的必备工具之一。
如果你正在开发项目需要进行接口调试,不妨试试 Apifox。注册过程非常简单,你可以直接在这里注册使用。

注册成功后可以先看看官方提供的示例项目,这些案例都是经过精心设计的,能帮助你快速了解 Apifox 的主要功能。
使用 Apifox 的一大优势是它完全兼容 Postman 和 Swagger 数据格式,如果你之前使用过这些工具,数据导入会非常方便。而且它的界面设计非常友好,即使是第一次接触的新手也能很快上手,快去试试吧!
