主题
理解 MCP 客户端
MCP 客户端由宿主应用实例化,用于与特定的 MCP 服务端通信。宿主应用(例如 Claude.ai 或 IDE)管理整体用户体验并协调多个客户端。每个客户端负责与一个服务端的一次直接通信。
理解这一区别很重要:宿主是用户交互的应用,而客户端是协议层组件,用于建立服务端连接。
客户端核心特性
除了使用服务端提供的上下文之外,客户端还可以向服务端提供若干特性。这些客户端特性让服务端作者能够构建更丰富的交互。
| 特性 | 说明 | 示例 |
|---|---|---|
| 征询 | 征询使服务端能够在交互过程中向用户请求特定信息,为服务端按需收集信息提供了一种结构化方式。 | 一个预订旅行的服务端可能会询问用户对飞机座位、房型的偏好,或询问其联系电话以完成预订。 |
| 根目录 | 根目录允许客户端指定服务端应关注的目录,通过协调机制传达预期范围。自协议版本 2026-07-28 起,根目录已被弃用。 | 一个预订旅行的服务端可能被授予对特定目录的访问权限,并从中读取用户的日历。 |
| 采样 | 采样允许服务端通过客户端请求 LLM 补全,从而支持智能体式工作流。这种方式让客户端完全掌控用户权限与安全措施。自协议版本 2026-07-28 起,采样已被弃用。 | 一个预订旅行的服务端可能将航班列表发送给 LLM,并请求 LLM 为用户挑选最佳航班。 |
征询
征询使服务端能够在交互过程中向用户请求特定信息,从而创建更动态、更响应式的工作流。
概述
征询为服务端按需收集必要信息提供了一种结构化方式。服务端无需预先要求所有信息,也无需在数据缺失时失败,而是可以暂停操作,向用户请求特定输入。这创造了更灵活的交互,使服务端能够适应用户需求,而不是遵循僵化的模式。
征询支持两种模式:
- 表单模式:服务端要求客户端从用户处收集结构化数据。请求中包含一个 schema,客户端用它构建输入表单并校验响应。
- URL 模式:服务端提供一个供用户打开的 URL。交互在带外进行,其数据从不经过客户端,因此该模式适用于凭据输入或第三方 OAuth 授权等敏感流程。
征询遵循多轮往返请求(MRTR)模式。当服务端在处理诸如 tools/call 之类的请求时需要用户输入,它会返回一个 InputRequiredResult,其 inputRequests 字段携带一个或多个 elicitation/create 请求。客户端收集输入并重试原始请求,附带收集到的 inputResponses,并回显服务端包含的任何 requestState。
征询流程:
sequenceDiagram
participant User
participant Client
participant Server
Client->>Server: tools/call (id: 1)
Note over Server: Server needs more information
Server-->>Client: InputRequiredResult with elicitation/create request
Note over Client,User: Human interaction
Client->>User: Present elicitation UI
User-->>Client: Provide requested information
Note over Client,Server: Retry request with user input
Client->>Server: tools/call (id: 2, inputResponses)
Note over Server: Continue processing with new information
Server-->>Client: Final result
该流程支持动态信息收集。服务端可以在需要时请求特定数据,用户通过适当的 UI 提供信息,服务端利用新获得的上下文完成重试的请求。
征询请求示例(在 InputRequiredResult.inputRequests 内传递):
typescript
{
method: "elicitation/create",
params: {
mode: "form",
message: "Please confirm your Barcelona vacation booking details:",
requestedSchema: {
type: "object",
properties: {
confirmBooking: {
type: "boolean",
description: "Confirm the booking (Flights + Hotel = $3,000)"
},
seatPreference: {
type: "string",
enum: ["window", "aisle", "no preference"],
description: "Preferred seat type for flights"
},
roomType: {
type: "string",
enum: ["sea view", "city view", "garden view"],
description: "Preferred room type at hotel"
},
travelInsurance: {
type: "boolean",
default: false,
description: "Add travel insurance ($150)"
}
},
required: ["confirmBooking"]
}
}
}示例:假期预订审批
一个旅行预订服务端通过最终的预订确认流程展示了征询的强大能力。当用户选定了前往巴塞罗那的理想度假套餐后,服务端需要在继续之前收集最终确认以及任何缺失的细节。
服务端通过一个结构化请求征询预订确认,其中包含行程摘要(巴塞罗那航班 6 月 15-22 日、海滨酒店、总计 $3,000)以及用于收集任何额外偏好的字段——例如座位选择、房型或旅行保险选项。
随着预订推进,服务端征询完成预订所需的联系信息。它可能会询问航班预订的旅客详情、酒店的特殊要求或紧急联系人信息。
用户交互模型
征询交互被设计为清晰、有上下文且尊重用户自主权:
请求呈现:客户端展示征询请求时,会清晰说明是哪个服务端在询问、为什么需要这些信息以及将如何使用。请求消息解释目的,而 schema 提供结构与校验。
响应选项:用户可以通过适当的 UI 控件(文本字段、下拉框、复选框)提供所请求的信息,可以拒绝提供信息并附上可选说明,也可以取消整个操作。客户端在将响应返回给服务端之前,会依据所提供的 schema 进行校验。
URL 处理:对于 URL 模式,客户端会显示完整 URL,并在打开前获取明确同意,且绝不自动抓取该 URL。客户端只会得知用户是否同意。交互本身仅发生在用户与目标站点之间。
隐私考量:服务端 MUST NOT(必须不)使用表单模式请求密码、API 密钥、访问令牌或支付凭据等敏感信息。这些交互属于 URL 模式,该模式将数据保持在带外,使其从不经过客户端或 LLM 上下文。客户端会对可疑请求发出警告,并让用户在发送前检查表单数据。
根目录
WARNING
自协议版本 2026-07-28 起,根目录已被弃用并计划移除。新的实现应改为通过工具参数、资源 URI 或服务端配置传递目录或文件。
根目录为服务端操作定义文件系统边界,允许客户端指定服务端应关注的目录。
概述
根目录是一种客户端向服务端传达文件系统访问边界的机制。它们由文件 URI 组成,指示服务端可以操作的目录,帮助服务端理解可用文件和文件夹的范围。虽然根目录传达了预期边界,但它们并不强制执行安全限制。实际安全必须在操作系统层面通过文件权限和/或沙箱来实施。
根目录结构:
json
{
"uri": "file:///Users/agent/travel-planning",
"name": "Travel Planning Workspace"
}根目录仅限文件系统路径,并且始终使用 file:// URI 方案。它们帮助服务端理解项目边界、工作区组织以及可访问目录。根目录列表可以随着用户处理不同项目或文件夹而变化。服务端在下次请求根目录列表时会获取更新后的边界。
示例:旅行规划工作区
一位处理多个客户行程的旅行代理受益于根目录来组织文件系统访问。设想一个工作区,其中包含用于旅行规划不同方面的各种目录。
客户端向旅行规划服务端提供文件系统根目录:
file:///Users/agent/travel-planning- 包含所有旅行文件的主工作区file:///Users/agent/travel-templates- 可复用的行程模板与资源file:///Users/agent/client-documents- 客户护照与旅行证件
当代理创建巴塞罗那行程时,行为良好的服务端会尊重这些边界——在指定的根目录内访问模板、保存新行程并引用客户文档。服务端通常通过从根目录出发的相对路径,或利用尊重根目录边界的文件搜索工具来访问根目录内的文件。
如果代理打开一个归档文件夹,例如 file:///Users/agent/archive/2023-trips,客户端会将其添加到根目录列表,服务端会在其下一次 roots/list 请求时看到新的边界。
关于尊重根目录的服务端完整实现,请参阅官方 servers 仓库中的 filesystem server。
设计理念
根目录充当客户端与服务端之间的协调机制,而非安全边界。规范要求服务端“SHOULD(应该)尊重根目录边界”,而不是“MUST(必须)强制执行”它们,因为服务端运行的是客户端无法控制的代码。
根目录在以下情况下效果最佳:服务端受信任或经过审查、用户理解其建议性质,且目标是防止意外而非阻止恶意行为。它们擅长上下文范围界定(告诉服务端应关注何处)、意外预防(帮助行为良好的服务端保持在边界内)以及工作流组织(例如自动管理项目边界)。
用户交互模型
根目录通常由宿主应用根据用户操作自动管理,不过某些应用可能会公开手动根目录管理:
自动根目录检测:当用户打开文件夹时,客户端会自动将其作为根目录公开。打开旅行工作区允许客户端将该目录作为根目录公开,帮助服务端理解哪些行程和文档属于当前工作的范围。
手动根目录配置:高级用户可以通过配置指定根目录。例如,添加 /travel-templates 以使用可复用资源,同时排除包含财务记录的目录。
采样
WARNING
自协议版本 2026-07-28 起,采样已被弃用并计划移除。新的实现应改为直接与 LLM 提供商 API 集成。
采样允许服务端通过客户端请求语言模型补全,在保持安全性和用户控制的同时支持智能体式行为。
概述
采样使服务端能够执行依赖 AI 的任务,而无需直接集成 AI 模型或为其付费。相反,服务端可以请求已经具备 AI 模型访问权限的客户端代表其处理这些任务。这种方式让客户端完全掌控用户权限与安全措施。由于采样请求发生在其他操作(例如工具分析数据)的上下文内,并作为独立的模型调用处理,它们在不同上下文之间保持了清晰的边界,从而可以更高效地利用上下文窗口。
采样遵循与征询下所述相同的多轮往返请求流程,其中 InputRequiredResult 携带一个 sampling/createMessage 请求。
服务端还可以在采样期间通过在请求中包含 tools 数组和可选的 toolChoice 字段来请求工具使用。工具定义的作用域限于该采样请求,无需对应服务端所公开的工具。客户端通过 sampling.tools 能力声明支持,服务端 MUST NOT(必须不)向未声明该能力的客户端发送启用工具的采样请求。详情请参阅规范中的采样。
采样流程:
sequenceDiagram
participant LLM
participant User
participant Client
participant Server
Client->>Server: tools/call (id: 1)
Note over Server: Server needs an LLM completion
Server-->>Client: InputRequiredResult with sampling/createMessage request
Note over Client,User: Human-in-the-loop review
Client->>User: Present request for approval
User-->>Client: Review and approve/modify
Note over Client,LLM: Model interaction
Client->>LLM: Forward approved request
LLM-->>Client: Return generation
Note over Client,User: Response review
Client->>User: Present response for approval
User-->>Client: Review and approve/modify
Note over Client,Server: Retry request with approved response
Client->>Server: tools/call (id: 2, inputResponses)
Server-->>Client: Final result
该流程通过多个“人在回路”检查点确保安全。在客户端用其重试原始请求之前,用户可以审查并修改初始请求和生成的响应。
请求参数示例:
typescript
{
messages: [
{
role: "user",
content: {
type: "text",
text: "Analyze these flight options and recommend the best choice:\n" +
"[47 flights with prices, times, airlines, and layovers]\n" +
"User preferences: morning departure, max 1 layover"
}
}
],
modelPreferences: {
hints: [{
name: "claude-sonnet-4-20250514" // Suggested model
}],
costPriority: 0.3, // Less concerned about API cost
speedPriority: 0.2, // Can wait for thorough analysis
intelligencePriority: 0.9 // Need complex trade-off evaluation
},
systemPrompt: "You are a travel expert helping users find the best flights based on their preferences",
maxTokens: 1500
}示例:航班分析工具
设想一个旅行预订服务端,其中有一个名为 findBestFlight 的工具,它使用采样来分析可用航班并推荐最优选择。当用户询问“帮我预订下个月飞往巴塞罗那的最佳航班”时,该工具需要 AI 协助来评估复杂的权衡。
该工具查询航空公司 API 并收集 47 个航班选项。然后它请求 AI 协助分析这些选项:“分析这些航班选项并推荐最佳选择:[47 个航班,包含价格、时间、航空公司和经停] 用户偏好:上午出发,最多 1 次经停。”
客户端发起采样请求,让 AI 评估各种权衡——例如更便宜的红眼航班与便利的上午出发航班。该工具利用此分析呈现前三名推荐。
用户交互模型
虽然并非强制要求,但采样的设计允许“人在回路”控制。用户可以通过多种机制保持监督:
审批控制:采样请求可能要求用户明确同意。客户端可以展示服务端想要分析什么以及为什么。用户可以批准、拒绝或修改请求。
透明度特性:客户端可以显示确切的提示词、模型选择和 token 限制,让用户在 AI 响应返回服务端之前进行审查。
配置选项:用户可以设置模型偏好、为受信任操作配置自动批准,或要求所有操作都需批准。客户端可以提供脱敏敏感信息的选项。
安全考量:客户端和服务端在采样期间都必须妥善处理敏感数据。客户端应实施速率限制并校验所有消息内容。“人在回路”设计确保服务端请求的 AI 交互不会在未经用户明确同意的情况下危及安全或访问敏感数据。