【引】尽管AI 可以帮助我们顺利地理解MCP规范,但一份完整的MCP规范中译稿还是有意义的,可以进一步帮助我们理解MCP规范的来龙去脉,以及协议中细节的方方面面。如果希望希望极简入门的话, 可以阅读老码农的新作——
模型上下文协议 (Model Context Protocol,MCP) 是一个开放的协议,支持 LLM 应用程序与外部数据源和工具之间的无缝集成。无论是构建基于 AI 的 IDE、增强聊天界面还是创建自定义 AI 工作流,MCP 都提供了一种标准化的方法来将 llm 与它们所需的上下文连接起来。
该规范基于 schema.ts 中的 TypeScript 模式定义了权威协议需求。
有关实现指南及示例,请浏览 modelcontextprotocol.io。
本文件中的关键词 “MUST”、“MUST NOT”、“REQUIRED”、“SHALL”、“SHALL NOT”、“SHOULD”、“SHOULD NOT”、“RECOMMENDED”、“NOT RECOMMENDED”、“MAY” 和 “OPTIONAL” 应按照 BCP 14 [RFC2119][RFC8174] 中的规定解释,如本文件所示,当且仅当它们出现在所有大写字母中时表示如上含义。
MCP 为应用程序提供了一种标准化的方式:
该协议使用 JSON-RPC 2.0 消息来建立以下组件之间的通信:
MCP 从语言服务器协议 (Language Server Protocol) 中获得了一些灵感,该协议标准化了如何在整个开发工具生态系统中添加对编程语言的支持。以类似的方式,MCP 标准化了如何将其他上下文和工具集成到 AI 应用程序的生态系统中。
服务器向客户端提供以下特性:
客户端可向服务器提供以下功能:
模型上下文协议通过任意的数据访问和代码执行路径实现了强大的功能。这种能力带来了重大的安全和信任问题,所有实现者都必须仔细考虑这些问题。
实现者应该为审查和授权活动提供清晰的用户界面
虽然 MCP 本身不能在协议级别上强制执行这些安全原则,但实现者应该:
本文档列出了自上一版本( 2024-11-05 )以来对模型上下文协议 (MCP) 规范所做的变更。
有关更多详细信息,请参见更新的数据模式。
有关自上次协议修订以来所做的所有变更的完整列表,请参见 GitHub。
模型上下文协议 (Model Context Protocol,MCP) 遵循客户端- 主机 - 服务器的架构模式,其中每个主机可以运行多个客户端实例。这种架构使用户能够在应用程序之间集成 AI 功能,同时保持清晰的安全边界和隔离关注点。MCP 建立在 JSON-RPC 之上,它提供了一个有状态的会话协议,主要关注客户端和服务器之间的上下文交换和采样协调。
主机进程充当容器和协调器:
每个客户端由主机创建,并维护一个独立的服务器连接:
主机应用程序创建并管理多个客户机,每个客户机与特定服务器具有 1:1 的关系。
服务器提供专门的环境和功能:
MCP 建立在几个关键设计原则的基础上,这些原则为其架构和实施提供了参考信息:
模型上下文协议使用一个基于能力的协商系统,客户端和服务器在初始化期间显式地声明它们支持的功能特性。能力决定哪些协议特性和原语在会话期间可用。
每个功能解锁特定的协议特性,以便在会话期间使用。例如:
此能力协商确保客户端和服务器在维护协议可扩展性的同时清楚地理解所支持的功能。
修订于 2025 年 3 月 26 日
模型上下文协议由几个协同工作的关键组成部分组成:
所有的实现都必须支持基本协议和生命周期管理组件。其他组件可以根据应用程序的具体需要来实现。
这些协议层建立了清晰的关注点分离,同时实现了客户端和服务器之间的丰富交互。模块化设计允许实现完全支持它们需要的特性。
MCP 客户端和服务器之间的所有消息必须遵循 JSON-RPC 2.0 规范,该协议定义了以下类型的消息。
请求从客户端发送到服务器,反之亦然,以启动一个操作。
{
jsonrpc: "2.0";
id: string | number;
method: string;
params?: {
[key: string]: unknown;
};
}
4.1.1.2 响应
响应是在回复请求时发送的,包含操作的结果或错误信息。
{
jsonrpc: "2.0";
id: string | number;
result?: {
[key: string]: unknown;
}
error?: {
code: number;
message: string;
data?: unknown;
}
}
通知作为单向消息从客户机发送到服务器,反之亦然。接收者不能发送响应。
{
jsonrpc: "2.0";
method: string;
params?: {
[key: string]: unknown;
};
}
通知不能包含 ID。
JSON-RPC 还定义了一种方法来批处理多个请求和通知,将它们发送到一个数组中。MCP 实现可能支持发送端的 JSON-RPC 批处理,但必须支持接收端的 JSON-RPC 批处理。
MCP 提供了一个用于 HTTP 的授权框架。使用基于 http 传输的实现应该符合这个规范,而使用 STDIO 传输的实现不应该遵循这个规范,而应该从环境中检索凭证。
此外,客户端和服务器可以协商自己的自定义身份验证和授权策略。
欲了解更多关于 MCP 身份验证机制发展的讨论和贡献,请加入 GitHub 讨论,帮助塑造协议的未来!
协议的完整规范被定义为 TypeScript 模式。这是所有协议消息和结构的真实来源。
还有一个JSON Schema,它是从 TypeScript 可信真值源自动生成的,用于各种自动化工具。
模型上下文协议 (Model Context Protocol,MCP) 为客户端 - 服务器连接定义了严格的生命周期,以确保适当的能力协商和状态管理。
初始化阶段必须是客户端和服务器之间的第一次交互。在这个阶段,客户端和服务器:
客户端必须通过发送包含以下内容的初始化请求来启动此阶段:
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {
"roots": {
"listChanged": true
},
"sampling": {}
},
"clientInfo": {
"name": "ExampleClient",
"version": "1.0.0"
}
}
}
初始化请求不能成为 JSON-RPC 批处理的一部分,因为在初始化完成之前,其他请求和通知是不可能发出的。这还允许向后兼容不显式支持 JSON-RPC 批处理的以前协议版本。
服务器必须用自己的能力和信息进行响应:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {
"logging": {},
"prompts": {
"listChanged": true
},
"resources": {
"subscribe": true,
"listChanged": true
},
"tools": {
"listChanged": true
}
},
"serverInfo": {
"name": "ExampleServer",
"version": "1.0.0"
},
"instructions": "Optional instructions for the client"
}
}
初始化成功后,客户端必须发送一个初始化通知,表明它已准备好开始正常操作:
{
"jsonrpc": "2.0",
"method": "notifications/initialized"
}
在初始化请求中,客户端必须发送它支持的协议版本。这应该是客户端支持的最新版本。
如果服务器支持请求的协议版本,它必须用相同的版本响应。否则,服务器必须使用其支持的另一个协议版本进行响应。这应该是服务器支持的最新版本。
如果客户端不支持服务器响应中的版本,它应该断开连接。
客户端和服务器功能确定在会话期间哪些可选协议的特性可用。
主要能力包括:
类别 | 能力 | 描述 |
---|---|---|
Client | roots | 提供文件系统根的能力 |
Client | sampling | 支持 LLM 采样请求 |
Client | experimental | 描述对非标准实验特性的支持 |
Server | prompts | 提供提示词模板 |
Server | resources | 提供可读的资源 |
Server | tools | 公开可调用的工具 |
Server | logging | 发出结构化的日志消息 |
Server | experimental | 描述对非标准实验特性的支持 |
能力对象可以像这样描述其子能力:
在操作阶段,客户端和服务器根据协商的能力交换消息。
双方应该:
在关闭阶段,一方 (通常是客户端) 干净地终止协议连接。没有定义特定的关闭消息ーー相反,应该使用底层传输机制来发送连接终止信号:
对于 stdio 传输,客户端应该通过以下方式启动关闭:
1.首先,关闭子进程 (服务器) 的输入流
2. 等待服务器退出,如果服务器没有在合理的时间内退出,则发送 SIGTERM
3. 如果服务器没有在 SIGTERM 之后的合理时间内退出,则发送 SIGKILL
服务器可以通过关闭其到客户端的输出流并退出来启动关闭。
对于 HTTP 传输,通过关闭相关的 HTTP 连接来指示关闭。
实现应该为所有发送的请求建立超时,以防止挂起连接和资源耗尽。当请求在超时期间内没有收到成功或错误响应时,发送方应该为该请求发出取消通知,并停止等待响应。
SDK和其他中间件应该允许根据每个请求配置这些超时。
实现可能在接收到相应请求的进度通知时选择重置超时时钟,这意味着工作实际上正在发生。但是,无论进度通知如何,实现都应该强制执行最大超时,以限制行为不当的客户端或服务器的影响。
应该准备好实现来处理这些错误情况:
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32602,
"message": "Unsupported protocol version",
"data": {
"supported": ["2024-11-05"],
"requested": "1.0.0"
}
}
}
MCP 使用 JSON-RPC 编码消息。 JSON-RPC 消息必须是 utf-8 编码。
该协议目前定义了客户端 - 服务器通信的两种标准传输机制:
客户端应该尽可能支持 stdio。
客户端和服务器也可以以可插拔的方式实现自定义传输。
在STDIO的传输中:
4.3.2 Streamable HTTP
这取代了协议 2024-11-05 版本中的 HTTP + SSE传输。
在 Streamable HTTP传输中,服务器作为独立进程运行,可以处理多个客户端连接。此传输使用 HTTP POST 和 GET 请求。服务器可以选择性地使用SSE来流化多个服务器消息。这为基本的 MCP 服务器和支持流的服务器提供了更多丰富的功能,并支持服务器到客户端的通知和请求。
服务器必须提供一个同时支持 POST 和 GET 方法的 HTTP 端点路径 (以下称为 MCP 端点)。例如,这可能是一个类似于 https://example.com/mcp 的 URL。
实现流式 HTTP 传输时:
如果没有这些保护,攻击者可以使用 DNS 重新绑定来与远程站点的本地 MCP 服务器交互。
从客户端发送的每个 JSON-RPC 消息都必须是对 MCP 端点的新HTTP POST 请求。
为了支持恢复中断的连接,并重新发送可能丢失的消息:
换句话说,服务器应该根据每个流分配这些事件 id,作为该特定流中的游标。
一个MCP “会话” 由客户端和服务器之间逻辑上相关的交互组成,从初始化阶段开始。未来支持希望建立有状态会话的服务器:
客户端和服务器可以维护与 HTTP+ SSE传输 (来自协议版本 2024-11-05) 的向后兼容性,如下所示:
希望支持老客户端的服务器应该:
希望支持旧服务器的客户端应该:
客户短和服务器可以实现额外的自定义传输机制,以满足它们的特定需求。该协议是传输无关的,可以在任何支持双向消息交换的信道上完成实现。
选择支持自定义传输的实现者必须确保它们保留由 MCP 定义的 JSON-RPC 消息格式和生命周期需求。自定义传输应该记录其特定的连接建立和消息交换模式,以帮助实现互操作性。
模型上下文协议在传输级别提供鉴权功能,使 MCP 客户短能够代表资源所有者向受限 MCP 服务器发出请求。本规范定义了基于 HTTP传输的授权流程。
对于 MCP 实现,鉴权是可选的。当支持鉴权时:
这种鉴权机制基于下列既定规范,但实现了其特性的一个选定子集,以确保安全性和互操作性,同时保持简单:
OAuth 指定不同的流或授权类型,这是获得访问令牌的不同方式。每个目标都有不同的用例和场景。
MCP 服务器应该支持 OAuth 授权类型,这种授权类型最适合目标用户。例如:
这里演示了用于用户身份验证的鉴权码授予类型的 OAuth 2.1 流。
注意: 下面的示例假定 MCP 服务器也作为授权服务器运行。但是,可以将授权服务器部署为其自己的特定服务。
人类用户通过 web 浏览器完成 OAuth 流程,获得一个访问令牌,该令牌可以识别用户,并允许客户端代表用户进行操作。
当需要鉴权且客户端尚未证明授权时,服务器必须响应HTTP 401 Unauthorized。
客户端在收到 HTTP 401 Unauthorized 之后启动 OAuth 2.1 IETF DRAFT 鉴权流程。
下图展示了使用 PKCE 公共客户端的基本 OAuth 2.1流程。
对于服务器能力发现而言:
发现流程如下:
MCP 客户端应该在服务器元数据发现期间包含头 MCP-protocol-version: ,以允许 MCP 服务器基于MCP的协议版本进行响应。
例如: MCP-Protocol-Version: 2024-11-05
通过丢弃任何当前的路径元素,鉴权的基 URL 必须从 MCP 服务器 URL 中确定。例如:
如果 MCP 服务器 URL 是 https://api.example.com/v1/MCP ,那么:
这确保鉴权端点始终位于承载 MCP 服务器的域名的根级别,而不管 MCP 服务器 URL 中的其他路径元素如何。
对于没有实现 OAuth 2.0 Authorization Server Metadata 协议的服务器,客户端必须使用相对于鉴权的基 URL (在 2.3.2 节中定义) 的以下默认端点路径:
端点 | 默认路径 | 描述 |
---|---|---|
鉴权端点 | /authorize/ | 用于鉴权请求 |
令牌端点 | /token/ | 用于令牌交换和刷新 |
注册端点 | /register/ | 用于动态客户端注册 |
例如,当 MCP 服务器托管在 https://api.example.com/v1/MCP 时,默认端点为:
https://api.example.com/authorize https://api.example.com/token https://api.example.com/register
客户端必须首先尝试通过元数据文档发现端点,然后再回到默认路径。当使用默认路径时,所有其他协议要求保持不变。
MCP 客户端和服务器应该支持 OAuth 2.0 动态客户端注册协议,以允许 MCP 客户端在没有用户交互的情况下获得 OAuth 客户端ID。这为客户端自动向新服务器注册提供了一种标准化的方法,对于 MCP 至关重要,因为:
任何不支持动态客户端注册的 MCP 服务器都需要提供获取客户端 ID 以及 (如果适用的话) 客户端保密的替代方法。对于其中一台服务器,MCP 客户端必须满足以下条件之一:
完整的鉴权流程如下:
访问令牌的处理必须符合 OAuth 2.1 第 5 部分对资源请求的要求,特别是:
1. MCP 客户端必须使用OAuth 2.1中 5.1.1 节的鉴权请求头字段:
Authorization: Bearer <access-token>
请注意,从客户端到服务器的每个 HTTP 请求中都必须包含鉴权,即使它们是同一逻辑会话的一部分。
2. 访问令牌不能包含在 URI 的查询字符串中 请求示例:
GET /v1/contexts HTTP/1.1
Host: mcp.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
资源服务器必须验证访问令牌,如OAuth 2.1的第 5.2 节所述。如果验证失败,服务器必须根据 5.3 节的错误处理要求进行响应。无效或过期的令牌必须接收一个HTTP 401 响应。
必须执行下列安全性要求:
服务器必须为鉴权错误返回适当的 HTTP 状态码:
状态代码 | 描述 | 用法 |
---|---|---|
401 | Unauthorized | 需要鉴权或令牌无效 |
403 | Forbidden | 无效范围或权限不足 |
400 | Bad Request | 格式错误的授权请求 |
MCP 服务器可以通过第三方鉴权服务器支持委托鉴权。在这个流程中,MCP 服务器既充当 OAuth 客户端(对于第三方身份验证服务器) ,又充当 OAuth 鉴权服务器 (对于 MCP 客户端)。
第三方鉴权流程包括以下步骤:
实现第三方授权的 MCP 服务器必须:
在实施第三方授权时,服务器必须:
我们强烈建议本地客户端将 OAuth 2.1 作为公共客户端实现:
我们强烈建议所有客户端都实现元数据发现。这减少了用户手动提供端点或客户端回退到预定义默认值的需要。
由于客户端事先不知道 MCP 服务器的集合,我们强烈建议实现动态客户端注册。这允许应用程序自动向 MCP 服务器注册,并消除了用户手动获取客户机 id 的需要。
模型上下文协议支持通过通知消息可选地取消正在进行的请求。任何一方都可以发送取消通知,表明以前发出的请求应该终止。
当一方希望取消一个正在进行的请求时,它会发送一个 notifications/cancelled 通知,其中包括:
{
"jsonrpc": "2.0",
"method": "notifications/cancelled",
"params": {
"requestId": "123",
"reason": "User requested cancellation"
}
}
由于网络延迟,取消通知可能在请求处理完成之后到达,并且可能在响应已经发送之后到达。
双方都必须妥善处理这些竞争条件:
无效的取消通知应该被忽略:
这保持了通知的 “发送和忘记” 特性,同时允许异步通信中的竞态条件。
模型上下文协议包含一个可选的 ping 机制,允许任何一方验证对方是否仍然响应,以及连接是否存在。
Ping 功能是通过简单的请求 / 响应模式实现的。客户端或服务器都可以通过发送 ping 请求来初始化一个 ping。
Ping 请求是一个没有参数的标准 JSON-RPC 请求:
{
"jsonrpc": "2.0",
"id": "123",
"method": "ping"
}
接收方必须立即作出一个空响应:
{
"jsonrpc": "2.0",
"id": "123",
"result": {}
}
如果在合理的超时期限内没有收到响应,则发送方可以:
模型上下文协议支持以通知消息对长时间运行的操作执行可选的进度跟踪。任何一方都可以发送进度通知,以提供有关操作状态的更新。
当一方希望接收请求的进度更新时,它会在请求元数据中包含 progressToken。
{
"jsonrpc": "2.0",
"id": 1,
"method": "some_method",
"params": {
"_meta": {
"progressToken": "abc123"
}
}
}
然后,接收方可以发送进度通知,内容包括: * 原始进度令牌 * 迄今为止的当前进度值 * 一个可选的 “total” 值 * 一个可选的 “message” 值
{
"jsonrpc": "2.0",
"method": "notifications/progress",
"params": {
"progressToken": "abc123",
"progress": 50,
"total": 100,
"message": "Reticulating splines..."
}
}
进度通知必须只引用以下令牌:
进度请求的接收方可以:
模型上下文协议为客户端向服务器公开文件系统的 “根目录” 提供了一种标准化的方法。Root 定义了服务器可以在文件系统中操作的边界,允许服务器理解它们可以访问哪些目录和文件。服务器可以从支持的客户端中请求根目录的列表,并在该列表发生更改时接收通知。
MCP 中的根通常通过工作区或项目配置接口公开。
例如,实现可以提供一个工作区 / 项目选择器,允许用户选择服务器应该访问的目录和文件。这可以与来自版本控制系统或项目文件的自动工作区检测相结合。
然而,具体实现可以自由地通过任何符合其需要的接口模式来公开“根”,协议本身并不要求任何特定的用户交互模型。
支持根目录的客户端必须在初始化期间声明根目录的能力:
{
"capabilities": {
"roots": {
"listChanged": true
}
}
}
listChanged 指示当根列表发生更改时,客户端是否发出通知。
为了检索根目录,服务器发送一个roots/list请求。
请求:
{
"jsonrpc": "2.0",
"id": 1,
"method": "roots/list"
}
响应:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"roots": [
{
"uri": "file:///home/user/projects/myproject",
"name": "My Project"
}
]
}
}
当根发生变更时,支持 listChanged 的客户端必须发送一个通知。
{ "jsonrpc": "2.0", "method": "notifications/roots/list_changed" }
根的定义包括:
URI: root 的唯一标识符,必须是当前规范中的文件://URI。 名称:用于显示目的的人类可读名称(可选)。
不同用例的root示例:
{
"uri": "file:///home/user/projects/myproject",
"name": "My Project"
}
[
{
"uri": "file:///home/user/repos/frontend",
"name": "Frontend Repository"
},
{
"uri": "file:///home/user/repos/backend",
"name": "Backend Repository"
}
]
对于常见的失败情况,客户端应该返回标准的 JSON-RPC 错误:
错误示例:
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32601,
"message": "Roots not supported",
"data": {
"reason": "Client does not have roots capability"
}
}
}
1. 客户端必须:
2. 服务器应该:
客户端应该:
服务器应该:
模型上下文协议为服务器通过客户端从语言模型请求 LLM 采样 (“补全” 或 “代替”) 提供了一种标准化的方法。此流程允许客户端维护对模型访问、选择和权限的控制,同时允许服务器利用 AI 功能ーー不需要服务器 API 密钥。服务器可以请求基于文本、音频或图像的交互,还可以在提示词中包含来自 MCP 服务器的上下文。
MCP 中的采样允许服务器实现智能体行为,允许 LLM 调用嵌套在其他 MCP 服务器的功能。
具体实现可以自由地通过任何适合其需要的接口模式公开采样,协议本身并不要求任何特定的用户交互模型。
为了信任、保密和安全性,应该总是有一个人工行为在循环中有能力拒绝采样请求。
应用应该:
支持采样的客户端必须在初始化期间声明采样能力:
{
"capabilities": {
"sampling": {}
}
}
为了请求语言模型的一个生成结果,服务器发送一个sampling/createMessage 请求:
请求:
{
"jsonrpc": "2.0",
"id": 1,
"method": "sampling/createMessage",
"params": {
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "What is the capital of France?"
}
}
],
"modelPreferences": {
"hints": [
{
"name": "claude-3-sonnet"
}
],
"intelligencePriority": 0.8,
"speedPriority": 0.5
},
"systemPrompt": "You are a helpful assistant.",
"maxTokens": 100
}
}
响应:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"role": "assistant",
"content": {
"type": "text",
"text": "The capital of France is Paris."
},
"model": "claude-3-sonnet-20240307",
"stopReason": "endTurn"
}
}
采样信息可以包含:
{
"type": "text",
"text": "The message content"
}
{
"type": "image",
"data": "base64-encoded-image-data",
"mimeType": "image/jpeg"
}
{
"type": "audio",
"data": "base64-encoded-audio-data",
"mimeType": "audio/wav"
}
MCP 中的模型选择需要仔细的抽象,因为服务器和客户端可能使用不同的 AI 提供者提供不同的模型。服务器不能简单地通过名称请求特定的模型,因为客户端可能无法访问该确切的模型,或者可能更喜欢使用不同提供者的等价模型。
为了解决这个问题,MCP 实现了一个偏好设置系统,将抽象的能力优先级与可选的模型引导结合起来。
服务器通过三个规范化的优先级值 (0-1) 来表达它们的需求:
虽然优先级有助于根据特征选择模型,但引导允许服务器建议特定的模型或模型家族:
例如:
{
"hints": [
{ "name": "claude-3-sonnet" }, // Prefer Sonnet-class models
{ "name": "claude" } // Fall back to any Claude model
],
"costPriority": 0.3, // Cost is less important
"speedPriority": 0.8, // Speed is very important
"intelligencePriority": 0.5 // Moderate capability needs
}
客户端处理这些偏好项以从其可用选项中选择适当的模型。例如,如果客户端没有访问 Claude 模型,但有 Gemini,它可能会基于类似的功能将sonnet引导映射到 Gemini-1.5-pro。
对于常见的故障情况,客户端应该返回错误:
错误示例:
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -1,
"message": "User rejected sampling request"
}
}
服务器提供了通过 MCP 向语言模型添加上下文的基本构建块。这些原语支持客户端、服务器和语言模型之间的丰富交互:
每个原语可以归纳为以下的控制层次结构:
原语 | 管制 | 描述 | 例子 |
---|---|---|---|
提示词 | 用户控制 | 由用户选择调用的交互式模板 | 斜杠命令,菜单选项 |
资源 | 应用控制 | 由客户端附加和管理的上下文数据 | 文件内容,git 历史 |
工具 | 模型控制 | 公开给 LLM 以执行操作的函数 | API POST 请求,文件写入 |
以下更详细地探讨这些关键原语:提示词、资源和工具。
模型上下文协议 (Model Context Protocol,MCP) 为服务器向客户机公开提示模板提供了一种标准化的方法。提示允许服务器提供与语言模型交互的结构化消息和指令。客户机可以发现可用的提示,检索它们的内容,并提供参数来定制它们。
提示词被设计为由用户控制,这意味着它们从服务器公开给客户端,用户可以显式地选择它们来使用。
通常,提示词将通过用户界面中由用户发起的命令触发,这允许用户自然地发现和调用可用的提示次。例如,作为斜杠命令。
然而,实现者可以自由地通过任何适合他们需要的接口模式公开提示词ーー协议本身并不要求任何特定的用户交互模型。
支持提示词的服务器必须在初始化期间声明提示词功能:
{
"capabilities": {
"prompts": {
"listChanged": true
}
}
}
listChanged 指示了当可用提示词列表发生更改时,服务器是否发出通知。
为了检索可用的提示词,客户端发送一个 prompts/list请求。此操作支持分页。
请求:
{
"jsonrpc": "2.0",
"id": 1,
"method": "prompts/list",
"params": {
"cursor": "optional-cursor-value"
}
}
响应:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"prompts": [
{
"name": "code_review",
"description": "Asks the LLM to analyze code quality and suggest improvements",
"arguments": [
{
"name": "code",
"description": "The code to review",
"required": true
}
]
}
],
"nextCursor": "next-page-cursor"
}
}
为了检索特定的提示词,客户端发送一个prompts/get请求。参数可以通过完整的API 自动完成。
请求:
{
"jsonrpc": "2.0",
"id": 2,
"method": "prompts/get",
"params": {
"name": "code_review",
"arguments": {
"code": "def hello():\n print('world')"
}
}
}
响应:
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"description": "Code review prompt",
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "Please review this Python code:\ndef hello():\n print('world')"
}
}
]
}
}
当可用提示词列表发生更改时,声明 listChanged 能力的服务器应发送通知:
{
"jsonrpc": "2.0",
"method": "notifications/prompts/list_changed"
}
一个提示词的定义包括:
一个提示词中的消息可以包含:
角色:指代说话者是 “用户” 或 “助手” 内容:以下内容类型之一:
文本内容表示纯文本消息:
{
"type": "text",
"text": "The text content of the message"
}
这是用于自然语言交互的最常见内容类型。
图像内容允许在消息中包含视觉信息:
{
"type": "image",
"data": "base64-encoded-image-data",
"mimeType": "image/png"
}
图像数据必须是 base64 编码,并且包含有效的 MIME 类型。这使得多模态交互在视觉上下文很重要的地方成为可能。
音频内容允许在消息中包含音频信息:
{
"type": "audio",
"data": "base64-encoded-audio-data",
"mimeType": "audio/wav"
}
音频数据必须是 base64 编码,并且包含有效的 MIME 类型。这使得在音频上下文很重要的情况下进行多模态交互成为可能。
嵌入式资源允许在消息中直接引用服务器端资源:
{
"type": "resource",
"resource": {
"uri": "resource://example",
"mimeType": "text/plain",
"text": "Resource content"
}
}
资源可以包含文本或二进制 (blob) 数据,必须包括:
嵌入式资源允许提示词将服务器管理的内容 (如文档、代码示例或其他参考资料) 无缝地直接合并到会话流中。
对于常见的故障情况,服务器应该返回标准的 JSON-RPC 错误:
具体实现必须仔细验证所有提示词的输入和输出,以防止注入攻击或未经授权的资源访问。
模型上下文协议为服务器向客户端公开资源提供了一种标准化的方法。资源允许服务器共享为语言模型提供上下文的数据,例如文件、数据库模式或特定于应用程序的信息。每个资源都由一个 URI 唯一标识。
MCP 中的资源被设计为由应用程序所驱动,由主机应用程序根据自己的需要确定如何合并上下文。
例如,应用程序可以:
然而,具体实现可以通过任何适合其需要的接口模式自由地公开资源ーー协议本身并不强制任何特定的用户交互模型。
支持资源的服务器必须声明资源能力:
{
"capabilities": {
"resources": {
"subscribe": true,
"listChanged": true
}
}
}
该能力支持两个可选特性:
Subscribe 和 listChanged 都是可选的ーー服务器可以不支持它们,也可以支持它们中的一个,或者两者都支持:
{
"capabilities": {
"resources": {} // Neither feature supported
}
}
{
"capabilities": {
"resources": {
"subscribe": true // Only subscriptions supported
}
}
}
{
"capabilities": {
"resources": {
"listChanged": true // Only list change notifications supported
}
}
}
为了发现可用的资源,客户端发送一个resources/list请求。此操作支持分页。
请求:
{
"jsonrpc": "2.0",
"id": 1,
"method": "resources/list",
"params": {
"cursor": "optional-cursor-value"
}
}
响应:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resources": [
{
"uri": "file:///project/src/main.rs",
"name": "main.rs",
"description": "Primary application entry point",
"mimeType": "text/x-rust"
}
],
"nextCursor": "next-page-cursor"
}
}
为了检索资源内容,客户端发送一个resources/read 请求。
请求:
{
"jsonrpc": "2.0",
"id": 2,
"method": "resources/read",
"params": {
"uri": "file:///project/src/main.rs"
}
}
响应:
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"contents": [
{
"uri": "file:///project/src/main.rs",
"mimeType": "text/x-rust",
"text": "fn main() {\n println!(\"Hello world!\");\n}"
}
]
}
}
资源模板允许服务器使用 URI 模板公开参数化的资源。参数可以通过 API 自动补全。
请求:
{
"jsonrpc": "2.0",
"id": 3,
"method": "resources/templates/list"
}
响应:
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"resourceTemplates": [
{
"uriTemplate": "file:///{path}",
"name": "Project Files",
"description": "Access files in the project directory",
"mimeType": "application/octet-stream"
}
]
}
}
当可用资源列表发生更改时,声明 listChanged 功能的服务器应发送通知。
{
"jsonrpc": "2.0",
"method": "notifications/resources/list_changed"
}
该协议支持对资源更改的可选订阅。客户端可以订阅特定的资源,并在资源更改时接收通知。
订阅请求:
{
"jsonrpc": "2.0",
"id": 4,
"method": "resources/subscribe",
"params": {
"uri": "file:///project/src/main.rs"
}
}
更新通知:
{
"jsonrpc": "2.0",
"method": "notifications/resources/updated",
"params": {
"uri": "file:///project/src/main.rs"
}
}
一个资源定义包括:
资源可以包含文本数据或二进制数据:
{
"uri": "file:///example.txt",
"mimeType": "text/plain",
"text": "Resource content"
}
{
"uri": "file:///example.png",
"mimeType": "image/png",
"blob": "base64-encoded-data"
}
该协议定义了几个标准的 URI 模式。这个列表并不详尽,具体实现总是可以自由地使用额外的、自定义的 URI 模式。
用于表示 web 上可用的资源。
只有当客户端能够自己直接从 web 获取和加载资源时,服务器才应该使用这种方案ーー也就是说,它不需要通过 MCP 服务器读取资源。
对于其他用例,服务器应该优先使用另一个 URI 方案,或者定义一个自定义 URI 方案,即使服务器本身将通过 internet 下载资源内容。
用于标识行为类似于文件系统的资源。但是,资源不需要映射到实际的物理文件系统。
MCP 服务器可以使用 XDG MIME 类型标识 file:// 资源,比如 inode/directory,来表示没有标准 MIME 类型的非常规文件 (比如目录)。
Git 版本控制集成。
对于常见的故障情况,服务器应该返回标准的 JSON-RPC 错误:
错误示例:
{
"jsonrpc": "2.0",
"id": 5,
"error": {
"code": -32002,
"message": "Resource not found",
"data": {
"uri": "file:///nonexistent.txt"
}
}
}
模型上下文协议允许服务器公开可由语言模型调用的工具。工具使模型能够与外部系统交互,例如查询数据库、调用 api 或执行计算。每个工具都由名称唯一标识,并包含描述其模式的元数据。
MCP 中的工具被设计为由模型控制,这意味着语言模型可以根据其上下文理解和用户的提示词自动发现和调用工具。
然而,具体实现可以通过任何适合其需要的接口模式自由地公开工具ーー协议本身并不强制要求任何特定的用户交互模型。
为了信任、保密和安全性,在循环中应该始终有一个人工操控有能力拒绝工具调用。
应用应该:
支持工具的服务器必须声明工具能力:
{
"capabilities": {
"tools": {
"listChanged": true
}
}
}
listChanged 指示当可用工具列表发生更改时,服务器是否发出通知。
为了发现可用的工具,客户端发送一个tools/list请求。这个操作支持分页。
请求:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {
"cursor": "optional-cursor-value"
}
}
响应:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": [
{
"name": "get_weather",
"description": "Get current weather information for a location",
"inputSchema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name or zip code"
}
},
"required": ["location"]
}
}
],
"nextCursor": "next-page-cursor"
}
}
要调用工具,客户端发送一个tools/call请求:
请求:
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": {
"location": "New York"
}
}
}
响应:
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [
{
"type": "text",
"text": "Current weather in New York:\nTemperature: 72°F\nConditions: Partly cloudy"
}
],
"isError": false
}
}
当可用工具列表发生更改时,声明 listChanged 功能的服务器应该发送一个通知:
{
"jsonrpc": "2.0",
"method": "notifications/tools/list_changed"
}
一个工具定义包括:
为了信任、保密和安全性,客户端必须认为工具注释是不可信的,除非它们来自受信任的服务器。
工具结果可以包含不同类型的多个内容项:
{
"type": "text",
"text": "Tool result text"
}
{
"type": "image",
"data": "base64-encoded-data",
"mimeType": "image/png"
}
{
"type": "audio",
"data": "base64-encoded-audio-data",
"mimeType": "audio/wav"
}
可以将资源嵌入到 URI 后面,以提供额外的上下文或数据,客户端以后可以订阅或再次获取这些 URI:
{
"type": "resource",
"resource": {
"uri": "resource://example",
"mimeType": "text/plain",
"text": "Resource content"
}
}
工具使用两种错误报告机制。
协议错误是 标准的 JSON-RPC 错误,例如:
协议错误示例:
{
"jsonrpc": "2.0",
"id": 3,
"error": {
"code": -32602,
"message": "Unknown tool: invalid_tool_name"
}
}
工具执行错误在工具结果中使用 isError: true 报告:
工具执行错误示例:
{
"jsonrpc": "2.0",
"id": 4,
"result": {
"content": [
{
"type": "text",
"text": "Failed to fetch weather data: API rate limit exceeded"
}
],
"isError": true
}
}
模型上下文协议为服务器提供了一种标准化的方法,用于为提示词和资源 uri 提供参数的自动补全建议。这使得用户可以在输入参数值时接收上下文建议,从而获得丰富的类 ide 体验。
MCP 中的补全设计用于支持类似于 IDE 代码补全的交互式用户体验。
例如,当用户输入时,应用程序可以在下拉菜单或弹出菜单中显示补全建议,并具有从可用选项中进行筛选和选择的能力。
然而,具体实现可以自由地通过任何适合其需要的接口模式公开补全的能力,协议本身并不要求任何特定的用户交互模型。
支持补全的服务器必须声明补全的能力:
{
"capabilities": {
"completions": {}
}
}
为了获得全建议,客户端通过参考类型发送一个completion/complete 请求,并指定正在完成的内容。
请求:
{
"jsonrpc": "2.0",
"id": 1,
"method": "completion/complete",
"params": {
"ref": {
"type": "ref/prompt",
"name": "code_review"
},
"argument": {
"name": "language",
"value": "py"
}
}
}
响应:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"completion": {
"values": ["python", "pytorch", "pyside"],
"total": 10,
"hasMore": true
}
}
}
该协议支持两种类型的补全:
类别 | 描述 | 例子 |
---|---|---|
ref/prompt | 通过名称的参考提示词 | {"type": "ref/prompt", "name": "code_review"} |
ref/resource | 参考资源 URI | {"type": "ref/resource", "uri": "file:///{path}"} |
服务器返回一个按相关性排序的补全值的数组,其中包括:
——按相关性排序返回建议 ——在适当的地方实现模糊匹配 ——补全请求速率限制 ——验证所有输入
2. 客户端应该:
模型上下文协议为服务器向客户端发送结构化日志消息提供了一种标准化方法。客户端可以通过设置最低日志级别来控制日志记录的详细程度,服务器发送包含严重级别、可选日志名称和任意可序列化 json 数据的通知。
具体实现可以自由地通过任何符合其需要的接口模式公开日志记录,协议本身并不要求任何特定的用户交互模型。
发出日志消息通知的服务器必须声明日志记录能力:
{
"capabilities": {
"logging": {}
}
}
该协议遵循 RFC 5424 规定的标准 syslog 的日志严重级别:
日志级别 | 描述 | 示例 |
---|---|---|
debug | 详细的调试信息 | 函数入口 / 出口点 |
info | 一般信息 | 操作进度更新 |
notice | 正常但重要的事件 | 配置变更 |
warning | 警告条件 | 不推荐的特性使用 |
error | 错误条件 | 操作故障 |
critical | 临界条件 | 系统组件故障 |
alert | 必须立即采取行动 | 检测到数据损坏 |
emergency | 系统无法使用 | 补全系统发生故障 |
要配置最低日志级别,客户端可以发送一个logging/setLevel 请求 。
请求:
{
"jsonrpc": "2.0",
"id": 1,
"method": "logging/setLevel",
"params": {
"level": "info"
}
}
服务器使用notifications/message发送日志消息:
{
"jsonrpc": "2.0",
"method": "notifications/message",
"params": {
"level": "error",
"logger": "database",
"data": {
"error": "Connection failed",
"details": {
"host": "localhost",
"port": 5432
}
}
}
}
对于常见的故障情况,服务器应该返回标准的 JSON-RPC 错误:
模型上下文协议支持可能返回大型结果集的分页列表操作。分页能够允许服务器以更小的块产生结果,而不是一次产生所有结果。
当通过互联网连接到外部服务时,分页尤其重要,而且对于本地集成也很有用,可以避免大型数据集的性能问题。
MCP 中的分页使用不透明的基于游标的方法,而不是编号页。
当服务器发送包含以下内容的响应时,开始分页:
接收到游标后,客户端可以通过发出包括该游标在内的请求来继续分页:
{
"jsonrpc": "2.0",
"method": "resources/list",
"params": {
"cursor": "eyJwYWdlIjogMn0="
}
}
下列 MCP 操作支持分页:
模型上下文协议使用符合 YYYY-MM-DD 格式的基于字符串的版本标识符,以指示向后不兼容更改的最后日期。
协议版本不会在协议更新时增加,只需更改保持向后兼容。这允许在保持互操作性的同时进行增量改进。
修订内容可标示如下:
Current协议版本是 2025-03-26。
版本协商发生在初始化过程中。客户端和服务器可以同时支持多个协议版本,但是它们必须同意在会话中使用一个版本。
如果版本协商失败,该协议提供适当的错误处理,允许客户端在找不到与服务器兼容的版本时正常地终止连接。
参见github。