Skip to main content
这篇 Model Context Protocol(MCP)概览介绍它的范围核心概念,并通过一个示例展示每个核心概念。 由于 MCP SDK 已经抽象掉许多细节,大多数开发者可能会发现数据层协议这一节最有用。它说明 MCP 服务器如何向 AI 应用提供上下文。 具体实现细节请参考对应语言 SDK 的文档。

范围

Model Context Protocol 包含以下项目:
MCP 只关注上下文交换协议本身,它不规定 AI 应用如何使用 LLM,也不规定如何管理已提供的上下文。

MCP 的概念

参与方

MCP 采用客户端-服务器架构。MCP host 是类似 Claude CodeClaude Desktop 的 AI 应用,它会与一个或多个 MCP 服务器建立连接。MCP host 会为每个 MCP 服务器创建一个 MCP client;每个 MCP client 都维护一条到对应 MCP server 的专用连接。 使用 STDIO 传输的本地 MCP 服务器通常只服务一个 MCP client,而使用 Streamable HTTP 传输的远程 MCP 服务器通常会服务多个 MCP client。 MCP 架构中的关键参与方包括:
  • MCP Host:协调和管理一个或多个 MCP client 的 AI 应用。
  • MCP Client:维护到 MCP server 的连接,并从 MCP server 获取上下文供 MCP host 使用的组件。
  • MCP Server:向 MCP client 提供上下文的程序。
例如:Visual Studio Code 可以充当 MCP host。当 Visual Studio Code 与某个 MCP server(例如 Sentry MCP server)建立连接时,Visual Studio Code 运行时会实例化一个 MCP client 对象来维护到 Sentry MCP server 的连接。随后,如果 Visual Studio Code 再连接另一个 MCP server(例如本地文件系统服务器),运行时会再实例化一个额外的 MCP client 对象来维护这条连接。 注意,MCP server 指的是提供上下文数据的程序,与它运行在哪里无关。MCP server 可以在本地运行,也可以远程运行。例如,当 Claude Desktop 启动文件系统服务器时,由于它使用 STDIO 传输,该服务器会在同一台机器上本地运行,这通常被称为“本地”MCP server。官方 Sentry MCP server 运行在 Sentry 平台上,并使用 Streamable HTTP 传输,这通常被称为“远程”MCP server。

分层

MCP 由两层组成:
  • 数据层:定义基于 JSON-RPC 的客户端-服务器通信协议,包括生命周期管理,以及 tools、resources、prompts、notifications 等核心 primitive。
  • 传输层:定义客户端与服务器之间交换数据所需的通信机制和通道,包括特定传输方式的连接建立、消息分帧和授权。
从概念上看,数据层是内层,传输层是外层。

数据层

数据层实现了基于 JSON-RPC 2.0 的交换协议,定义消息结构和语义。这一层包括:
  • 生命周期管理:处理客户端与服务器之间的连接初始化、能力协商和连接终止。
  • 服务器能力:让服务器可以提供核心功能,包括供 AI 执行动作的 tools、作为上下文数据的 resources,以及面向客户端交互模板的 prompts。
  • 客户端能力:让服务器可以请求客户端从 host LLM 进行采样、向用户引出输入,并向客户端发送日志消息。
  • 工具能力:支持实时更新通知、长时间运行操作的进度跟踪等附加能力。

传输层

传输层管理客户端与服务器之间的通信通道和认证。它负责 MCP 参与方之间的连接建立、消息分帧和安全通信。 MCP 支持两种传输机制:
  • Stdio transport:使用标准输入/输出流,在同一台机器上的本地进程之间进行直接通信,没有网络开销,性能最佳。
  • Streamable HTTP transport:使用 HTTP POST 发送客户端到服务器的消息,并可选择使用 Server-Sent Events 提供流式能力。该传输方式支持远程服务器通信,也支持标准 HTTP 认证方式,包括 bearer token、API key 和自定义 header。MCP 推荐使用 OAuth 获取认证 token。
传输层对协议层抽象了通信细节,使所有传输机制都可以使用相同的 JSON-RPC 2.0 消息格式。

数据层协议

MCP 的核心之一是定义 MCP client 和 MCP server 之间的 schema 与语义。对开发者来说,数据层,尤其是 primitives 集合,通常是 MCP 中最值得关注的部分。它定义了开发者如何将 MCP server 中的上下文共享给 MCP client。 MCP 使用 JSON-RPC 2.0 作为底层 RPC 协议。客户端和服务器会相互发送请求并返回响应;如果不需要响应,可以使用通知。

生命周期管理

MCP 是一个需要生命周期管理的。生命周期管理的目的,是协商客户端和服务器共同支持的。详细信息可见规范示例展示了初始化序列。

Primitives

MCP primitives 是 MCP 中最重要的概念。它们定义客户端和服务器可以相互提供什么。这些 primitive 指定了可共享给 AI 应用的上下文信息类型,以及可执行的操作范围。 MCP 定义了三类可由_服务器_暴露的核心 primitive:
  • Tools:AI 应用可以调用来执行动作的可执行函数,例如文件操作、API 调用、数据库查询。
  • Resources:向 AI 应用提供上下文信息的数据源,例如文件内容、数据库记录、API 响应。
  • Prompts:帮助组织与语言模型交互的可复用模板,例如系统提示、few-shot 示例。
每种 primitive 都有关联方法,用于发现(*/list)、获取(*/get),某些情况下还用于执行(tools/call)。MCP client 会使用 */list 方法发现可用的 primitive。例如,客户端可以先列出所有可用工具(tools/list),再执行它们。这样的设计允许列表动态变化。 举一个具体例子:一个提供数据库上下文的 MCP server,可以暴露用于查询数据库的 tools、包含数据库 schema 的 resource,以及包含工具交互 few-shot 示例的 prompt。 关于服务器 primitive 的更多信息,请参阅服务器概念 MCP 也定义了可由_客户端_暴露的 primitive。这些 primitive 让 MCP server 作者可以构建更丰富的交互。
  • Sampling:允许服务器从客户端的 AI 应用请求语言模型补全。当服务器作者希望使用语言模型,但又想保持模型无关、不在 MCP server 中集成语言模型 SDK 时,这会很有用。服务器可以使用 sampling/createMessage 方法向客户端的 AI 应用请求语言模型补全。
  • Elicitation:允许服务器向用户请求额外信息。当服务器作者需要从用户获取更多信息,或请求用户确认某个动作时,这会很有用。服务器可以使用 elicitation/create 方法向用户请求额外信息。
  • Logging:允许服务器向客户端发送日志消息,用于调试和监控。
关于客户端 primitive 的更多信息,请参阅客户端概念 除了服务器和客户端 primitive 外,协议还提供跨领域的工具型 primitive,用于增强请求执行方式:
  • Tasks(实验性):持久化执行包装器,让 MCP 请求可以延迟获取结果并跟踪状态,例如高成本计算、工作流自动化、批处理、多步骤操作。

通知

协议支持实时通知,以便服务器和客户端之间进行动态更新。例如,当服务器的可用工具发生变化(比如新增功能可用,或现有工具被修改)时,服务器可以发送工具更新通知,告知已连接的客户端这些变化。通知以 JSON-RPC 2.0 notification message 发送,不期望响应,并允许 MCP server 向已连接的客户端提供实时更新。

示例

数据层

本节逐步演示一次 MCP client-server 交互,重点关注数据层协议。我们会使用 JSON-RPC 2.0 消息展示生命周期序列、工具操作和通知。
1

初始化(生命周期管理)

MCP 从生命周期管理开始,通过能力协商握手建立连接。如生命周期管理一节所述,客户端会发送 initialize 请求来建立连接并协商受支持的功能。
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2025-06-18",
    "capabilities": {
      "elicitation": {}
    },
    "clientInfo": {
      "name": "example-client",
      "version": "1.0.0"
    }
  }
}

理解初始化交换

初始化流程是 MCP 生命周期管理的关键部分,承担几个重要职责:
  1. 协议版本协商protocolVersion 字段(例如 "2025-06-18")确保客户端和服务器使用兼容的协议版本。这可以避免不同版本尝试交互时产生通信错误。如果未能协商出双方兼容的版本,应终止连接。
  2. 能力发现capabilities 对象允许双方声明自己支持哪些功能,包括可处理哪些 primitives(tools、resources、prompts),以及是否支持通知等功能。这样可以避免执行不支持的操作,从而提升通信效率。
  3. 身份交换clientInfoserverInfo 对象提供身份与版本信息,用于调试和兼容性判断。
在这个示例中,能力协商展示了 MCP primitive 如何声明:客户端能力
  • "elicitation": {} - 客户端声明它可以处理用户交互请求(可以接收 elicitation/create 方法调用)。
服务器能力
  • "tools": {"listChanged": true} - 服务器支持 tools primitive,并且在工具列表变化时可以发送 tools/list_changed 通知。
  • "resources": {} - 服务器也支持 resources primitive(可以处理 resources/listresources/read 方法)。
初始化成功后,客户端会发送一条通知表示自己已准备就绪:
Notification
{
  "jsonrpc": "2.0",
  "method": "notifications/initialized"
}

它在 AI 应用中如何工作

初始化期间,AI 应用的 MCP client manager 会与已配置的服务器建立连接,并保存它们的能力供后续使用。应用会利用这些信息判断哪些服务器可以提供特定类型的功能(tools、resources、prompts),以及它们是否支持实时更新。
Pseudo-code for AI application initialization
# Pseudo Code
async with stdio_client(server_config) as (read, write):
    async with ClientSession(read, write) as session:
        init_response = await session.initialize()
        if init_response.capabilities.tools:
            app.register_mcp_server(session, supports_tools=True)
        app.set_server_ready(session)
2

工具发现(Primitives)

连接建立后,客户端可以发送 tools/list 请求来发现可用工具。这个请求是 MCP 工具发现机制的基础,它允许客户端在尝试使用工具前了解服务器上有哪些可用工具。
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/list"
}

理解工具发现请求

tools/list 请求很简单,不包含参数。

理解工具发现响应

响应包含一个 tools 数组,其中提供每个可用工具的完整元数据。基于数组的结构允许服务器同时暴露多个工具,同时保持不同功能之间的清晰边界。响应中的每个工具对象都包含几个关键字段:
  • name:工具在服务器命名空间内的唯一标识符。它是执行工具时的主键,应遵循清晰的命名模式(例如 calculator_arithmetic,而不是只有 calculate)。
  • title:工具的人类可读显示名称,客户端可以展示给用户。
  • description:详细说明工具做什么,以及何时使用。
  • inputSchema:定义预期输入参数的 JSON Schema,用于类型校验,并清晰记录必填和可选参数。

它在 AI 应用中如何工作

AI 应用会从所有已连接的 MCP server 获取可用工具,并将它们组合成语言模型可访问的统一工具注册表。这样 LLM 就能理解自己可以执行哪些动作,并在对话过程中自动生成合适的工具调用。
Pseudo-code for AI application tool discovery
# Pseudo-code using MCP Python SDK patterns
available_tools = []
for session in app.mcp_server_sessions():
    tools_response = await session.list_tools()
    available_tools.extend(tools_response.tools)
conversation.register_available_tools(available_tools)
3

工具执行(Primitives)

现在客户端可以使用 tools/call 方法执行工具。这展示了 MCP primitive 在实践中的用法:发现可用工具后,客户端可以用合适的参数调用它们。

理解工具执行请求

tools/call 请求遵循结构化格式,以确保类型安全,并让客户端和服务器之间的通信清晰明确。注意,这里使用的是发现响应中的正确工具名(weather_current),而不是简化名称:
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "weather_current",
    "arguments": {
      "location": "San Francisco",
      "units": "imperial"
    }
  }
}

工具执行的关键元素

请求结构包含几个重要组成部分:
  1. name:必须与发现响应中的工具名(weather_current)完全匹配。这样服务器才能正确识别要执行哪个工具。
  2. arguments:包含工具 inputSchema 定义的输入参数。在本例中:
    • location:“San Francisco”(必填参数)
    • units:“imperial”(可选参数;未指定时默认是 "metric"
  3. JSON-RPC 结构:使用标准 JSON-RPC 2.0 格式,并通过唯一 id 关联请求和响应。

理解工具执行响应

响应展示了 MCP 灵活的内容系统:
  1. content 数组:工具响应会返回内容对象数组,支持文本、图片、资源等多格式响应。
  2. 内容类型:每个内容对象都有 type 字段。在本例中,"type": "text" 表示纯文本内容;MCP 也支持适用于不同场景的其他内容类型。
  3. 结构化输出:响应提供可操作的信息,AI 应用可以将其作为语言模型交互的上下文。
这种执行模式允许 AI 应用动态调用服务器功能,并接收可整合进语言模型对话的结构化响应。

它在 AI 应用中如何工作

当语言模型在对话过程中决定使用某个工具时,AI 应用会拦截该工具调用,将其路由到相应 MCP server,执行工具,并把结果作为对话流程的一部分返回给 LLM。这样 LLM 就可以访问实时数据,并在外部世界执行动作。
# Pseudo-code for AI application tool execution
async def handle_tool_call(conversation, tool_name, arguments):
    session = app.find_mcp_session_for_tool(tool_name)
    result = await session.call_tool(tool_name, arguments)
    conversation.add_tool_result(result.content)
4

实时更新(通知)

MCP 支持实时通知,使服务器可以在没有显式请求的情况下告知客户端发生了变化。这里展示的通知系统,是保持 MCP 连接同步和响应迅速的关键能力。

理解工具列表变更通知

当服务器的可用工具发生变化时,例如新增功能可用、现有工具被修改,或工具暂时不可用,服务器可以主动通知已连接的客户端:
Request
{
  "jsonrpc": "2.0",
  "method": "notifications/tools/list_changed"
}

MCP 通知的关键特性

  1. 不需要响应:注意通知中没有 id 字段。这遵循 JSON-RPC 2.0 的通知语义,即不期望也不会发送响应。
  2. 基于能力:只有在初始化期间(如步骤 1 所示)在 tools 能力中声明了 "listChanged": true 的服务器,才会发送这种通知。
  3. 事件驱动:服务器会基于内部状态变化决定何时发送通知,从而让 MCP 连接具备动态性和响应性。

客户端如何响应通知

收到这种通知后,客户端通常会请求更新后的工具列表。这样会形成一个刷新循环,让客户端始终掌握最新的可用工具信息:
Request
{
  "jsonrpc": "2.0",
  "id": 4,
  "method": "tools/list"
}

为什么通知重要

通知系统之所以重要,有几个原因:
  1. 动态环境:工具可能会根据服务器状态、外部依赖或用户权限出现或消失。
  2. 效率:客户端不需要轮询变化;更新发生时会收到通知。
  3. 一致性:确保客户端始终拥有关于可用服务器能力的准确信息。
  4. 实时协作:让 AI 应用可以响应上下文变化并动态适配。
这种通知模式不仅适用于 tools,也可扩展到其他 MCP primitive,从而实现客户端和服务器之间全面的实时同步。

它在 AI 应用中如何工作

当 AI 应用收到工具变化通知时,会立即刷新工具注册表,并更新 LLM 的可用能力。这确保正在进行的对话始终可以访问最新工具集合,同时 LLM 也可以在新功能可用时动态适配。
# Pseudo-code for AI application notification handling
async def handle_tools_changed_notification(session):
    tools_response = await session.list_tools()
    app.update_available_tools(session, tools_response.tools)
    if app.conversation.is_active():
        app.conversation.notify_llm_of_new_capabilities()