模型上下文协议 (MCP) 正在成为构建具备强大上下文感知能力的大型语言模型 (LLM) 应用的重要基石。上一篇文章中我介绍了MCP,它让我深深着迷,因此我决定深入了解其背后的架构。当然,我提到过 MCP 主机 (Host)、客户端 (Client) 和服务器 (Server),但 MCP 比这更复杂。它建立在许多其他组件和概念之上,这些组件都值得了解。理解这些概念,才能更好地构建类似系统。比如,如果我想构建一个定制的 MCP 服务器,虽然有很多库可以帮助我做到这一点,但理解所有环节如何连接以及事物如何运作会更有趣。本文将深入探讨 MCP 架构 的核心概念,包括传输 (Transports)、资源 (Resources)、提示 (Prompts)、工具 (Tools)、采样 (Sampling) 和根 (Roots),并通过具体例子说明其作用。

MCP 架构:客户端-服务器模式的核心

MCP 架构 采用经典的客户端-服务器模式。简单来说,客户端发起请求,MCP 服务器 处理请求并返回响应。一个 MCP 主机 可以拥有多个客户端,每个客户端与一个服务器保持一对一的关系。这种架构带来的优势在于,它允许客户端和服务器独立开发和部署,从而提高系统的灵活性和可扩展性。比如,一个网页聊天机器人(客户端)可以向部署在云端的 MCP 服务器 发送用户消息,服务器负责调用 LLM 进行处理,并将结果返回给客户端。

传输 (Transports):客户端与服务器之间的桥梁

客户端和服务器之间的通信通过 传输 (Transports) 层进行。 MCP 文档定义了两种内置的传输类型:标准输入输出 (Stdio) 传输和 HTTP 与服务器发送事件 (SSE) 传输。

  • Stdio 传输: 客户端和服务器通过标准输入进行通信,服务器通过标准输出将数据返回给客户端。这种传输方式适用于客户端和服务器运行在同一台机器上或同一应用/进程内的情况。例如,一个命令行应用读取一个长文本文件,通过 Stdio 将其发送给本地 LLM,然后打印返回的摘要。

  • HTTP 与 SSE 传输: 客户端通过 HTTP POST 请求与服务器进行通信,服务器通过常规 HTTP 或服务器发送事件 (SSE) 将数据返回给客户端,SSE 用于流式传输。这种传输方式适用于客户端和服务器通过网络分隔,并且需要从服务器获得实时更新的情况。例如,一个网页聊天机器人,用户输入问题后,可以实时看到 LLM 的响应。

MCP 中,客户端和服务器之间交换的数据使用 JSON-RPC 2.0 格式。JSON-RPC 2.0 是一种协议,它定义了如何使用 JSON 构建 API,包括命令、结构化请求和响应。这确保了通信的标准化和可靠性。

资源 (Resources):为 LLM 提供上下文信息

资源 (Resources)MCP 服务器 向其客户端公开的数据。客户端使用这些数据作为与 LLM 交互时的上下文。 MCP 中的资源可以有两种类型的内容:

  • 文本 (UTF-8 编码): 任何类型的文本数据,例如纯文本、JSON/XML 文件等。

  • 二进制 (base64 编码的原始数据): 任何类型的非文本格式,包括图像、音频、视频文件等。

例如,一个客户服务机器人可以使用客户的个人资料 (JSON 格式) 和历史对话记录 (文本格式) 作为 资源,为 LLM 提供必要的上下文信息,从而更好地理解客户的需求并提供个性化的服务。

提示 (Prompts):可复用的模板和工作流

MCP 中,提示 (Prompts) 是服务器提供的,客户端可以发现和调用可重用的模板和工作流程。它们不仅仅是 LLM 遵循的简单规则,还可以接受变量作为输入、从资源中提取信息、触发操作,甚至可以作为界面元素(例如客户端应用中的斜杠命令 /debug)出现。

例如,一个代码审查 提示 可能如下所示:

对这段 {language} {code_type} 代码进行全面的代码审查,并结合以下上下文:

**项目上下文:**
- 框架:{framework}
- 团队编码标准:{coding_standards}
- 性能要求:{performance_requirements}

**待审查代码:**
{code_snippet}

**审查重点领域:**
1. 安全漏洞
2. 代码可维护性和可读性
3. 性能优化机会
4. 遵守 {framework} 最佳实践
5. 测试覆盖建议
6. 文档完整性

**输出格式:**
- 总体评估 (批准/请求更改/评论)
- 关键问题 (如果有)
- 改进建议
- 值得强调的积极方面

这个 提示 接受 languagecode_typeframeworkcoding_standardsperformance_requirementscode_snippet 作为变量输入,使代码审查过程更加灵活和高效。

工具 (Tools):赋予 LLM 行动能力

工具 (Tools)MCP 中最重要的概念之一。它们是 MCP 服务器 向客户端公开的可执行功能。换句话说,工具 使 LLM 能够与外部系统交互,并赋予其执行操作的能力。

例如,一个 工具 可以定义为:

@Tool(
    name = "get_customer_by_id",
    description = "根据客户 ID 检索客户信息",
    parameters = {
        @MCPParameter(name = "customer_id", type = "integer", description = "要查找的客户 ID", required = true)
    }
)
public String getCustomerById(int customerId) {
  // 实现
}

这个 工具 允许 LLM 通过客户 ID 检索客户信息。

资源工具 之间的区别在于,资源 仅向 LLM 提供数据或上下文,而 工具 赋予 LLM 与外部系统交互和执行操作的能力。例如,LLM可以使用getcustomerby_id这个工具,结合客户历史订单的资源,分析客户偏好并给出精准的商品推荐。

采样 (Sampling):服务器与 LLM 的协作

采样 (Sampling) 是指 MCP 服务器 通过客户端“向 LLM 寻求帮助”的能力。换句话说,它是关于服务器与 LLM 协作分析数据并做出决策。

一个没有 采样 的基本流程可能如下所示:

  1. 用户:提出需要分析的请求
  2. LLM:调用 工具 获取信息
  3. 服务器:从源检索原始数据
  4. 服务器:将原始数据直接返回给 LLM
  5. LLM:分析所有数据并提供最终响应

相同的流程,但包含 采样,可能如下所示:

  1. 用户:提出需要分析的请求
  2. LLM:调用 工具 获取信息
  3. 服务器:从源检索原始数据
  4. 服务器 采样 LLM:“分析此数据。这意味着什么?”
  5. LLM 生成:数据的解释/分析
  6. 服务器:使用 LLM 的分析来决定要获取的额外数据
  7. 服务器:将上下文信息返回给 LLM
  8. LLM:根据全面的分析提供最终响应

例如,一个天气预报 工具

没有采样:

  1. 用户:“我今天应该去徒步旅行吗?”
  2. LLM:调用天气 工具
  3. 服务器:获取天气数据 (温度:24°C,湿度:85%,降雨概率:60%)
  4. 服务器:将原始数据返回给 LLM
  5. LLM:分析数据并响应:“天气显示降雨概率为 60%,湿度很高。这不适合徒步旅行”

有采样:

  1. 用户:“我今天应该去徒步旅行吗?”
  2. LLM:调用天气 工具
  3. 服务器:获取天气数据 (温度:24°C,湿度:85%,降雨概率:60%)
  4. 服务器 采样 LLM:“这种天气适合徒步旅行吗?”
  5. LLM 生成:“高湿度和 60% 的降雨概率使其具有徒步旅行的风险”
  6. 服务器:使用 LLM 的评估来查找是否有因最近的降雨损坏而关闭的徒步旅行路径
  7. 服务器:发现由于最近的降雨损坏,3 条受欢迎的路径已关闭
  8. 服务器:将包含天气数据和路径状态的完整建议返回给 LLM
  9. LLM:“我不建议今天去徒步旅行。天气显示降雨概率为 60%,湿度很高,使情况变得危险。此外,由于最近的降雨损坏,3 条受欢迎的徒步旅行路径目前已关闭。”

通过 采样MCP 服务器 可以利用 LLM 的分析能力,做出更明智的决策,并提供更准确的响应。这体现了 MCP 架构中服务器和 LLM 相互协作的强大能力。

根 (Roots):限制服务器的访问权限

根 (Roots)MCP 客户端使用的一种机制,用于通知服务器其资源,同时也限制服务器的访问权限。如果想知道 MCP 服务器 为什么需要了解客户端的根,主要原因在于安全性、性能、上下文感知能力和资源范围界定。

例如:

没有根: 服务器可以访问系统上的任何文件。
有根: 服务器仅限于 /Users/yourname/project/

  • 客户端根:/workspace/frontend/

    • 服务器公开:仅与该前端项目相关的 工具
    • 服务器隐藏:后端数据库、系统文件、其他项目。
  • 根:https://api.company.com/v2/

    • 服务器:预加载 API 架构,缓存常用端点。
    • 服务器:忽略 v1 API、其他域。
  • 根:file:///code/python-project/

    • 服务器启用:Python 代码检查、pytest 运行器、pip 工具

通过定义 MCP 客户端可以有效地控制 MCP 服务器 的访问权限,确保系统的安全性和可靠性。例如,一个金融应用程序可以使用 来限制服务器只能访问用户的账户信息,而不能访问用户的个人身份信息。

结语

深入研究 MCP 的各个组件和概念后,我对 MCP 架构 的理解更加透彻。MCP 是一种复杂的协议,每个部分都有明确的目标。最终,当希望为应用添加 AI 层时,它们协同工作使我们的生活更加轻松。理解 MCP传输资源提示工具采样 这些关键概念,将有助于我们更好地构建智能、安全和高效的 LLM 应用。希望本文能够帮助你更好地理解 MCP 架构,并将其应用到你的项目中。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注