架构概述
本文档对模型上下文协议(MCP)进行概述,涵盖其应用范围、核心概念,并通过示例展示每个核心概念。
由于MCP软件开发工具包(SDK)抽象了许多细节,大多数开发者可能会发现数据层协议部分最为实用。该部分阐述了MCP服务器如何向人工智能应用程序提供上下文信息。
如需了解具体实现细节,请参阅适用于您所用编程语言的特定语言SDK文档。
应用范围
模型上下文协议包含以下项目:
- MCP规范:该规范明确了MCP的实施要求,包括客户端和服务器的相关要求。
- MCP SDK:适用于不同编程语言、用于实现MCP的软件开发工具包。
- MCP开发工具:用于开发MCP服务器和客户端的工具,其中包括MCP检查器。
- MCP参考服务器实现:MCP服务器的参考实现。
MCP仅专注于上下文交换协议,它并不规定人工智能应用程序如何使用大型语言模型(LLM),也不管理所提供的上下文。
MCP的核心概念
参与方
MCP采用客户端 - 服务器架构,其中MCP宿主(如Claude Code或Claude Desktop这类人工智能应用程序)会与一个或多个MCP服务器建立连接。MCP宿主通过为每个MCP服务器创建一个MCP客户端来实现这一连接。每个MCP客户端与其对应的MCP服务器保持专用的点对点连接。
MCP架构中的关键参与方如下:
- MCP宿主:负责协调和管理一个或多个MCP客户端的人工智能应用程序。
- 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客户端对象来维护此连接,从而确保MCP客户端与MCP服务器保持一对一的关系。
(例如,Sentry)"] Server2["MCP服务器2
(例如,文件系统)"] Server3["MCP服务器3
(例如,数据库)"] Client1 ---|"一对一
连接"| Server1 Client2 ---|"一对一
连接"| Server2 Client3 ---|"一对一
连接"| Server3 style Client1 fill:#e1f5fe style Client2 fill:#e1f5fe style Client3 fill:#e1f5fe style Server1 fill:#f3e5f5 style Server2 fill:#f3e5f5 style Server3 fill:#f3e5f5
需要注意的是,MCP服务器指的是提供上下文数据的程序,无论其运行位置如何。MCP服务器可以在本地或远程运行。例如,当Claude Desktop启动文件系统服务器时,由于该服务器使用标准输入输出(STDIO)传输方式,因此它在本地机器上运行,这通常被称为"本地"MCP服务器。官方的Sentry MCP服务器在Sentry平台上运行,并使用可流式传输的超文本传输协议(HTTP)传输方式。这通常被称为"远程"MCP服务器。
层级
MCP包含两个层级:
- 数据层:定义了基于JSON - RPC的客户端 - 服务器通信协议,包括生命周期管理以及核心原语(如工具、资源、提示和通知)。
- 传输层:定义了实现客户端和服务器之间数据交换的通信机制和通道,包括特定于传输方式的连接建立、消息帧格式化和授权机制。
从概念上讲,数据层是内部层级,而传输层是外部层级。
数据层
数据层实现了一个基于JSON-RPC2.0的交换协议,该协议定义了消息结构和语义。
此层级包括:
- 生命周期管理:处理客户端和服务器之间的连接初始化、功能协商以及连接终止。
- 服务器功能:使服务器能够提供核心功能,包括供人工智能执行操作的工具、为上下文数据提供支持的资源,以及用于与客户端进行交互的提示模板。
- 客户端功能:使服务器能够要求客户端从宿主大型语言模型中采样数据、从用户那里获取额外信息,并向客户端记录消息。
- 实用功能:支持额外的功能,如实时更新通知和长时间运行操作的进度跟踪。
传输层
传输层管理客户端和服务器之间的通信通道和身份验证。它处理连接的建立、消息的帧格式化以及MCP参与方之间的安全通信。
MCP支持两种传输机制:
- 标准输入输出传输:使用标准输入输出流实现本地机器上本地进程之间的直接进程通信,无需网络开销,可提供最佳性能。
- 可流式传输的超文本传输协议:使用HTTP POST进行客户端到服务器的消息传输,并可选择使用服务器发送事件(SSE)实现流式传输功能。此传输方式支持远程服务器通信,并支持标准的HTTP身份验证方法,包括持有者令牌、API密钥和自定义请求头。MCP建议使用OAuth获取身份验证令牌。
传输层将通信细节从协议层抽象出来,使得所有传输机制都能使用相同的JSON - RPC 2.0消息格式。
数据层协议
MCP的一个核心部分是定义MCP客户端和MCP服务器之间的模式和语义。开发者可能会发现数据层(尤其是原语集合)是MCP中最有趣的部分。该部分定义了开发者如何从MCP服务器向MCP客户端共享上下文信息。
MCP使用JSON - RPC 2.0作为其底层的远程过程调用(RPC)协议。客户端和服务器相互发送请求并做出相应响应。当不需要响应时,可以使用通知机制。
生命周期管理
MCP是一个(使用可流式传输的超文本传输协议传输方式时,MCP的部分功能可以实现无状态)有状态协议,需要进行生命周期管理。生命周期管理的目的是协商客户端和服务器双方支持(例如,工具、资源或提示等客户端或服务器支持的功能和操作)。详细信息请参阅规范,示例展示了初始化序列。
原语
MCP原语是MCP中最重要的概念。它们定义了客户端和服务器可以相互提供的内容。这些原语规定了可以与人工智能应用程序共享的上下文信息类型以及可以执行的操作范围。
MCP定义了服务器可以公开的三种核心原语:
- 工具:人工智能应用程序可以调用以执行操作(例如,文件操作、API调用、数据库查询)的可执行函数。
- 资源:为人工智能应用程序提供上下文信息的数据源(例如,文件内容、数据库记录、API响应)。
- 提示:有助于构建与语言模型交互的可重用模板(例如,系统提示、少样本示例)。
每种原语类型都有与之关联的用于发现(*/list
)、检索(*/get
)以及在某些情况下执行(tools/call
)的方法。
MCP客户端将使用*/list
方法来发现可用的原语。例如,客户端可以先列出所有可用的工具(tools/list
),然后执行这些工具。这种设计允许列表是动态的。
举个具体例子,假设有一个MCP服务器提供有关数据库的上下文信息。它可以公开用于查询数据库的工具、包含数据库架构的资源以及包含用于与工具交互的少样本示例的提示。
有关服务器原语的更多详细信息,请参阅服务器概念。
MCP还定义了客户端可以公开的原语。这些原语允许MCP服务器作者构建更丰富的交互。
- 采样 :允许服务器向客户端的AI应用程序请求语言模型补全。当服务器作者希望访问语言模型,但又想保持模型独立性,且不在其MCP服务器中包含语言模型SDK时,这非常有用。他们可以使用
sampling/complete
方法向客户端的AI应用程序请求语言模型补全。 - 信息获取 :允许服务器向用户请求额外信息。当服务器作者希望从用户那里获取更多信息或请求确认某个操作时,这非常有用。他们可以使用
elicitation/request
方法向用户请求额外信息。 - 日志记录:使服务器能够向客户端发送日志消息,用于调试和监控目的。
有关客户端原语的更多详细信息,请参阅客户端概念。
通知
该协议支持实时通知,以实现服务器和客户端之间的动态更新。例如,当服务器的可用工具发生变化(例如,新功能可用或现有工具被修改)时,服务器可以发送工具更新通知,以告知连接的客户端这些变化。通知作为JSON - RPC 2.0通知消息(无需响应)发送,使MCP服务器能够向连接的客户端提供实时更新。
示例
数据层
本部分逐步介绍MCP客户端 - 服务器交互过程,重点关注数据层协议。我们将使用JSON - RPC 2.0消息演示生命周期序列、工具操作和通知机制。
1. 初始化(生命周期管理)
MCP从通过能力协商握手的生命周期管理开始。如生命周期管理部分所述,客户端发送initialize
请求以建立连接并协商支持的功能。
json
// request
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-06-18",
"capabilities": {
"elicitation": {}
},
"clientInfo": {
"name": "example-client",
"version": "1.0.0"
}
}
}
json
// response
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2025-06-18",
"capabilities": {
"tools": {
"listChanged": true
},
"resources": {}
},
"serverInfo": {
"name": "example-server",
"version": "1.0.0"
}
}
}
理解初始化交互
初始化过程是MCP生命周期管理的关键部分,具有以下几个重要目的:
- 协议版本协商 :
protocolVersion
字段(例如,"2025 - 06 - 18")确保客户端和服务器使用兼容的协议版本。这可以避免因不同版本尝试交互而可能导致的通信错误。如果无法协商出相互兼容的版本,则应终止连接。 - 能力发现 :
capabilities
对象允许各方声明其支持的功能,包括它们可以处理的原语(工具、资源、提示)以及是否支持通知等功能。这可以通过避免不支持的操作来实现高效通信。 - 身份交换 :
clientInfo
和serverInfo
对象提供用于调试和兼容性目的的标识和版本信息。
在此示例中,能力协商展示了如何声明MCP原语:
客户端能力:
"tools": {}
- 客户端声明它可以处理工具原语(可以调用tools/list
和tools/call
方法)
服务器能力:
"tools": {"listChanged": true}
- 服务器支持工具原语,并且当工具列表发生变化时,可以发送tools/list_changed
通知"resources": {}
- 服务器还支持资源原语(可以处理resources/list
和resources/read
方法) 初始化成功后,客户端发送一个通知,表示其已准备就绪:
json
{ "jsonrpc": "2.0", "method": "notifications/initialized" }
这在人工智能应用中是如何工作的
在初始化过程中,人工智能应用程序的MCP客户端管理器会与配置好的服务器建立连接,并存储它们的能力信息以供后续使用。应用程序利用这些信息来确定哪些服务器可以提供特定类型的功能(工具、资源、提示)以及它们是否支持实时更新。
python
#人工智能应用程序初始化的伪代码
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. 工具发现(原语)
现在连接已建立,客户端可以通过发送tools/list
请求来发现可用工具。这是MCP工具发现机制的基础,它允许客户端在使用工具之前了解服务器上可用的工具
json
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list"
}
json
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"tools": [
{
"name": "com.example.calculator/arithmetic",
"title": "计算器",
"description": "执行数学计算,包括基本算术、三角函数和代数运算",
"inputSchema": {
"type": "object",
"properties": {
"expression": {
"type": "string",
"description": "要计算的表达式(例如,'2 + 3 * 4','sin(30)','sqrt(16)')"
}
},
"required": ["expression"]
}
},
{
"name": "com.example.weather/current",
"title": "天气信息",
"description": "获取全球任何地点的当前天气信息",
"inputSchema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "城市名称、地址或坐标(纬度,经度)"
},
"units": {
"type": "string",
"enum": ["metric", "imperial", "kelvin"],
"description": "响应中使用的温度单位",
"default": "metric"
}
},
"required": ["location"]
}
}
]
}
}
理解工具发现请求
tools/list
请求很简单,不包含任何参数。
理解工具发现响应
响应包含一个tools
数组,该数组提供了有关每个可用工具的全面元数据。这种基于数组的结构允许服务器同时公开多个工具,同时保持不同功能之间的清晰边界。
响应中的每个工具对象都包含几个关键字段:
name
:工具在服务器命名空间内的唯一标识符。这作为工具执行的主键,最好采用类似统一资源标识符(URI)的形式(例如,com.example.calculator/arithmetic
,而不是简单的calculate
),以便更好地进行命名空间管理。title
:工具的人类可读显示名称,客户端可以向用户展示该名称。description
:对工具功能的详细说明以及使用场景。inputSchema
:一个JSON模式,用于定义预期的输入参数,支持类型验证,并提供有关必填和可选参数的清晰文档。
这在人工智能应用程序中的工作原理
人工智能应用程序从所有连接的MCP服务器获取可用工具,并将它们组合成一个统一的工具注册表,语言模型可以访问该注册表。这使得语言模型能够了解它可以执行的操作,并在对话过程中自动生成适当的工具调用。
python
# 人工智能应用程序工具发现的伪代码 使用MCP Python SDK模式的伪代码
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.工具执行(原语)
客户端现在可以使用tools/call
方法执行工具。这展示了MCP原语在实际中的应用:在发现可用工具后,客户端可以使用适当的参数调用这些工具。
理解工具执行请求
tools/call
请求遵循一种结构化格式,以确保类型安全并实现客户端和服务器之间的清晰通信。请注意,我们使用的是从发现响应中获取的正确工具名称(com.example.weather/current
),而不是简化名称:
json
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "com.example.weather/current",
"arguments": {
"location": "旧金山",
"units": "imperial"
}
}
}
json
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"content": [
{
"type": "text",
"text": "旧金山当前天气:68华氏度,局部多云,伴有来自西方的微风,风速为8英里/小时。湿度:65%"
}
]
}
}
工具执行的关键要素
请求结构包含几个重要组成部分:
-
name
:必须与发现响应中的工具名称(com.example.weather/current
)完全匹配。这确保服务器能够正确识别要执行的工具。 -
arguments
:包含由工具的inputSchema
定义的输入参数。在此示例中:location
:"旧金山"(必填参数)units
:"imperial"(可选参数,如果未指定,则默认为"metric")
-
JSON - RPC结构 :使用标准的JSON - RPC 2.0格式,并为请求 - 响应关联提供唯一的
id
。
理解工具执行响应
响应展示了MCP灵活的内容系统:
-
content
数组:工具响应返回一个内容对象数组,支持丰富、多格式的响应(文本、图像、资源等)。 -
内容类型 :每个内容对象都有一个
type
字段。在此示例中,"type": "text"
表示纯文本内容,但MCP支持各种内容类型以满足不同的使用场景。 -
结构化输出:响应提供可操作的信息,人工智能应用程序可以将其用作与语言模型交互的上下文。
这种执行模式允许人工智能应用程序动态调用服务器功能,并接收可集成到与语言模型对话中的结构化响应。
这在人工智能应用程序中的工作原理
当语言模型在对话过程中决定使用工具时,人工智能应用程序会拦截工具调用,将其路由到适当的MCP服务器,执行该工具,并将结果作为对话流程的一部分返回给语言模型。这使得语言模型能够访问实时数据并在外部世界执行操作。
python
# 人工智能应用程序工具执行的伪代码
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. 实时更新(通知)
理解工具列表变更通知
当服务器的可用工具发生变化(例如,新功能可用、现有工具被修改或工具暂时不可用)时,服务器可以主动通知连接的客户端:
json
{
"jsonrpc": "2.0",
"method": "notifications/tools/list_changed"
}
MCP通知的关键特性
-
无需响应 :请注意,通知中没有
id
字段。这遵循JSON - RPC 2.0通知语义,即不期望也不发送响应。 -
基于能力 :只有那些在初始化过程中在工具能力中声明了
"listChanged": true
的服务器才会发送此通知(如步骤1所示)。 -
事件驱动:服务器根据内部状态变化决定何时发送通知,这使得MCP连接具有动态性和响应性。
客户端对通知的响应
收到此通知后,客户端通常会通过请求更新的工具列表做出响应。这创建了一个刷新周期,使客户端对可用工具的了解始终保持最新:
json
{
"jsonrpc": "2.0",
"id": 4,
"method": "tools/list"
}
通知为何重要
该通知系统具有以下几个重要原因:
- 动态环境:工具可能会根据服务器状态、外部依赖关系或用户权限的出现和消失。
- 高效性:客户端无需轮询以获取变化;当更新发生时,它们会收到通知。
- 一致性:确保客户端始终拥有有关服务器可用功能的准确信息。
- 实时协作:支持能够适应不断变化上下文的响应式人工智能应用程序。
该通知模式不仅适用于工具,还适用于其他MCP原语,从而实现客户端和服务器之间的全面实时同步。
这在人工智能应用程序中的工作原理
当人工智能应用程序收到有关工具变化的通知识别时,它会立即刷新其工具注册表,并更新语言模型的可用功能。这确保了正在进行的对话始终可以访问最新的一组工具,并且语言模型可以随着新功能的出现而动态适应。
python
# 人工智能应用程序通知处理的伪代码
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()