MCP 客户端由主机应用程序实例化,用于与特定的 MCP 服务器通信。主机应用程序(如 Claude.ai 或 IDE)管理整体用户体验并协调多个客户端。每个客户端处理与一个服务器的一次直接通信。 理解这个区别很重要:主机是用户与之交互的应用程序,而客户端是启用服务器连接的协议级组件。

核心客户端功能

除了利用服务器提供的上下文,客户端还可以向服务器提供多种功能。这些客户端功能允许服务器作者构建更丰富的交互。例如,客户端可以允许 MCP 服务器通过信息请求(elicitations)向用户索取额外信息。客户端可以提供以下能力:

采样

采样允许服务器通过客户端请求语言模型补全,从而实现智能体行为,同时保持安全性和用户控制。

概述

采样使服务器能够执行依赖于 AI 的任务,而无需直接集成或为 AI 模型付费。相反,服务器可以请求已具备 AI 模型访问权限的客户端代为处理这些任务。这种方法将用户权限和安全措施的完全控制权交给了客户端。由于采样请求发生在其他操作(如工具分析数据)的上下文中,并作为单独的模型调用进行处理,因此它们在不同上下文之间保持了清晰的界限,从而可以更有效地利用上下文窗口。 采样流程: 该流程通过多个人工审核(human-in-the-loop)检查点来确保安全。用户在初始请求和生成的响应返回服务器之前都可以对其进行审查和修改。 请求参数示例:
{
  messages: [
    {
      role: "user",
      content: "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-3-5-sonnet"  // 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 会评估各种权衡因素——例如更便宜的红眼航班与更方便的早班机。该工具利用此分析结果向用户呈现前三个推荐。

用户交互模型

采样设计的核心原则是人工审核控制。用户通过多种机制保持监督: 批准控制:每个采样请求都需要用户明确同意。客户端会显示服务器想要分析的内容及其原因。用户可以批准、拒绝或修改请求。 透明度功能:客户端会显示确切的提示、模型选择和令牌限制。用户在 AI 响应返回服务器之前可以对其进行审查。 配置选项:用户可以设置模型偏好,为受信任的操作配置自动批准,或要求对所有操作进行审批。客户端可以提供编辑敏感信息的选项。用户通过 includeContext 参数决定采样请求中可以包含多少对话上下文。 隔离:默认情况下,采样请求与主对话上下文隔离。服务器无法访问用户对话。 安全考虑:客户端和服务器在采样期间都必须妥善处理敏感数据。客户端应实施速率限制并验证所有消息内容。人工审核设计确保了由服务器发起的 AI 交互在未经用户明确同意的情况下,无法危及安全或访问敏感数据。

根(Roots)为服务器操作定义了文件系统边界,允许客户端指定服务器应关注的目录。

概述

根是一种客户端向服务器传达文件系统访问边界的机制。它们由文件 URI 组成,指示服务器可以操作的目录,帮助服务器了解可用文件和文件夹的范围。根并不是给予服务器无限制的文件系统访问权限,而是在维持安全边界的同时,引导它们到相关的工作目录。 根结构:
{
  "uri": "file:///Users/agent/travel-planning",
  "name": "Travel Planning Workspace"
}
根专指文件系统路径,并始终使用 file:// URI 方案。它们帮助服务器理解项目边界、工作区组织和可访问的目录。随着用户处理不同的项目或文件夹,根列表可以动态更新,当边界发生变化时,服务器会通过 roots/list_changed 收到通知。 需要注意的是,虽然根为服务器提供了操作位置的指导,但客户端始终完全控制文件访问。根仅仅是传达预期的边界——实际的文件访问总是由客户端的安全策略来调节。

示例:旅行计划工作区

一位处理多个客户旅行计划的旅行代理人可以从根中受益,以组织文件系统访问。假设一个工作区中有不同的目录用于旅行计划的各个方面。 客户端向旅行计划服务器提供以下文件系统根:
  • file:///Users/agent/travel-planning - 包含所有旅行文件的主工作区
  • file:///Users/agent/travel-templates - 可重用的行程模板和资源
  • file:///Users/agent/client-documents - 客户护照和旅行证件
当代理人创建巴塞罗那行程时,服务器在这些边界内工作——访问模板、保存新行程并引用客户文件。它无法访问这些根之外的文件。服务器通常通过使用相对于根目录的路径,或利用遵守根边界的文件搜索工具来访问根内的文件。 如果代理人打开一个归档文件夹,如 file:///Users/agent/archive/2023-trips,客户端会通过 roots/list_changed 更新根列表。

用户交互模型

根通常由主机应用程序根据用户操作自动管理,但某些应用程序也可能提供手动管理根的功能: 自动根检测:当用户打开文件夹时,客户端会自动将其作为根暴露出来。打开一个旅行工作区,服务器就可以访问该目录内的行程和文件。 手动根配置:高级用户可以通过配置指定根。例如,为可重用资源添加 /travel-templates,同时排除包含财务记录的目录。

引出

信息请求(Elicitation)使服务器能够在交互过程中向用户请求特定信息,从而创建更动态、响应更迅速的工作流。

概述

信息请求为服务器按需收集必要信息提供了一种结构化方式。服务器不必预先要求所有信息,也不会在数据缺失时失败,而是可以暂停操作以请求用户的特定输入。这创造了更灵活的交互,服务器能适应用户需求,而不是遵循固定的模式。 信息请求流程: 该流程实现了动态信息收集。服务器可以在需要时请求特定数据,用户通过适当的 UI 提供信息,服务器则利用新获取的上下文继续处理。 信息请求组件示例:
{
  method: "elicitation/requestInput",
  params: {
    message: "Please confirm your Barcelona vacation booking details:",
    schema: {
      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日巴塞罗那航班,海滨酒店,总价3000美元)以及任何其他偏好选项的字段——如座位选择、房型或旅行保险选项。 随着预订的进行,服务器会请求完成预订所需的联系信息。它可能会要求提供航班预订的旅客信息、酒店的特殊要求或紧急联系信息。

用户交互模型

信息请求交互的设计旨在清晰、有上下文且尊重用户自主权: 请求呈现:客户端会以清晰的上下文显示信息请求,说明是哪个服务器在请求、为什么需要这些信息以及将如何使用。请求消息解释目的,而模式(schema)则提供结构和验证。 响应选项:用户可以通过适当的 UI 控件(文本框、下拉菜单、复选框)提供所请求的信息,也可以选择拒绝提供信息并附上可选解释,或取消整个操作。客户端在将响应返回给服务器之前,会根据提供的模式进行验证。 隐私考虑:信息请求绝不会要求密码或 API 密钥。客户端会对可疑请求发出警告,并让用户在发送数据前进行审查。