翻译:intro
mcp-servers
介绍
Model Context Protocol (MCP) 是一个开放协议,标准化了应用程序如何为大型语言模型(LLM)提供上下文。 可以将 MCP 想象成 AI 应用程序的 USB-C 接口。 就像 USB-C 为连接设备与各种外设和配件提供了标准化方式一样,MCP 为连接 AI 模型与不同数据源和工具提供了标准化的方式。 MCP 使您能够在 LLM 上构建代理和复杂的工作流,将模型与外部世界连接。
总体架构
Concepts of MCP
参与者
MCP 遵循客户端-服务器架构,这个架构中的关键参与者包括:
- **MCP 主机 (MCP Host):**协调和管理一个或多个 MCP 客户端的 AI 应用。
- **MCP 客户端 (MCP Client):**负责与 MCP 服务器保持连接并从服务器获取上下文,以供 MCP 主机使用的组件。
- MCP 服务器 (MCP Server):为 MCP 客户端提供上下文的程序。
例如: Visual Studio Code 可作为 MCP 主机。
当它与一个 MCP 服务器(如 Sentry MCP 服务器)建立连接时,Visual Studio Code 运行时会实例化一个 MCP 客户端对象,该对象负责维护与 Sentry MCP 服务器的连接。
当 Visual Studio Code 随后连接到另一个 MCP 服务器(如本地文件系统服务器)时,它会再实例化一个额外的 MCP 客户端对象来维护这个连接。
因此,MCP 客户端和 MCP 服务器之间保持着一对一的关系。

层次结构
MCP 由两个层次构成:
- 数据层 (Data layer):定义基于 JSON-RPC 的客户端-服务器通信协议,包括生命周期管理和核心原语(如工具、资源、提示和通知)。
- 传输层 (Transport layer):定义实现客户端和服务器之间数据交换的通信机制和通道,包括特定于传输方式的连接建立、消息分帧和授权。
从概念上讲,数据层是内层,而传输层是外层。
数据层
数据层实现了基于 JSON-RPC 2.0 的交换协议,定义了消息结构和语义。该层包括:
- 生命周期管理 (Lifecycle management):处理客户端和服务器之间的
连接初始化、能力协商和连接终止。 - 服务器特性 (Server features):使服务器能够提供核心功能,包括用于 AI 动作的
工具、用于上下文数据的资源以及用于交互模板的提示。 - 客户端特性 (Client features):使服务器能够请求客户端从主机 LLM 进行采样、向用户征求输入以及向客户端记录消息。
- 实用特性 (Utility features):支持额外的功能,如用于实时更新的通知和用于长时间运行操作的进度跟踪。
传输层
传输层管理客户端和服务器之间的通信通道和身份验证。它负责处理连接建立、消息分帧以及 MCP 参与者之间的安全通信。
MCP 支持两种传输机制:
- Stdio 传输 (Stdio transport):使用标准输入/输出流在同一台机器上的本地进程之间进行直接通信,提供最佳性能且无网络开销。
- **可流式 HTTP 传输 (Streamable HTTP transport):**使用 HTTP POST 进行客户端到服务器的消息传输,并可选地使用服务器发送事件 (Server-Sent Events) 来实现流式传输。这种传输方式支持远程服务器通信,并支持标准的 HTTP 身份验证方法,包括持有者令牌 (bearer tokens)、API 密钥和自定义标头。MCP 建议使用 OAuth 获取身份验证令牌。
传输层将通信细节从协议层抽象出来,使得所有传输机制都可以使用相同的 JSON-RPC 2.0 消息格式。
数据层协议
生命周期管理
MCP 是一个有状态协议,需要生命周期管理。生命周期管理的目的是协商客户端和服务器都支持的能力。详细信息可在规范中找到,而示例部分则展示了初始化序列。
原语
MCP 原语 (Primitives) 是 MCP 中最重要的概念。它们定义了客户端和服务器可以互相提供的功能。这些原语规定了可以与 AI 应用共享的上下文信息类型以及可以执行的操作范围。
MCP 定义了服务器可以公开的三种核心原语:
- 工具 (Tools):AI 应用可以调用的可执行函数,用于执行操作(例如,文件操作、API 调用、数据库查询)。
- 资源 (Resources):为 AI 应用提供上下文数据的数据源(例如,文件内容、数据库记录、API 响应)。
- 提示 (Prompts):可重复使用的模板,用于帮助构建与语言模型的交互(例如,系统提示、少样本示例)。
每种原语类型都包含用于发现 (*/list)、检索 (*/get),以及在某些情况下用于执行 (tools/call) 的关联方法。
MCP 也定义了客户端可以公开的原语。这些原语允许 MCP 服务器作者构建更丰富的交互。
- 采样 (Sampling):允许服务器请求客户端的 AI 应用提供语言模型补全。当服务器作者需要访问语言模型,但又希望保持模型独立性而不将语言模型 SDK 包含在 MCP 服务器中时,这个功能非常有用。他们可以使用
sampling/complete方法向客户端的 AI 应用请求语言模型补全。 - 征求 (Elicitation):允许服务器向用户请求额外信息。当服务器作者需要从用户那里获取更多信息或请求对某个操作的确认时,这个功能非常有用。他们可以使用
elicitation/request方法向用户请求额外信息。 - 日志记录 (Logging):使服务器能够向客户端发送日志消息,用于调试和监控目的。
通知 (Notifications)
该协议支持实时通知,以实现服务器和客户端之间的动态更新。
例如,
- 当服务器的可用工具发生变化时
- 新功能可用或现有工具被修改时
服务器可以发送工具更新通知,以告知已连接的客户端这些变化。通知作为 JSON-RPC 2.0 通知消息发送(不期望响应),使得 MCP 服务器能够向已连接的客户端提供实时更新。
示例(数据层)
1.Initialization (Lifecycle Management)
正如生命周期管理部分所述,客户端发送一个 initialize 请求来建立连接并协商支持的功能。
Request
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-06-18",
"capabilities": {
"elicitation": {}
},
"clientInfo": {
"name": "example-client",
"version": "1.0.0"
}
}
}
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 原语:
-
客户端能力:
"elicitation": {}- 客户端声明它能够处理用户交互请求(可以接收elicitation/create方法调用)。
-
服务器能力:
"tools": {"listChanged": true}- 服务器支持工具原语 并且 可以在其工具列表更改时发送tools/list_changed通知。"resources": {}- 服务器也支持资源原语(可以处理resources/list和resources/read方法)。
成功初始化后,客户端发送一个通知以表明已准备就绪:
{
"jsonrpc": "2.0",
"method": "notifications/initialized"
}
2.工具发现-Tool Discovery (Primitives)
连接建立后,客户端现在可以通过发送tools/list 请求来发现可用的工具。
request
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list"
}
response
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"tools": [
{
"name": "calculator_arithmetic",
"title": "计算器",
"description": "执行数学计算,包括基本算术、三角函数和代数运算",
"inputSchema": {
"type": "object",
"properties": {
"expression": {
"type": "string",
"description": "要评估的数学表达式(例如:'2 + 3 * 4', 'sin(30)', 'sqrt(16)')"
}
},
"required": ["expression"]
}
},
{
"name": "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 数组,它提供了关于每个可用工具的全面元数据。这种基于数组的结构允许服务器同时公开多个工具,同时在不同功能之间保持清晰的界限。
响应中的每个工具对象都包含几个关键字段:
name:服务器命名空间中工具的唯一标识符。这是工具执行的主键,应遵循清晰的命名模式(例如calculator_arithmetic而非仅仅calculate)。title:人类可读的工具显示名称,客户端可以向用户展示。description:详细解释该工具的作用以及何时使用。inputSchema:一个 JSON Schema,定义了预期的输入参数,实现了类型验证并提供了关于必需和可选参数的清晰文档。
3.工具执行-Tool Execution (Primitives)
客户端现在可以使用 tools/call 方法来执行工具。这演示了 MCP 原语在实践中的使用方式:在发现可用工具后,客户端可以以适当的参数调用它们
request
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "weather_current",
"arguments": {
"location": "San Francisco",
"units": "imperial"
}
}
}
response
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"content": [
{
"type": "text",
"text": "Current weather in San Francisco: 68°F, partly cloudy with light winds from the west at 8 mph. Humidity: 65%"
}
]
}
}
4.实时更新(Notifications)
当服务器的可用工具发生变化时,服务器可以主动通知已连接的客户端:
request
{
"jsonrpc": "2.0",
"method": "notifications/tools/list_changed"
}
MCP 通知的关键特性
- 无需响应:请注意,通知中没有
id字段。这遵循 JSON-RPC 2.0 的通知语义,即不期望或发送响应。 - 基于能力:此通知仅由在初始化期间在其工具能力中声明
"listChanged": true的服务器发送 - 事件驱动:服务器根据内部状态变化来决定何时发送通知,这使得 MCP 连接具有动态性和响应性。
客户端对通知的响应
收到此通知后,客户端通常会通过请求更新后的工具列表来做出反应。这创建了一个刷新周期,使客户端对可用工具的理解保持最新:
{
"jsonrpc": "2.0",
"id": 4,
"method": "tools/list"
}
为什么通知很重要
这个通知系统至关重要,原因有几个:
- 动态环境:工具可能会根据服务器状态、外部依赖或用户权限而出现或消失。
- 效率:客户端无需轮询更改;当更新发生时它们会收到通知。
- 一致性:确保客户端始终拥有关于可用服务器功能的准确信息。
- 实时协作:支持响应式 AI 应用,它们可以适应不断变化的上下文。
这种通知模式不仅限于工具,还扩展到其他 MCP 原语,实现了客户端和服务器之间全面的实时同步。
Server Concepts
MCP 服务器是通过标准化的协议接口向 AI 应用公开特定功能的程序。每个服务器都为其特定的领域提供专注的功能。
构建模块核心
| Building Block | Purpose | Who Controls It | Real-World Example |
|---|---|---|---|
| Tools | 用于 AI 动作 | Model-controlled | 搜索航班、发送消息、创建日历事件 |
| Resources | 用于上下文数据 | Application-controlled | 文档、日历、电子邮件、天气数据 |
| Prompts | For interaction templates | User-controlled | “规划度假”、“总结我的会议”、“起草一封电子邮件” |
Tools(略)
前文已详细说明,不再赘述
资源 - Resources - Context Data
资源公开来自文件、API、数据库或任何其他 AI 需要理解上下文的数据源的信息。
应用可以直接访问这些信息,并决定如何使用它——无论是选择相关部分、使用嵌入式搜索还是将其全部传递给模型。
资源使用基于 URI 的标识,每个资源都有一个唯一的 URI,例如 file:///path/to/document.md。
它们声明 MIME 类型以进行适当的内容处理,并支持两种发现模式:具有固定 URI 的直接资源(direct resources)和具有参数化 URI 的资源模板(resource templates)。
资源模板通过 URI 模板实现动态资源访问。例如,travel://activities/{city}/{category} 模板将通过替换 {city} 和{category}参数来访问过滤后的活动数据。
协议操作:
| 方法 | 目的 | 返回值 |
|---|---|---|
| resources/list | 列出可用的直接资源 | 资源描述符数组 |
| resources/templates/list | 发现资源模板 | 资源模板定义数组 |
| resources/read | 检索资源内容 | 带有元数据的资源数据 |
| resources/subscribe | 监控资源变化 | 订阅确认 |
Resource示例
继续以旅行规划为例,资源为 AI 应用提供了访问相关信息的途径:
- 日历数据 (calendar://events/2024) - 用于检查可用性。
- 旅行文档 (file:///Documents/Travel/passport.pdf) - 用于获取重要信息。
- 过往行程 (trips://history/barcelona-2023) - 用户选择遵循哪种过往旅行风格。
Resource Template 示例
{
"uriTemplate": "weather://forecast/{city}/{date}",
"name": "weather-forecast",
"title": "Weather Forecast",
"description": "Get weather forecast for any city and date",
"mimeType": "application/json"
}
{
"uriTemplate": "travel://flights/{origin}/{destination}",
"name": "flight-search",
"title": "Flight Search",
"description": "Search available flights between cities",
"mimeType": "application/json"
}
Prompts
Prompts提供可重复使用的模板。它们允许 MCP 服务器作者为某个领域提供参数化提示,或展示如何最佳地使用 MCP 服务器。
协议操作:
| 方法 | 目的 | 返回值 |
|---|---|---|
| prompts/list | 发现可用提示 | 提示描述符数组 |
| prompts/get | 检索提示详情 | 带有参数的完整提示定义 |
Example: “Plan a vacation” prompt:
{
"name": "plan-vacation",
"title": "规划度假",
"description": "指导完成度假规划过程",
"arguments": [
{ "name": "destination", "type": "string", "required": true },
{ "name": "duration", "type": "number", "description": "天数" },
{ "name": "budget", "type": "number", "required": false },
{ "name": "interests", "type": "array", "items": { "type": "string" } }
]
}
通过提示系统,用户可以实现结构化输入,而非非结构化的自然语言输入:
- 选择
“Plan a vacation”template - 输入结构化参数:巴塞罗那,7 天,$3000,[“海滩”, “建筑”, “美食”]
- 根据模板执行一致的工作流
MCP 协同工作
当多个服务器协同工作,通过统一的接口结合其专业能力时,MCP 的真正力量就显现出来了。
示例:多服务器旅行规划
考虑一个连接了三个服务器的 AI 应用:
- Travel Server - 处理航班、酒店和行程
- Weather Server - 提供气候数据和预报
- Calendar/Email Server - 管理日程和通信
完整的工作流
1. 用户调用带有参数的Promot:
{
"prompt": "plan-vacation",
"arguments": {
"destination": "巴塞罗那",
"departure_date": "2024-06-15",
"return_date": "2024-06-22",
"budget": 3000,
"travelers": 2
}
}
2.用户选择要包含的Resource:
calendar://my-calendar/June-2024(from Calendar Server)travel://preferences/europe(from Travel Server)travel://past-trips/Spain-2023(from Travel Server)
3.AI 处理请求
AI 首先读取所有选定的资源以收集上下文。
4. 从日历中,它确定了可用的日期。
5. 从旅行偏好中,它了解了首选的航空公司和酒店类型。
6. 从过往行程中,它发现了以前喜欢的地点。
7. 从天气数据中,它检查了旅行期间的气候条件。
利用这些上下文,AI 随后请求用户批准以执行一系列协调的动作:
8. 搜索从纽约到巴塞罗那的航班、
9. 在指定预算内寻找酒店、
10. 为旅行时长创建一个日历事件,
11. 以及发送包含旅行详情的确认电子邮件。
Client Concepts
MCP Client由host application实例化,用于与特定的 MCP 服务器进行通信。
Core Client Features
除了利用服务器提供的上下文外,客户端还可以向服务器提供多种功能。这些客户端特性允许服务器作者构建更丰富的交互。
采样-Sampling
采样允许服务器通过客户端请求语言模型补全,从而在保持安全和用户控制的同时,实现代理行为。
该流程通过多个**人工参与(human-in-the-loop)**检查点来确保安全。用户可以审查并修改初始请求和生成的响应,然后响应才会返回给服务器。
Request parameters example
{
messages: [
{
role: "user",
content: "分析这些航班选项并推荐最佳选择:\n" +
"[47个航班,包含价格、时间、航空公司和中转信息]\n" +
"用户偏好:上午出发,最多一次中转"
}
],
modelPreferences: {
hints: [{
name: "claude-3-5-sonnet" // 建议使用的模型
}],
costPriority: 0.3, // 较不关心API成本
speedPriority: 0.2, // 可等待全面分析
intelligencePriority: 0.9 // 需要复杂权衡评估
},
systemPrompt: "你是一名旅行专家,帮助用户根据他们的偏好找到最佳航班",
maxTokens: 1500
}
示例:航班分析工具
考虑一个旅行预订服务器,它有一个名为findBestFlight 的工具,该工具使用采样来分析可用航班并推荐最佳选择。
当用户要求“下个月帮我预订去巴塞罗那的最佳航班”时,该工具需要 AI 的协助来评估复杂的权衡。
- 该工具查询航空公司 API 并收集 47 个航班选项。
- 然后,它请求 AI 协助来分析这些选项:
“分析这些航班选项并推荐最佳选择:[47个航班,包含价格、时间、航空公司和中转信息] 用户偏好:上午出发,最多一次中转。” - 客户端询问用户:“允许采样请求吗?”
- 获得批准后,AI 会评估权衡——例如更便宜的红眼航班与方便的上午出发航班。该工具利用这一分析来呈现三个最佳推荐。
征求-Elicitation
**征求(Elicitation)**使服务器能够在交互过程中向用户请求特定信息,从而创建更具动态性和响应性的工作流。
Elicitation components example:
{
method: "elicitation/requestInput",
params: {
message: "请确认您的巴塞罗那度假预订详情:",
schema: {
type: "object",
properties: {
confirmBooking: {
type: "boolean",
description: "确认预订(航班 + 酒店 = $3,000)"
},
seatPreference: {
type: "string",
enum: ["window", "aisle", "no preference"],
description: "首选的航班座位类型"
},
roomType: {
type: "string",
enum: ["sea view", "city view", "garden view"],
description: "首选的酒店房间类型"
},
travelInsurance: {
type: "boolean",
default: false,
description: "添加旅行保险($150)"
}
},
required: ["confirmBooking"]
}
}
}
示例:假期预订批准
一个旅行预订服务器通过最终的预订确认流程展示了elicitation的强大之处。
当用户选择了理想的巴塞罗那度假套餐后,服务器需要收集最终的批准和任何缺失的细节才能继续。
服务器发起一个结构化的elicitation请求,其中包括旅行摘要(巴塞罗那航班 6月15-22日,海滨酒店,总计 $3,000)以及用于任何额外偏好的字段——例如座位选择、房间类型或旅行保险选项。
随着预订的进展,服务器会征求完成预订所需的联系信息。它可能会要求提供航班预订所需的旅行者详情、酒店的特殊请求或紧急联系信息。
版本控制-Versioning
模型上下文协议(MCP)使用字符串格式的版本标识符,遵循 YYYY-MM-DD 的格式,以表明最近一次进行不兼容变更的日期。
只要协议的更新保持向后兼容性,版本号将不会递增。这使得在保持互操作性的同时,可以进行渐进式改进。
修订版本
修订版本可能被标记为:
- 草稿 (Draft):正在进行中的规范,尚未准备好供使用。
- 当前 (Current):当前版本的协议,已准备好供使用,并可能继续接收向后兼容的更改。
- 最终 (Final):过去的、完整的规范,将不会被更改。
版本协商
版本协商在初始化阶段进行。客户端和服务器可以(MAY)同时支持多个协议版本,但它们必须(MUST)就一个用于本次会话的版本达成一致。
如果版本协商失败,协议会提供适当的错误处理,允许客户端在无法找到与服务器兼容的版本时,优雅地终止连接

2591

被折叠的 条评论
为什么被折叠?



