MCP 协议的架构核心组件拆解(Host、Client、Server 三方职责与协作流程)

拆解 MCP(Model Context Protocol)的架构,关键不是罗列名词,而是看清它为什么非要拆成”Host / Client / Server”三方,而不是传统意义上”客户端 + 服务端”两方。三方模型让 AI 应用本身(Host)不用直接对接每一个外部工具(Server),中间的 Client 充当”安全守门员 + 协议翻译器”。Host 负责用户体验与 LLM 编排,Client 负责连接与消息路由,Server 负责把具体能力封装成标准原语。这种隔离设计是 MCP 能复用、能治理、能横向扩展的根因。

一、三方架构总览

MCP 把整个系统切成三个独立角色,每一个都只关心自己那一层的事。Host 是用户直接打交道的 AI 应用(Claude Desktop、VS Code + Copilot、自研 Agent 平台等),它运行 LLM 并决定什么时候调什么工具;Client 是 Host 内部维护的协议连接器,一个 Client 对应一个 Server,持有这条连接的状态机;Server 才是真正”干活的”,把数据库、文件系统、API、Git 仓库这些异构能力包成统一的 Tools / Resources / Prompts。

组件 部署位置 核心职责 典型实现
Host 终端用户应用 UI、LLM 编排、用户授权、上下文聚合 Claude Desktop、Cursor、自研 Agent
Client Host 进程内 协议协商、消息路由、订阅管理、安全隔离 MCP SDK 内置 Client、各语言客户端
Server 本地进程或远程服务 暴露 Tools / Resources / Prompts 原语 GitHub MCP、FileSystem MCP、Database MCP

MCP 规范明确要求 Host 与 Server 不直接通信:所有交互必须经过 Client 中转。这一条设计原则保证了 Server 拿不到 LLM 的全部对话历史,也拿不到别的 Server 的内部状态——Server 只能看到”我这次调用所需的最小上下文”,极大缩小了攻击面。

二、Host:用户体验与策略中心

Host 的存在感容易被低估,但它承担的职责其实最重。Host 要决定用户授权哪些工具、UI 上如何呈现工具调用结果、上下文窗口怎么分配,以及最关键的——在多 Client 并存时如何把不同 Server 的结果汇总成一次完整的 LLM 调用。

实际工程中,Host 通常用这样的初始化结构来管理多个 Client:

from mcp.client.session import ClientSession
from mcp.client.stdio import stdio_client

# Host 启动一个本地 MCP Server 子进程,并建立 Client 会话
async with stdio_client(["python", "github_mcp_server.py"]) as (read, write):
    async with ClientSession(read, write) as session:
        # 1. 能力协商:Client 声明自己支持的能力
        await session.initialize()

        # 2. 发现:列出 Server 暴露的工具
        tools = await session.list_tools()
        for t in tools:
            print(t.name, "-", t.description)

效果与注意点:每多一个 Server,Host 就多起一个 Client,两者是 1:1 关系。Host 千万不能在 Client 之外另起一条”野连接”绕开协议——那样 Server 协议升级时整条链路会断。能力协商(capability negotiation)发生在 initialize 阶段,双方互相声明支持哪些原语,避免后续调用到一半才暴露能力缺失。

三、Client:协议守门员

Client 是三方中最”轻”却最关键的一环。它由 Host 创建,生命周期完全由 Host 管控,对外不暴露网络端口,对内也不直接处理业务逻辑。Client 的工作可以压缩成四件事:

  1. 与一个 Server 建立状态化会话(stateful session),保持连接心跳与重连;
  2. 在会话初始化时完成协议版本与能力协商;
  3. 双向路由 JSON-RPC 2.0 消息,包括 Requests / Responses / Notifications 三类;
  4. 维护订阅与通知机制,例如资源变更、工具列表更新。

3.1 能力协商:让协议可演进

MCP 不会一次性把”全部能力”都打开,而是按”声明 → 协商 → 使用”的顺序开放。Server 在 initialize 响应里声明自己支持 tools、resources、prompts 中的哪些,Client 则声明自己支持 sampling(让 Server 反向请 Client 调一次 LLM)或 roots(暴露文件系统根目录)。这种”能力开关”机制让协议能向后兼容地加新原语,旧实现不会因为新特性上线而崩。

下面这段展示 Server 端的初始化响应,能力声明一目了然:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2024-11-05",
    "capabilities": {
      "tools":        { "listChanged": true },
      "resources":    { "subscribe": true, "listChanged": true },
      "prompts":      { "listChanged": true },
      "logging":      {}
    },
    "serverInfo": { "name": "github-mcp", "version": "1.0.0" }
  }
}

Client 收到这份响应后,只把它声明的能力纳入可用集。如果想用 resources/subscribe,必须确认 resources.subscribe = true,否则会收到方法不存在的错误。

四、Server:能力的标准封装层

Server 是 MCP 落地的”重头戏”,所有具体能力都在这里被抽象成三种原语(Primitives):

  • Tools:可执行函数,对应 LLM 的 Function Calling 场景,调用有 JSON Schema 约束的参数;
  • Resources:可寻址的只读数据,通过 URI 标识,适合文件、文档、数据库记录等;
  • Prompts:参数化的提示词模板,由 Server 注册、由 Host 触发(如 /generateApiRoute)。

用 Python 写一个最小 MCP Server 通常不到 50 行:

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("weather-mcp")

@mcp.tool()
async def get_weather(city: str) -> str:
    """根据城市名返回当前天气。"""
    # 实际项目中对接气象 API,此处省略
    return f"{city}: 晴,25°C"

if __name__ == "__main__":
    # 本地进程通过 stdio 通信;远程部署可换 HTTP SSE
    mcp.run(transport="stdio")

效果与注意点:@mcp.tool() 的文档字符串会直接成为 LLM 看到的工具描述,决定模型在什么时候选这个工具。描述写得越具体,模型挑得越准。@mcp.resource(uri=...) 用于暴露可读数据,@mcp.prompt() 用于注册可复用的提示词模板,三者不能混用。Server 永远不应主动”推消息”打断 LLM 推理,所有调用都应等 Client 来拉。

五、传输层:STDIO 与 HTTP SSE 的取舍

MCP 把传输层做成可插拔,目前主流是两种:

传输 通信方式 部署形态 适用场景
STDIO 进程间 stdin/stdout 本地子进程 桌面应用、IDE 插件、本地开发
HTTP SSE 长连接 + 事件流 远程服务 分布式部署、云端、多租户

工程上有个反模式:把 STDIO Server 强行改造成 TCP 长连接再转发到远程。STDIO 假设 Server 与 Client 同生命周期,一旦跨网络就需要额外的鉴权、心跳与多路复用,不如直接走 HTTP SSE。工程上社区里较一致的推荐是:本地场景优先 STDIO,跨主机统一用 HTTP SSE。

到这里,Host 编排、Client 守门、Server 出力的三方协作链路就完整了。下一步要做的,是把这些能力映射到自己的业务系统里——先挑一两个高频工具做 MCP Server 验证,再逐步把数据源迁入。

常见问题(FAQ)

Q1:一个 Host 能连多少个 MCP Server?

理论上受限于 Host 的进程与上下文预算,常见做法是按业务域分组,每个 Host 维护 5–20 个活跃 Server。

Q2:MCP Server 必须用 Python 写吗?

不是。官方与社区提供 TypeScript、Python、Java、Kotlin、C#、Go、PHP、Rust 等多语言 SDK。

Q3:Client 与 Server 的连接断了会怎样?

Host 负责重连;未声明支持的能力在重连后不会自动恢复,需要重新做能力协商。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 qiqicto@qq.com 举报,一经查实,本站将立刻删除。
赞 (0)
赵其鑫的头像赵其鑫管理团队

相关推荐

返回顶部