02Bread MCP · 第 3 章
总进度 12 / 33

最简 MCP client + 完整握手

ch01 的测试脚本已经能通信,但每次使用都要处理启动进程、握手、请求编号和读取结果。把这些步骤集中到一个类里,调用工具时就不用反复写同样的代码。

2026-09-28约 40 分钟120 行代码难度 ★★

如果想获取全套课程资料,请关注微信公众号 「AI面包君」,回复 「课程资料」 即可领取。

1. 把连接和收发整理成 MCPClient

ch01 的测试脚本已经能通信,但每次使用都要处理启动进程、握手、请求编号和读取结果。把这些步骤集中到一个类里,调用工具时就不用反复写同样的代码。

这一章建立 MCPClient,让调用方可以这样使用:

with MCPClient([sys.executable, "server.py"]) as client:
    tools = client.list_tools()
    result = client.call_tool("echo", text="hello")

后面 ch04 接入 Bread Agent 时,会继续使用这个类。Agent 只需调用它的方法,由它负责把请求送到 MCP 服务端。

文件结构:

ch02_min_client/
├── server.py    # 跟 ch01 一样的 echo server,搬过来让本章独立可跑
├── client.py    # 本章的核心
└── README.md
<!-- bread-visual:start -->

MCPClient:把协议细节藏进一个类

图解: with 块负责连接和清理,业务代码只调用高层方法。 自动递增的请求 id,帮助 client 把每次请求和响应对应起来。

<!-- bread-visual:end -->

2. 跑起来

cd ch02_min_client
python client.py

预期输出:

已连接 server: {'name': 'bread-mcp-echo', 'version': '0.1.0'}
server 能力: {'tools': {}}

--- 工具列表 ---
  echo: 把传入的字符串原样回声出来,前面加上 'echo: ' 前缀。

--- 调用 echo ---
  结果: echo: 你好 MCP

--- 再调一次 ---
  结果: echo: Hello again

image-20260610211346727

检查输出是否依次展示握手、列出工具和工具调用结果,并确认程序结束后子进程关闭。这几步都正常,才说明连接的建立和清理连起来了。


<!-- bread-practice:start -->

实操画面对照

发现 echo 工具并调用两次

实操运行记录: 实际执行课程副本的 client.py;展示原始输出第 1–11 行。发现 echo 工具并调用两次。这是实测日志的排版图,并非 Windows 原生终端截图;模型回复可能随运行变化。

<!-- bread-practice:end -->

3. 对照代码看实现(client.py)

第 1 段:构造函数 + 状态

class MCPClient:
    def __init__(self, server_command: list[str]):
        self.server_command = server_command       # 比如 ["python", "server.py"]
        self.proc: subprocess.Popen | None = None  # 子进程句柄
        self._next_id = 1                          # 自动 id 计数器
        self.server_info: dict = {}                # 握手后填入
        self.server_capabilities: dict = {}

试读到这里 · 后续内容已封存

关注公众号,继续把这章学完

在「AI面包君」发送关键词「学习AI」拿到口令。验证一次,这个浏览器就能继续阅读全部课程。