侧边栏壁纸
博主头像
AI中文站

开拓MCP洪荒时代

  • 累计撰写 17 篇文章
  • 累计创建 3 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

MCP核心概念-资源

将服务器中的数据和内容公开到LLMs

资源是模型上下文协议 (MCP) 中的核心原语,它允许服务器公开可由客户端读取并用作LLM交互的上下文的数据和内容。

概述

资源表示MCP服务器希望向客户端提供的任何类型的数据。这可以包括:

  • 文件内容

  • 数据库记录

  • API响应

  • 实时系统数据

  • 屏幕截图和图像

  • 日志文件

  • ...

每个资源由唯一的URI标识,并且可以包含文本或二进制数据。

资源uri

使用遵循以下格式的uri标识资源:

复制

[protocol]://[host]/[path]

例如:

  • file:///home/user/documents/report.pdf

  • postgres://database/customers/schema

  • screen://localhost/display1

协议和路径结构由MCP服务器实现定义。服务器可以定义自己的自定义URI方案。

资源类型

资源可以包含两种类型的内容:

文本资源

文本资源包含UTF-8编码的文本数据。这些适用于:

  • 源代码

  • 配置文件

  • 日志文件

  • JSON/XML数据

  • 纯文本

二进制资源

二进制资源包含以base64编码的原始二进制数据。这些适用于:

  • 图像

  • PDFs

  • 音频文件

  • 视频文件

  • 其他非文本格式

资源发现

客户端可以通过两种主要方法发现可用资源:


直接资源

服务器通过resources/list端点。每个资源包括:

{
  uri: string;           // Unique identifier for the resource
  name: string;          // Human-readable name
  description?: string;  // Optional description
  mimeType?: string;     // Optional MIME type
  size?: number;         // Optional size in bytes
}

资源模板

对于动态资源,服务器可以公开URI模板客户端可以使用它来构造有效的资源uri:

复制


{
  uriTemplate: string;   // URI template following RFC 6570
  name: string;          // Human-readable name for this type
  description?: string;  // Optional description
  mimeType?: string;     // Optional MIME type for all matching resources
}


阅读资源

要读取资源,客户端会创建一个resources/read具有资源URI的请求。

服务器以资源内容列表进行响应:

复制

{
  contents: [
    {
      uri: string;        // The URI of the resource
      mimeType?: string;  // Optional MIME type

      // One of:
      text?: string;      // For text resources
      blob?: string;      // For binary resources (base64 encoded)
    }
  ]
}

服务器可能会返回多个资源以响应一个resources/read请求。例如,这可以用于在读取目录时返回目录内的文件列表。

资源更新

MCP通过两种机制支持资源的实时更新:

列表更改

当可用资源列表发生更改时,服务器可以通过notifications/resources/list_changed通知。

内容更改

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

  1. 客户端发送resources/subscribe使用资源URI

  2. 服务器发送notifications/resources/updated当资源发生变化时

  3. 客户端可以使用获取最新内容resources/read

  4. 客户端可以取消订阅resources/unsubscribe


示例实现

下面是在MCP服务器中实现资源支持的简单示例:

app = Server("example-server")

@app.list_resources()
async def list_resources() -> list[types.Resource]:
    return [
        types.Resource(
            uri="file:///logs/app.log",
            name="Application Logs",
            mimeType="text/plain"
        )
    ]

@app.read_resource()
async def read_resource(uri: AnyUrl) -> str:
    if str(uri) == "file:///logs/app.log":
        log_contents = await read_log_file()
        return log_contents

    raise ValueError("Resource not found")

# Start server
async with stdio_server() as streams:
    await app.run(
        streams[0],
        streams[1],
        app.create_initialization_options()
    )

最佳实践

实施资源支持时:

  1. 使用清晰的描述性资源名称和uri

  2. 包括有用的描述以指导LLM理解

  3. 已知时设置适当的MIME类型

  4. 为动态内容实施资源模板

  5. 将订阅用于频繁更改的资源

  6. 使用清晰的错误消息优雅地处理错误

  7. 考虑大型资源列表的分页

  8. 适当时缓存资源内容

  9. 在处理之前验证uri

  10. 记录您的自定义URI方案

安全注意事项

公开资源时:

  • 验证所有资源uri

  • 实施适当的访问控制

  • 清理文件路径以防止目录遍历

  • 谨慎处理二进制数据

  • 考虑资源读取的速率限制

  • 审计资源访问

  • 加密传输中的敏感数据

  • 验证MIME类型

  • 为长时间运行的读取实现超时

  • 适当地处理资源清理

0

评论区