Resources
资源也是 MCP Server 向客户端应用提供信息的一种形式。
例如:
-
File contents(文件内容)
比如本地的
.txt
、.md
、.js
、.json
文件 -
Database records(数据库记录)
比如 SQL 查询结果或某个表格的内容
-
Screenshots and images(截图和图像)
图像类资源
URI
URI 英语全称为 Uniform Resource Identifier,中文是“统一资源标识符”,用于互联网上某个资源的唯一标识。
URI 的格式为:
[protocol]://[host]/[path]
例如:
file:///home/user/documents/report.pdf
:文件资源,这个例子里面没有 hostpostgres://database/customers/schema
:是一个数据库资源screen://localhost/display1
:屏幕资源
在 MCP 协议中,不强制 URI 规则,允许 Server 自定义。
notebook://cell/123
log://app/service/error
chat://conversation/abc123
回头在 MCP Server 中,所有的资源都会有一个 URI.
资源类型
MCP 中的资源分为两类:Text resources 和 Binary resources
文本资源
文本资源是用 UTF-8 编码的纯文本数据,适合用来展示、编辑、分析。
- Source code(源代码):如
.js
、.ts
、.py
、.cpp
等文件的内容,可以作为上下文供 LLM 阅读和理解。 - Configuration files(配置文件): 如
.env
、config.yaml
、tsconfig.json
等。 - Log files(日志文件):包括运行日志、错误日志,供分析或总结。
- JSON/XML data:结构化的文本格式,广泛用于数据交换。
- Plain text(纯文本):普通的
.txt
文件或文档片段。
二进制资源
二进制资源是原始的二进制数据,必须通过 base64 编码传输。
-
Images(图像):如 PNG、JPG、SVG 等,可用于截图、照片识别等任务。
-
PDFs:常用于展示格式化文档或技术手册。
-
Audio files(音频):如 MP3、WAV,用于语音识别、分析等。
-
Video files(视频):如 MP4、WEBM,可用于视频摘要或分析。
-
Other non-text formats(其它非文本格式):如
.zip
压缩包、.docx
文档、.exe
文件等。
发现资源
MCP 提供了两种发现资源的方式:
- 直接资源
- 资源模板
直接资源
服务器直接暴露一组固定资源,通过 JSON-RPC 方法 resources/list
提供给客户端。
工具:tools/list
每个资源包含字段如下:
{uri: string; // 资源的唯一 URI(例如 file:///xxx)name: string; // 人类可读的名称description?: string;// 可选描述,解释用途或内容mimeType?: string; // MIME 类型,如 text/plain, image/pngsize?: number; // 文件大小(单位:字节)
}
例如:
{uri: "file:///logs/build.log",name: "构建日志",description: "包含最近一次构建的所有输出信息",mimeType: "text/plain",size: 18423
}
资源模板
后面再说。
读取资源
客户端通过发送 JSON-RPC 请求:
方法名为 resources/read
,在 params 中写上资源的 URI
{"method": "resources/read","params": {"uri": "file:///logs/error.log"}
}
服务器返回一个 JSON 对象,包含一个 contents
数组,每个数组元素表示一个资源内容对象,结构如下:
{contents: [{uri: string; // 必填,资源的唯一 URImimeType?: string; // 可选,MIME 类型,如 text/plain、image/png// 以下两者二选一text?: string; // 文本资源内容(UTF-8 编码)blob?: string; // 二进制资源内容(Base64 编码)}]
}
MCP 支持 一次 resources/read
返回多个资源内容。
比如:读取一个目录:file:///project/src/
,返回值可能是里面多个文件的内容(如多个 .ts
文件)
课堂练习
为 MCP 服务器注册资源上下文。
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { readResourse } from "./utils.js";const server = new McpServer({name: "resources-mcp-server",version: "0.1.0",
});server.registerResource("香蕉手机", // 资源的名称"bananaphone://info", // 资源URI{title: "香蕉手机信息",description: "香蕉手机的产品以及特性的介绍文字",mimeType: "text/plain",},async (uri) => {console.error("uri>>>", uri);const content = await readResourse("src/assets", "bananaphone.txt", false);return {contents: [{uri: uri.href,name: "香蕉手机信息",text: content,},],};}
);// 注册图像资源(二进制)
server.registerResource("书籍图片", // 资源的名称"pics://books", // 资源URI{title: "书籍图片",description: "一张有很多书籍的图片",mimeType: "image/jpeg",},async (uri) => {console.error("uri>>>", uri);const content = await readResourse("src/assets", "books.jpeg", true);return {contents: [{uri: uri.href,name: "书籍图片",blob: content,},],};}
);server.connect(new StdioServerTransport());
import fs from "fs";
import path from "path";/**** @param {*} filepath 文件的路径* @param {*} filename 文件的名称* @param {*} isBinary 是否是二进制数据*/
export async function readResourse(filepath, filename, isBinary) {try {const filePath = path.join(process.cwd(), filepath, filename);let content = null; // 存储最终读取到的资源if (isBinary) {// 说明是二进制数据const buffer = fs.readFileSync(filePath);// 需要将二进制数据转换为base64编码content = buffer.toString("base64");} else {// 非二进制数据content = fs.readFileSync(filePath, "utf8");}return content;} catch (err) {return `读取资源失败☹️:${err.message}`;}
}
调试工具:
npx @modelcontextprotocol/inspector
在线base64图片预览:https://jaredwinick.github.io/base64-image-viewer/
data:image/png;base64,<base64编码>