资源(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通知客户端可用资源列表的变化。

内容变化

客户端可以订阅特定资源的更新:

  1. 客户端发送resources/subscribe请求并附带资源URI。
  2. 服务器在资源更新时发送notifications/resources/updated通知。
  3. 客户端可以通过resources/read获取最新内容。
  4. 客户端可以通过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标识资源,客户端可以发现、读取和订阅资源的变化。服务器作者应根据不同的客户端需求实现资源支持,并考虑使用模型控制的工具来自动暴露数据。

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐