引言
模型上下文协议 (Model Context Protocol, MCP) 旨在为大型语言模型 (LLM) 应用与外部数据源和工具之间建立标准化的桥梁。本文将深入解析 MCP 的核心概念、生命周期、关键功能以及实用工具,结合最新的 2025-03-26 协议修订版本和具体的 JSON-RPC 请求/响应示例,为开发者提供一份全面的实践指南。
MCP 核心组件
MCP 由多个协同工作的关键组件构成:
- 基础协议: 定义核心的 JSON-RPC 消息类型。
- 生命周期管理: 控制连接初始化、能力协商和会话管理。
- 服务器功能: 服务器提供的特性,如资源 (Resources)、提示 (Prompts) 和工具 (Tools)。
- 客户端功能: 客户端提供的特性,如采样 (Sampling) 和根目录 (Roots)。
- 实用工具: 跨领域的功能,如日志 (Logging)、自动完成 (Completion)、进度跟踪 (Progress) 和取消 (Cancellation)。
所有实现 必须 (MUST) 支持基础协议和生命周期管理。其他组件可根据应用需求选择性实现。
基础协议:JSON-RPC 消息
MCP 完全基于 JSON-RPC 2.0 规范。
请求 (Requests)
用于启动操作。
响应 (Responses)
请求的回复,包含结果或错误。
响应中 result 和 error 必须 (MUST) 设置其一,且 不能 (MUST NOT) 同时设置。
通知 (Notifications)
单向消息,无需响应。
通知 不能 (MUST NOT) 包含 id。
批处理 (Batching)
MCP 实现 可以 (MAY) 发送批处理请求/通知,但 必须 (MUST) 支持接收批处理。
生命周期管理
MCP 连接遵循严格的生命周期:初始化 -> 操作 -> 关闭。
初始化阶段
这是客户端和服务器之间的第一个交互,用于协商协议版本和交换能力。
初始化请求 (来自客户端)
注意: 初始化请求 不能 (MUST NOT) 包含在批处理中。
初始化响应 (来自服务器)
版本协商: 客户端发送其支持的最新版本。如果服务器支持,则返回相同版本;否则,返回服务器支持的最新版本。如果客户端不支持服务器返回的版本,应该 (SHOULD) 断开连接。
能力协商: 双方通过 capabilities 对象声明支持的特性及其子功能(如 listChanged, subscribe)。后续操作只能使用协商成功的能力。
初始化完成通知 (来自客户端)
在收到成功的 initialize 响应后,客户端 必须 (MUST) 发送此通知,表明已准备好进入操作阶段。
在 initialize 响应之前,客户端不应发送除 ping 外的请求。在收到 initialized 通知之前,服务器不应发送除 ping 和 logging 外的请求。
操作阶段
双方根据协商的能力和协议版本进行正常的通信。
关闭阶段
通常由客户端发起,通过底层传输机制(如关闭 stdio 流或 HTTP 连接)来终止连接。没有特定的 MCP 关闭消息。
服务器功能详解
服务器可以暴露以下核心功能:
1. 资源 (Resources)
允许服务器共享上下文数据(文件、数据库模式等),每个资源由唯一的 URI 标识。
能力: resources (可选 subscribe, listChanged)
列出资源 (resources/list) (支持分页)
读取资源 (resources/read)
订阅资源变更 (resources/subscribe) (需要 subscribe 能力)
资源更新通知 (notifications/resources/updated) (由服务器发送给订阅者)
客户端收到此通知后,通常会重新 resources/read 以获取最新内容。
资源列表变更通知 (notifications/resources/list_changed) (需要 listChanged 能力)
客户端收到此通知后,通常会重新 resources/list。
资源模板: 服务器可以通过 resources/templates/list 暴露带参数的 URI 模板 (RFC6570)。
常见 URI Schemes: https://, file://, git:// (实现可自定义)。
2. 工具 (Tools)
允许语言模型调用服务器提供的外部功能(API、计算等)。
能力: tools (可选 listChanged)
列出工具 (tools/list) (支持分页)
注意: 客户端 必须 (MUST) 将工具注解视为不可信,除非来自可信服务器。
调用工具 (tools/call)
工具列表变更通知 (notifications/tools/list_changed) (需要 listChanged 能力)
安全: 客户端 应该 (SHOULD) 在敏感操作前提示用户确认,并展示工具输入以防数据泄露。
3. 提示 (Prompts)
服务器提供结构化的消息模板,供用户显式选择以与 LLM 交互。
能力: prompts (可选 listChanged)
列出提示 (prompts/list) (支持分页)
获取提示 (prompts/get)
提示列表变更通知 (notifications/prompts/list_changed) (需要 listChanged 能力)
客户端功能详解
客户端可以暴露以下核心功能:
1. 根目录 (Roots)
允许客户端向服务器暴露文件系统访问的边界。
能力: roots (可选 listChanged)
列出根目录 (roots/list) (由服务器请求)
根目录列表变更通知 (notifications/roots/list_changed) (由客户端发送,需要 listChanged 能力)
2. 采样 (Sampling)
允许服务器请求客户端通过 LLM 生成内容(文本、图像、音频)。客户端控制模型访问和选择。
能力: sampling
创建消息 (sampling/createMessage) (由服务器请求)
安全: 客户端 应该 (SHOULD) 实现用户批准流程,允许用户在发送前审查和编辑提示。
实用工具
MCP 提供了一系列可选的辅助功能:
Ping
用于检测连接是否存活。
进度 (Progress)
用于报告长时间运行的操作进度。
请求时携带 progressToken: 发送方(如客户端)在请求的 _meta 中包含一个唯一的 progressToken。
进度通知 (notifications/progress): 接收方(如服务器)发送进度更新。
日志 (Logging)
允许服务器向客户端发送结构化日志。
能力: logging
设置日志级别 (logging/setLevel): 客户端可以设置服务器应发送的最低日志级别 (debug, info, notice, warning, error, critical, alert, emergency)。
日志消息通知 (notifications/message): 服务器发送日志。
取消 (Cancellation)
允许一方请求取消先前发送的、仍在进行中的请求。
取消通知 (notifications/cancelled): 发送方发出。
接收方 应该 (SHOULD) 停止处理被取消的请求,并且 不应 (SHOULD NOT) 为其发送响应。发送方 应该 (SHOULD) 忽略之后可能收到的对已取消请求的响应。
自动完成 (Completion)
服务器为提示参数或资源 URI 提供自动完成建议。
能力: completions
请求自动完成 (completion/complete)
分页 (Pagination)
对于可能返回大量结果的列表操作(resources/list, tools/list, prompts/list, resources/templates/list),MCP 使用基于光标的分页。
服务器响应: 在结果中包含 nextCursor(如果不为空,表示有更多页)。
客户端请求下一页: 在请求的 params 中包含收到的 cursor。
客户端 必须 (MUST) 将光标视为不透明字符串。
错误处理
MCP 使用标准的 JSON-RPC 错误代码。
- -32600 Invalid Request: 无效的 JSON 或不符合规范。
- -32601 Method not found: 方法不存在或不可用。
- -32602 Invalid params: 无效的方法参数。
- -32603 Internal error: 服务器内部错误。
- -32000 to -32099 Server error: 特定于实现的服务器错误 (例如,
-32002用于资源未找到)。
安全与信任
MCP 实现者 必须 (MUST) 仔细考虑安全和信任问题:
- 用户同意与控制: 所有数据访问和操作都需要用户明确同意。
- 数据隐私: 未经同意不得共享用户数据。
- 工具安全: 工具调用代表代码执行,需谨慎处理,并获得用户同意。
- 采样控制: 用户应能控制采样请求和审查结果。
- 验证: 客户端和服务器都必须验证输入和输出。
- 权限: 实施适当的访问控制。
结语
模型上下文协议 (MCP) 通过其标准化的消息、生命周期管理和丰富的功能集,为构建强大、安全且可互操作的 AI 应用提供了坚实的基础。理解其核心概念和协议细节,并结合具体的请求/响应示例,将有助于开发者有效地利用 MCP 连接 LLM 与外部世界。
参考资料: