在开发 MCP 服务器的过程中,我们需要好好理解几个相关的概念:资源、工具、提示词等。
Resources 资源
这里我们需要对 Resources
资源进行一些说明,资源是 MCP 协议中的一种概念,它表示一个可以被读取和操作的对象,我们可以将服务器中的数据和内容作为资源暴露给 LLM,然后 LLM 就可以通过工具来操作这些资源。比如我们可以将一个笔记、一个文件、一个数据库表等作为资源。
资源代表 MCP 服务器希望向客户端提供的任何类型的数据,可以包括如下类型:
- 文件内容
- 数据库记录
- API 响应
- 实时系统数据
- 屏幕截图和图像
- 日志文件
- 还有更多
每个资源都由唯一的 URI
标识,并且可以包含文本或二进制数据。
资源 URI
资源使用遵循以下格式的 URI 进行标识:
[protocol]://[host]/[path]
例如:
file:///home/user/documents/report.pdf
postgres://database/customers/schema
screen://localhost/display1
其中 protocol
协议和 path
路径结构由 MCP 服务器实现定义,当然服务器可以定义自己的自定义 URI 方案。
资源发现
客户端可以通过两种主要方法发现可用资源:
直接资源
服务器通过 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 类型 }
读取资源
要读取资源,客户端用资源 URI 发出 resources/read
请求。服务器响应如下所示的资源内容列表:
{ contents: [ { uri: string; // 资源的 URI mimeType?: string; // 可选的 MIME 类型 // 其中之一: text?: string; // 对于文本资源 blob?: string; // 对于二进制资源 (base64 编码) } ] }
服务器可能会返回多个资源来响应一个 resources/read
请求,比如在读取目录时返回目录内的文件列表。
资源更新
MCP 通过两种机制支持资源的实时更新:
列表变更
当可用资源列表发生变化时,服务器可以通过 notification/resources/list_changed
通知客户端。
内容变更
客户端可以订阅指定资源的更新:
- 客户端使用资源 URI 发送
resources/subscribe
请求 - 当资源发生变化时服务器发送
notification/resources/update
通知 - 客户端可以通过
resources/read
来获取最新内容 - 客户端可以取消订阅资源/取消订阅
工具 Tools
工具使 LLM 能够通过你的服务器执行操作,Tools 使服务器能够向客户端暴露可执行功能,通过工具,LLM 可以与外部系统交互、执行计算并在现实世界中执行操作。工具从服务器暴露给客户端,目的是 AI 模型能够自动调用它们(授予批准)。
MCP 中的工具允许服务器暴露可执行函数,这些函数可以被客户端调用,并被 LLM 用来执行操作,实现工具主要包含以下几个方面:
- 发现:客户端可以通过
tools/list
端点列出可用的工具调用 - 调用:使用
tools/call
端点调用工具,服务器在其中执行请求操作并返回结果 - 灵活性:工具的范围可以从简单的计算到复杂的 API 交互
与资源一样,工具由唯一名称标识,并且可以包含描述来标识其用途,但是与资源不同,工具代表可以修改状态或与外部系统交互的动态操作。
每个工具都定义有以下结构:
{ name: string; // 工具的唯一标识符 description?: string; // 人类可读的描述 inputSchema: { // 工具参数的 JSON Schema type: "object"; properties: { ... } // 工具特定参数 } }
提示词 Prompts
Prompts
提示词是 MCP 协议中用于定义可重复使用的提示词模板和工作流程的机制,客户可以轻松地向用户和 LLM 展示这些模板和工作流程。提示词被设计为由用户控制,这意味着它们从服务器暴露给客户端,以便用户能够显式选择使用它们。
MCP 中的提示词是预定义的模板,可以:
- 接受动态参数
- 从资源中包含上下文
- 链多个交互
- 指导特定工作流程
- 作为 UI 元素(如斜杠命令)
每个 Prompt 定义包含以下结构:
{ name: string; // 提示词的唯一标识符 description?: string; // 人类可读的描述 arguments?: [ // 可选的参数列表 { name: string; // 参数的标识符 description?: string; // 参数的描述 required?: boolean; // 是否必须 } ] }
客户端可以通过 prompts/list
端点来发现所有可用的提示词,比如发起如下所示的请求:
// Request { method: "prompts/list" } // Response { prompts: [ { name: "analyze-code", description: "Analyze code for potential improvements", arguments: [ { name: "language", description: "Programming language", required: true } ] } ] }
然后可以通过 prompts/get
端点来获取指定提示词的详细信息:
// Request { "method": "prompts/get", "params": { "name": "analyze-code", "arguments": { "language": "python" } } } // Response { "description": "Analyze Python code for potential improvements", "messages": [ { "role": "user", "content": { "type": "text", "text": "Please analyze the following Python code for potential improvements:\\n\\n\`\`\`python\\ndef calculate\_sum(numbers):\\n total = 0\\n for num in numbers:\\n total = total + num\\n return total\\n\\nresult = calculate\_sum(\[1, 2, 3, 4, 5\])\\nprint(result)\\n\`\`\`" } } ] }