翻译自官方文档:https://modelcontextprotocol.io/docs/learn/architecture
本模型上下文协议 (MCP) 概述讨论了其范围和核心概念,并提供了一个示例来演示每个核心概念。由于 MCP SDK 抽象掉了许多细节,大多数开发者可能会发现数据层协议部分最有用。它讨论了 MCP 服务器如何向 AI 应用程序提供上下文。有关具体的实现细节,请参考您所用编程语言的 SDK的文档。
范围
模型上下文协议包括以下方面:
- MCP 规范:概述客户端和服务器实现要求的 MCP 规范。
- MCP SDK:用于实现 MCP 的不同编程语言的 SDK。
- MCP 开发工具:用于开发 MCP 服务器和客户端的工具,包括 MCP Inspector。
- MCP 参考服务器实现:MCP 服务器的参考实现。
MCP 仅关注上下文交换的协议——它并不规定 AI 应用程序如何使用 LLM 或管理所提供的上下文。
MCP 的核心概念
参与者
MCP 遵循客户端-服务器架构,其中 MCP 主机(如 Claude Code或 Claude Desktop等 AI 应用程序)建立与一个或多个 MCP 服务器的连接。MCP 主机通过为每个 MCP 服务器创建一个 MCP 客户端来实现这一点。每个 MCP 客户端与其对应的 MCP 服务器保持专用连接。使用 STDIO 传输的本地 MCP 服务器通常服务于单个 MCP 客户端,而使用可流式 HTTP 传输的远程 MCP 服务器通常服务于许多 MCP 客户端。
MCP 架构中的关键参与者是:
- MCP 主机:协调和管理一个或多个 MCP 客户端的 AI 应用程序。
- MCP 客户端:一个组件,维护与 MCP 服务器的连接,并从 MCP 服务器获取上下文供 MCP 主机使用。
- MCP 服务器:一个向 MCP 客户端提供上下文的程序。
例如:Visual Studio Code 充当 MCP 主机。当 Visual Studio Code 建立与某个 MCP 服务器(例如 Sentry MCP 服务器)的连接时,Visual Studio Code 运行时会实例化一个 MCP 客户端对象,该对象维护与 Sentry MCP 服务器的连接。当 Visual Studio Code 随后连接到另一个 MCP 服务器(例如 本地文件系统服务器)时,Visual Studio Code 运行时会实例化一个额外的 MCP 客户端对象来维护此连接。
1 | theme={null} |
请注意,MCP 服务器指的是提供上下文数据的程序,无论其运行在何处。MCP 服务器可以在本地或远程执行。例如,当 Claude Desktop 启动文件系统服务器时,由于它使用 STDIO 传输,该服务器在同一台机器上本地运行。这通常被称为“本地”MCP 服务器。官方的 Sentry MCP 服务器运行在 Sentry 平台上,并使用可流式 HTTP 传输。这通常被称为“远程”MCP 服务器。
分层
MCP 由两层组成:
- 数据层:定义基于 JSON-RPC 的客户端-服务器通信协议,包括生命周期管理,以及核心原语,如工具、资源、提示和通知。
- 传输层:定义实现客户端和服务器之间数据交换的通信机制和通道,包括特定于传输的连接建立、消息帧和授权。
从概念上讲,数据层是内层,而传输层是外层。
数据层
数据层实现了基于 JSON-RPC 2.0的交换协议,定义了消息结构和语义。此层包括:
- 生命周期管理:处理客户端和服务器之间的连接初始化、能力协商和连接终止。
- 服务器功能:使服务器能够提供核心功能,包括用于 AI 操作的工具、用于上下文数据的资源,以及用于与客户端交互的提示模板。
- 客户端功能:使服务器能够要求客户端对主机 LLM 进行采样、向用户获取输入,并将日志消息发送到客户端。
- 实用功能:支持额外的能力,如实时更新的通知和长时间运行操作的进度跟踪。
传输层
传输层管理客户端和服务器之间的通信通道和身份验证。它处理 MCP 参与者之间的连接建立、消息帧和安全的通信。
MCP 支持两种传输机制:
- Stdio 传输:使用标准输入/输出流在同一台机器上的本地进程之间进行直接进程通信,提供最佳性能且无网络开销。
- 可流式 HTTP 传输:使用 HTTP POST 进行客户端到服务器的消息传递,并可选择使用服务器发送事件 (SSE) 实现流式功能。此传输支持远程服务器通信,并支持标准的 HTTP 身份验证方法,包括承载令牌、API 密钥和自定义标头。MCP 建议使用 OAuth 来获取身份验证令牌。
传输层从协议层抽象出通信细节,使相同的 JSON-RPC 2.0 消息格式能够在所有传输机制中使用。
数据层协议
MCP 的一个核心部分是定义 MCP 客户端和 MCP 服务器之间的模式和语义。开发者可能会发现数据层——特别是原语的集合——是 MCP 中最有趣的部分。它是 MCP 中定义开发者如何从 MCP 服务器向 MCP 客户端共享上下文的部分。
MCP 使用 JSON-RPC 2.0作为其底层 RPC 协议。客户端和服务器彼此发送请求并相应地响应。当不需要响应时,可以使用通知。
生命周期管理
MCP 是一个有状态协议,需要进行生命周期管理。生命周期管理的目的是协商客户端和服务器都支持的能力。详细信息可以在规范中找到,并且示例展示了初始化序列。
原语
MCP 原语是 MCP 中最重要的概念。它们定义了客户端和服务器可以相互提供什么。这些原语指定了可以与 AI 应用程序共享的上下文信息的类型,以及可以执行的操作范围。
MCP 定义了三个核心原语,可以由_服务器_暴露:
- 工具:AI 应用程序可以调用以执行操作(例如,文件操作、API 调用、数据库查询)的可执行函数。
- 资源:向 AI 应用程序提供上下文信息的数据源(例如,文件内容、数据库记录、API 响应)。
- 提示:帮助构建与语言模型交互的可重用模板(例如,系统提示、少样本示例)。
每种原语类型都有用于发现 (*/list)、检索 (*/get) 以及在某些情况下执行 (tools/call) 的关联方法。MCP 客户端将使用 */list方法来发现可用的原语。例如,客户端可以首先列出所有可用工具 (tools/list),然后执行它们。这种设计允许列表是动态的。
作为一个具体示例,考虑一个提供数据库上下文的 MCP 服务器。它可以暴露用于查询数据库的工具、包含数据库模式的资源,以及一个包含与工具交互的少样本示例的提示。
有关服务器原语的更多详细信息,请参见服务器概念。
MCP 还定义了可以由客户端暴露的原语。这些原语允许 MCP 服务器作者构建更丰富的交互。
- 采样:允许服务器从客户端的 AI 应用程序请求语言模型补全。当服务器作者希望访问语言模型,但又想保持模型独立性并且不在其 MCP 服务器中包含语言模型 SDK 时,这很有用。他们可以使用
sampling/complete方法从客户端的 AI 应用程序请求语言模型补全。 - 征询:允许服务器向用户请求更多信息。当服务器作者希望从用户那里获取更多信息,或请求确认某个操作时,这很有用。他们可以使用
elicitation/request方法向用户请求额外信息。 - 日志记录:使服务器能够向客户端发送日志消息,用于调试和监控目的。
有关客户端原语的更多详细信息,请参见客户端概念。
除了服务器和客户端原语之外,该协议还提供了横切实用程序原语,以增强请求的执行方式:
- 任务(实验性):持久的执行包装器,支持对 MCP 请求进行延迟结果检索和状态跟踪(例如,昂贵的计算、工作流自动化、批处理、多步骤操作)。
通知
该协议支持实时通知,以实现服务器和客户端之间的动态更新。例如,当服务器的可用工具发生变化时(例如,当新功能可用或现有工具被修改时),服务器可以发送工具更新通知,以通知连接的客户端这些更改。通知作为 JSON-RPC 2.0 通知消息发送(不期望响应),并使 MCP 服务器能够向连接的客户端提供实时更新。
示例
数据层
本节逐步演示 MCP 客户端-服务器交互,重点关注数据层协议。我们将使用 JSON-RPC 2.0 消息展示生命周期序列、工具操作和通知。
初始化(生命周期管理)
初始化请求
1 | { |
初始化响应
1 | { |
理解初始化交换
初始化过程是 MCP 生命周期管理的关键部分,具有几个关键目的:
- 协议版本协商:
protocolVersion字段(例如,“2025-06-18”)确保客户端和服务器都使用兼容的协议版本。这可以防止不同版本尝试交互时可能发生的通信错误。如果未协商出相互兼容的版本,则应终止连接。 - 能力发现:
capabilities对象允许每一方声明它们支持哪些功能,包括它们可以处理的原语(工具、资源、提示)以及是否支持通知等功能。这通过避免不支持的操 - 作来实现高效通信。
- 身份交换:
clientInfo和serverInfo对象提供标识和版本信息,用于调试和兼容性目的。
在此示例中,能力协商展示了如何声明 MCP 原语:
客户端能力:
"elicitation": {}- 客户端声明它可以处理用户交互请求(可以接收elicitation/create方法调用)
服务器能力:
"tools": {"listChanged": true}- 服务器支持工具原语,并且可以在其工具列表更改时发送tools/list_changed通知。"resources": {}- 服务器还支持资源原语(可以处理resources/list和resources/read方法)。
成功初始化后,客户端发送通知以指示其已准备就绪:
1 | { |
这在 AI 应用程序中如何工作
在初始化期间,AI 应用程序的 MCP 客户端管理器建立与已配置服务器的连接,并存储它们的能力以供以后使用。应用程序使用此信息来确定哪些服务器可以提供特定类型的功能(工具、资源、提示),以及它们是否支持实时更新。
1 | # Pseudo Code |
工具发现(原语)
现在连接已建立,客户端可以通过发送 tools/list请求来发现可用工具。此请求是 MCP 工具发现机制的基础——它允许客户端在使用工具之前了解服务器上有哪些工具可用。
Tool list request
1 | { |
Tool list response
1 | { |
理解工具发现请求
tools/list请求很简单,不包含任何参数。
理解工具发现响应
响应包含一个 tools数组,该数组提供有关每个可用工具的全面元数据。这种基于数组的结构允许服务器同时暴露多个工具,同时保持不同功能之间的清晰界限。
响应中的每个工具对象都包含几个关键字段:
**name**:服务器命名空间内该工具的唯一标识符。这作为工具执行的主键,应遵循清晰的命名模式(例如,使用calculator_arithmetic而不仅仅是calculate)。**title**:工具的人类可读显示名称,客户端可以将其显示给用户。**description**:关于该工具的功能以及何时使用它的详细说明。**inputSchema**:定义预期输入参数的 JSON 模式,支持类型验证并提供有关必需和可选参数的清晰文档。
这在 AI 应用程序中如何工作
AI 应用程序从所有连接的 MCP 服务器获取可用工具,并将它们组合成一个统一的工具注册表,供语言模型访问。这允许 LLM 了解它可以执行哪些操作,并在对话期间自动生成适当的工具调用。
1 | # Pseudo-code using MCP Python SDK patterns |
工具执行(原语)
客户端现在可以使用 tools/call方法执行一个工具。这演示了 MCP 原语在实践中如何使用:在发现可用工具后,客户端可以使用适当的参数调用它们。
理解工具执行请求
tools/call请求遵循结构化格式,确保类型安全性和客户端与服务器之间的清晰通信。请注意,我们使用的是发现响应中的正确工具名称 (weather_current),而不是简化名称:
Tool call request
1 | { |
Tool call response
1 | { |
工具执行的关键要素
请求结构包括几个重要组成部分:
**name**:必须与发现响应中的工具名称 (weather_current) 完全匹配。这确保服务器能够正确识别要执行哪个工具。**arguments**:包含由工具的inputSchema定义的输入参数。在此示例中:location: “San Francisco”(必需参数)units: “imperial”(可选参数,如果未指定,则默认为 “metric”)
- JSON-RPC 结构:使用具有唯一
id的标准 JSON-RPC 2.0 格式,用于请求-响应关联。
理解工具执行响应
响应演示了 MCP 灵活的内容系统:
**content**数组:工具响应返回一个内容对象数组,允许丰富、多格式的响应(文本、图像、资源等)。- 内容类型:每个内容对象都有一个
type字段。在此示例中,"type": "text"表示纯文本内容,但 MCP 支持多种内容类型以满足不同的使用场景。 - 结构化输出:响应提供了可操作的信息,AI 应用程序可以将其用作语言模型交互的上下文。
这种执行模式允许 AI 应用程序动态调用服务器功能,并接收可以作为对话一部分与语言模型集成的结构化响应。
这在 AI 应用程序中如何工作
当语言模型在对话中决定使用某个工具时,AI 应用程序会拦截该工具调用,将其路由到适当的 MCP 服务器,执行它,并将结果作为对话流的一部分返回给 LLM。这使得 LLM 能够访问实时数据并在外部世界中执行操作。
1 | # Pseudo-code for AI application tool execution |
实时更新(通知)
MCP 支持实时通知,使服务器能够在未被明确请求的情况下通知客户端更改。这演示了通知系统,这是保持 MCP 连接同步和响应的关键功能。
理解工具列表更改通知
当服务器的可用工具发生更改时(例如,当新功能可用、现有工具被修改或工具暂时不可用时),服务器可以主动通知连接的客户端:
1 | { |
MCP 通知的关键特性
- 无需响应:请注意通知中没有
id字段。这遵循 JSON-RPC 2.0 通知语义,即不期望或发送响应。 - 基于能力:此通知仅由在初始化期间在其工具能力中声明了
"listChanged": true的服务器发送(如步骤 1 所示)。 - 事件驱动:服务器根据内部状态更改决定何时发送通知,使 MCP 连接具有动态性和响应性。
客户端对通知的响应
收到此通知后,客户端通常会通过请求更新后的工具列表来做出响应。这创建了一个刷新周期,使客户端对可用工具的理解保持最新:
1 | { |
为什么通知很重要
此通知系统至关重要,原因有几个:
- 动态环境:工具可能基于服务器状态、外部依赖项或用户权限而出现或消失。
- 效率:客户端无需轮询更改;当更新发生时,它们会收到通知。
- 一致性:确保客户端始终拥有关于可用服务器功能的准确信息。
- 实时协作:支持能够适应不断变化上下文的响应式 AI 应用程序。
此通知模式不仅限于工具,还扩展到其他 MCP 原语,实现了客户端和服务器之间全面的实时同步。
这在 AI 应用程序中如何工作
当 AI 应用程序收到有关工具更改的通知时,它会立即刷新其工具注册表,并更新 LLM 的可用能力。这确保了正在进行的对话始终可以访问最新的工具集,并且 LLM 可以随着新功能的出现而动态适应。
1 | # Pseudo-code for AI application notification handling |