想象一个画面:你是一家公司的老板,Agent 是你请来的“智能参谋”,每天帮你做各种决策。可参谋自己不会查天气、算数据、看股价,他得靠外部机构——气象局、交易所、内部数据库。MCP Host 是参谋身边的秘书处,负责判断“这事该找谁”;而 MCP Client,就是秘书处桌上那台贴着标签的智能总机。老板一声令下,秘书处写好转办单,总机员的职责是:拨通正确的机构、把事情说清楚、把回复原样带回来。如果占线,他得按规矩等一等再拨;如果这个机构不熟,他甚至要先确认对方还营业、还认不认账。本文就把这台总机拆开看:它怎么和机构建立连接、怎么同时管好几条专线、拨不通怎么办、和秘书处怎么分工,以及不同品牌总机的差异。
学习 MCP Client,是你从“会调大模型”走向“能造真正自主 Agent”的关键一步:所有工具调用、多服务集成和可靠通信,最后都落在这薄薄的一层客户端上。
可视化演示
本节配有交互动效(进入视口后自动加载,约 3KB)。
(Agent) MCP Client MCP Server MCP Client可视化:展示协议客户端生命周期和多Server连接管理 MCP Client可视化:展示协议客户端生命周期和多Server连接管理
角色定位
老板第一次把总机摆在桌上时,秘书处特意嘱咐:你只需要对总机说话,剩下的事不用管。这台总机的全部意义,就是充当老板与外部机构之间的“翻译和管道”。老板不必知道气象局的具体分机号,也不必纠结电话线怎么走,他只要对着总机说一句“我要北京明天的天气”,剩下的环节全部由这台机器负责衔接。
在 MCP 协议中,这个“管道”被具体化为 Client 对象。它与运行中的 MCP Server 一一对应,是协议通信的真正发起方。你可以把 MCP Client 理解为一个协议会话的代名词:它不负责思考“为什么调用”,也不负责决定“调用哪个工具”,它只负责让一次远程调用安全、准确、可追溯地完成。
MCP Client 的核心职责可以收敛为三件事:第一,能力发现,向 Server 发起 initialize 和 tools/list,弄清对方提供什么工具、每个工具接受什么参数;第二,工具调用,把 Agent 的意图封装成 tools/call 请求发出去,并检验返回结果;第三,状态维护,记录这个连接里有哪些工具、最近调用了什么、结果是否出错,这些状态是后续决策的上下文来源。
你会发现,接线员的工作从来不是替老板做决策——他负责查号码、拨电话、记本子。MCP Client 也是如此:它被设计得足够“笨”,只做协议层的事,把聪明留给 Host 和 Agent。
- 元组含义用集合符号把客户端职责收拢成三个可独立设计的功能域。
- 能力发现Discover 指初始化握手和工具列表查询,是后续一切调用的前置动作。
- 状态维护State 指消息 ID、调用历史、上下文的保存,让连接具备“记忆”。
生命周期
总机员每天上班有一套固定流程:先检查线路,报出自己的工号,和对方确认合作范围,确认无误后才会开始接活;下班时再挂断电话、合上记录本。这套“上班—上岗—干活—下班”的流程,在 MCP 协议里被称为 Client 与 Server 的连接生命周期。
MCP 协议中,Client 与 Server 的每次连接都遵循一套严格的状态序列。为什么不能省掉握手直接调用?就像你不能电话一接通就开始念订单而不先报身份一样,Server 需要知道“你是谁、协议版本是否兼容、你能处理哪些能力”,Client 也需要知道“你提供哪些能力、工具长什么样”。
技术细节上,初始化阶段 Client 发送 initialize 请求,带上协议版本、客户端能力和客户端信息;Server 回复协议版本、服务端能力和服务器信息。随后 Client 发送 notifications/initialized 通知,双方进入 ready 状态。运行期可以收发 tools/list、tools/call 等消息。最后是关闭阶段,Host 决定不再使用该连接,Client 清理本地会话状态和未完成请求。
就像下班前必须挂断电话、合上记录本,一次不完整的关闭会留下占着的线路。在 MCP 开发里,忘记关闭 Client 连接是最常见的资源泄漏根源之一,尤其在长驻服务中,每个未关闭的会话都会持续占用内存和网络句柄。
- 初始状态init 表示连接尚未建立,Client 准备发起握手,称为初始化。
- 就绪状态ready 表示握手完成、能力协商通过,双方可以交换业务消息。
- 运行状态run 是工具调用最活跃的阶段,所有 tools/call 都发生在这里。
- 关闭状态close 负责释放资源,把会话状态归档或丢弃。
多Server管理
桌上的电话不止一部,气象局、交易所、数据库各占一条专线。接线员心里有本通讯录,哪条线对应哪个机构,绝不能串线——不能把天气查询拨到交易所去。更关键的是,每条专线的通话记录是分开记的,不能混在一起。
一个 Agent 要提供有用能力,几乎总要连接多个 Server:一个做联网搜索、一个访问公司数据库、一个调用内部业务 API。有些初学者以为“连接一个 Server 就够了”,但真实场景中,一个工具调用动辄需要三四个外部服务协同。
工程上的标准做法是:每个 Server 连接都使用独立的 Client 会话,状态绝不混用。再用一个会话注册表管理这些会话,key 是 server 标识,value 是会话对象。调用前先查表拿到正确的会话,连接不可用时移除条目并允许重建。这样既保证了路由正确,也隔离了故障——某个 Server 挂了不会拖垮其他连接。
接线员最怕串线,MCP Client 管理多 Server 时最怕会话串扰。如果你在代码里让两个 Server 共用同一个 Client 对象,就会发现消息 ID 冲突、工具清单互相覆盖——这就像把两家机构的电话打到彼此的记录本上,场面会彻底失控。
- 映射函数f 表示从 Server 标识到 Client 会话的对应关系,是路由的核心。
- 映射对集合元组 (S_i, C_i) 表示第 i 个 Server 与其专属会话的成对关系。
- 下标范围i 从 1 到 N,说明系统支持任意多个 Server,只需新增映射即可扩展。
工具调用
老板说“我要北京天气”,秘书处写一张转办单,总机员把它翻译成标准格式报给对方,对方回复后再原样带回来。这里有一个细节:转办单上必须有一个编号,机构的回复上也要带同一个编号,总机员才能确认这是那张单子的回执。
MCP 协议里的“标准格式”就是 JSON-RPC 2.0 消息。一次完整的工具调用分四步:工具发现、参数构建、发送请求、校验响应。Client 先通过 tools/list 拿到工具清单,包括工具名称和参数 Schema;Agent 侧基于 Schema 补全参数后,Client 构造 tools/call 请求,包含唯一 id、方法名和 params;Server 返回带同一 id 的响应。
Client 在收到响应时要做的第一件事不是解析业务数据,而是校验 id 是否与某个未完成请求匹配。这个匹配机制决定了并发能力:多个工具调用可以同时在空中飞行,谁回来就发给谁。响应还带 isError 标记,即使是业务错误也会以正常消息返回,Client 只需如实上报给 Host。
总机员拿着编号去对账,Client 拿着 id 去对消息。如果你在封装 SDK 时忽略 id 配对,就会出现响应错乱、超时误判——就像把张三的订单回执交给了李四,客户体验会瞬间崩塌。
- 请求结构请求由请求 ID、方法名和参数三部分组成,m 通常为 tools/call。
- 响应结构响应由请求 ID 和结果组成,r 可以是业务数据或错误信息。
- 配对条件只有请求 ID 等于响应 ID,这次调用才算对齐,否则视为无关消息。
错误重试
也有拨不通的时候:占线、无人接、说到一半断线。老练的接线员从不立刻重拨,也不无限重拨。他会先看是哪种失败——是号码不存在(协议错),还是对方忙(资源紧张),还是对方接了但信号断了(连接中断),然后按场景决定要不要重试。
MCP Client 同样要把错误分成三类:连接类错误(握手失败、连接中断)、协议类错误(非法 JSON-RPC、超时)、业务类错误(工具执行失败返回 error)。处理手段包括:给建连和读写设置超时时间;失败后只重试有限次数;每次重试等待时间按指数规律增长,避免把服务打爆。
更 subtle 的一点是幂等。像“转账”“创建订单”这类有副作用的操作,重放时必须保证只执行一次。办法是复用请求 id 或业务 token,Server 端识别到同一 id 就返回上次结果,而不是再执行一遍。MCP 的 JSON-RPC 结构中,请求 id 天然适合承担这个角色。
重拨的智慧在于:等得够久,又不至于让机构被电话打爆。没有退避的重试是“雪崩发生器”——一旦 Server 出现过载,所有 Client 同时立刻重试,瞬间把 Server 彻底压垮;有了指数退避,大家自动错开节奏,Server 才有机会缓过来。
- 基础延迟D_0 是第一次重试前的基准等待时间,比如 0.2 秒。
- 指数增长每次失败后等待时间翻倍,2 的 n-1 次方让重试节奏越来越慢。
- 封顶保护min 函数把等待时间限制在 D_max 内,避免最坏情况下等上几年。
与Host协作
秘书处和总机员各司其职:前者决定找谁、问什么,后者负责打通线路、原样传话。秘书处不会冲到机房里去拨号,总机员也绝不会替老板拍板“这事不用问了”——一旦越权,整个办公秩序就乱了。
在 MCP 架构里,Host 与 Client 的关系正是这种分工。Host 是 Agent 应用的核心容器,掌握着任务编排、模型调度和用户交互;Client 只是 Host 手下一个“外卖骑手”,负责把任务送到 Server 再取回来。两者通过回调协作,职责边界非常清晰。
技术实现上,Host 负责高层编排:决定调用哪个工具、什么时候创建新连接、收到结果后下一步做什么;Client 负责协议细节:initialize 握手、消息编码解码、重试策略、id 配对,并通过回调把结果和通知交还给 Host。Host 依赖 Client 的稳定传输,Client 不感知 Host 的业务意图。
总机如果擅自替老板回答或者替秘书处做决定,那就越权了。MCP 里的 Client 如果试图介入业务编排,就会让职责混乱、协议层与应用层耦合,最终难以测试和维护。记住这句话:Host 是大脑,Client 是手脚。
- 意图出发A 到 H,Agent 把“我想知道天气”的意图交给 Host 编排。
- 选中工具H 到 C,Host 决定调用哪个工具,把调用指令交给 Client。
- 远程执行C 到 S,Client 将请求封装成协议消息发给远端 Server 执行。
- 结果返回S 到 C、C 到 H、H 到 A,结果沿原链路逐层回传,最终交还 Agent。
SDK对比
市面上的总机品牌众多,功能都能打通电话,但操作台布局、配套培训、扩容方案各不相同。有的总机按键少、易上手,适合初创团队;有的总机扩展槽多、支持并发线路,适合大企业;选型从来不是“哪个最好”,而是“哪个最适合你的团队”。
MCP 生态同样如此,官方 SDK 已经覆盖 Python、TypeScript、Java/Kotlin、Ruby、C# 等主流语言,还有社区维护的 Go、Rust 等实现。它们遵循同一份协议规范,所以 Server 侧互操作没有问题,差异集中在开发体验和运行特性上。
选型时主要看三个维度:传输层支持(是否同时支持 stdio、HTTP+SSE、Streamable HTTP);异步模型(Python 的 asyncio、TypeScript 的回调与响应式流、Java 的阻塞与响应式);能力完善度(工具发现、自动重连、对 notifications 和采样的支持)。AI Agent 原型常用 Python SDK,Web 集成偏爱 TypeScript,企业级系统倾向 Java。
选总机不是越贵越好,而是看秘书处的人会不会用、设备稳不稳。选 MCP SDK 也不是越流行越好:如果你的 Agent 跑在 Node 服务里,硬塞一个 Python SDK 就非常别扭;如果你的团队全是 Java 工程师,为了快速原型引入不熟悉的语言栈,后续维护成本会远高于节省的那点开发时间。
- 生态成熟度E 代表文档质量、社区活跃度和版本稳定性。
- 类型与异步T 代表类型系统的严格程度和异步模型的契合度。
- 性能表现P 代表吞吐、延迟和资源占用等可量化指标。
AI 应用场景
智能客服 Agent 接入多业务系统
阶段:工具调用与多 Server 连接管理
解决的问题:传统客服系统每接入一个数据源(订单库、CRM、物流平台)就要写一套对接代码,业务流程写死,后期加一个查询维度就要改代码。用 MCP Client 管理多个 Server 会话后,每个业务系统都变成标准 MCP Server,Agent 通过统一工具接口查询,新增系统只需添加一条 Server 注册记录。
具体案例:某电商客服 Agent 同时连接订单管理系统、物流查询服务和退款接口三个 MCP Server。Host 根据用户问题编排调用链:先查订单、再查物流、必要时发起退款申请。每个 Server 有独立 Client 会话,请求 id 不冲突,任一系统故障不影响其他查询。
数据分析 Agent 的容错查询
阶段:错误重试与超时控制
解决的问题:数据分析 Agent 经常要调用外部 BI 服务的慢查询接口,回应时间不稳定,传统同步调用遇到超时就直接报错,用户体验差。MCP Client 内置指数退避重试逻辑,配合超时控制,把不稳定服务变成可用服务。
具体案例:某数据分析工具用 Python MCP SDK 连接内部 BI Server,执行 SQL 类工具调用。当 BI 服务负载高时,Client 自动按 0.2s、0.4s、0.8s 间隔重试,最多 3 次;对于聚合统计这类幂等操作,复用请求 id 防止重复计算导致数据翻倍。
代码助手 Agent 的本地工具链
阶段:SDK 选型与生命周期管理
解决的问题:IDE 里的代码助手 Agent 需要调用本地文件检索、git 状态查询等功能。通过 stdio 传输与本地 MCP Server 通信最安全,不需要开网络端口。生命周期管理在这里很关键:编辑会话结束就要主动关闭 Client 连接,避免长驻服务内存泄漏。
具体案例:某 IDE 插件用 TypeScript MCP SDK 创建 Client 连接本地代码分析进程。初始化时握手协商版本,运行期执行 grep 文件工具,用户关闭编辑器时触发优雅关闭:先结束消息处理,再断开传输,最后清空会话状态。
Python 演示
import time class MCPSession: def __init__(self, server_id, endpoint): self.server_id = server_id self.endpoint = endpoint self.connected = False self.tools = {} def initialize(self, server_meta): """握手:登记工具表,进入就绪状态。""" if not isinstance(server_meta, dict) or "tools" not in server_meta: raise ValueError("invalid server metadata") self.tools = server_meta["tools"] self.connected = True return {"status": "ok", "tools": sorted(self.tools)} def call_tool(self, name, args): """执行工具调用,失败时抛出异常。""" if not self.connected: raise ConnectionError("session not initialized") if name not in self.tools: raise KeyError("tool not found: " + name) return self.tools[name](args) def close(self): """优雅关闭:清空会话状态。""" self.connected = False self.tools = {} class MCPClientManager: def __init__(self): self.sessions = {} def add_server(self, server_id, endpoint, server_meta): """新增一个 Server 连接,并完成初始化握手。""" session = MCPSession(server_id, endpoint) result = session.initialize(server_meta) self.sessions[server_id] = session return result def active_sessions(self): """返回当前仍处于连接状态的会话列表。""" return [sid for sid, s in self.sessions.items() if s.connected] def call_with_retry(self, server_id, tool, args, max_retries=3, base_delay=0.2, max_delay=2.0): """带指数退避的工具调用。""" session = self.sessions.get(server_id) if session is None: raise KeyError("no such server: " + server_id) last_exc = None for attempt in range(max_retries + 1): try: return session.call_tool(tool, args) except Exception as exc: last_exc = exc if attempt == max_retries: break delay = min(base_delay * (2 ** attempt), max_delay) time.sleep(delay) raise last_exc def close(self): """关闭所有会话。""" for session in self.sessions.values(): session.close() self.sessions.clear() def flaky_tool(args): raise RuntimeError("service busy") def main(): calc_meta = { "tools": { "add": lambda args: args["a"] + args["b"], "mul": lambda args: args["a"] * args["b"], "flaky": flaky_tool, } } weather_meta = { "tools": { "query": lambda args: {"city": args["city"], "temp": 22}, } } manager = MCPClientManager() print(manager.add_server("calc", "stdio://calc", calc_meta)) print(manager.add_server("weather", "http://weather", weather_meta)) print(manager.call_with_retry("calc", "add", {"a": 3, "b": 4})) print(manager.call_with_retry("weather", "query", {"city": "Beijing"})) try: manager.call_with_retry("calc", "flaky", {}, max_retries=1, base_delay=0.01) except RuntimeError as exc: print("retry failed:", exc) print("active:", manager.active_sessions()) manager.close() if __name__ == "__main__": main()
session.initialize(server_meta)模拟 MCP 初始化握手:登记工具表,把 connected 置为 True,对应现实中的 initialize 请求。self.sessions[server_id] = session用字典作为会话注册表,这就是文章里“多 Server 管理”的落点。session.call_tool(tool, args)根据名字动态分发到具体工具函数,对应 JSON-RPC 的 tools/call。delay = min(base_delay * (2 ** attempt), max_delay)指数退避公式的代码实现,等待时间按翻倍增长并封顶。manager.call_with_retry("calc", "add", {"a": 3, "b": 4})对外暴露的容错调用入口,失败会自动重试。manager.close()遍历所有会话执行优雅关闭,对应生命周期里的 close 阶段。
常见误区
误区我以为 MCP Client 是一个需要单独部署的微服务,就像启动一个 HTTP 服务器那样。实际上它只是一个 SDK 库里的对象,我找遍整个项目也没找到可以启动的入口。
正解MCP Client 通常以库对象的形式存在于 Host 进程中,由代码创建和销毁。你可以把它想成总机设备——它不是一间独立的机构,而是秘书处桌上的一台机器。它的生命周期依附于 Host,进程退出时所有连接也随之消亡。
为何常见:因为日常开发中习惯了“服务 = 独立进程 + 端口”的心智模型,遇到协议客户端时也自然往服务方向联想。
误区我觉得只要创建一个 MCP Client,然后把多个 Server 的地址都传进去,它自然能帮我维护好多条连接。这样代码最省事。
正解一个 Client 对象对应一条到特定 Server 的连接,它有独立的握手状态、能力协商结果和消息 ID 空间。多 Server 需要多个独立会话,再用注册表统一管理——就像一条电话线不能同时接通气象局和交易所,每打一个电话都是独立的线路。
为何常见:网络编程里常有“一个客户端类连多个服务端”的模式(比如数据库连接池),容易把这种经验套用到 MCP 上。
误区工具调用失败了,最自然的想法是马上再调一次。如果还失败就再调一次,总共试十次。结果服务反而更卡了。
正解没有退避的密集重试会让过载的 Server 雪上加霜。正确做法是有限次重试 + 指数退避 + 抖动,让等待间隔从 0.2s、0.4s、0.8s 逐渐拉长。接线员不会疯狂拨同一个占线号码,他会等对方缓过来再拨。
为何常见:人面对失败的第一反应是“再来一次”,线性思维让人忽略了分布式系统里的相互影响。
误区MCP 有三个角色:Host、Client、Server,我觉得 Host 就是 Client 的另一个名字,反正都是 Agent 侧的东西,写代码时混着用。
正解Host 是 Agent 应用的宿主环境,负责业务编排和生命周期决策;Client 是协议会话的实现者,负责消息收发和状态维护。用秘书处和总机的比喻来想:Host 决定打给谁,Client 负责把电话打通。混用会导致职责混乱、测试困难。
为何常见:在官方文档里 Host 和 Client 都出现在“Agent 侧”,初读时容易把整个 Agent 侧视为一个整体,忽略内部边界。
误区反正都是实现同一个协议,用 Python 或 TypeScript 写出来的 Client 应该完全等价,选一个顺手的就行。
正解协议消息是互通的,但 SDK 在传输层支持、异步模型、自动重连等能力上差异很大。比如某些 SDK 对 Streamable HTTP 支持还不完整,某些 SDK 的 stdio 传输更稳定。选型要看成色,而不是只看语言名。
为何常见:初学者容易把“协议统一”误解为“实现统一”,就像认为所有路由器都按同一标准造就能随便买一台,忽略了吞吐量和稳定性差异。
面试题
Q1. MCP Client 在 MCP 架构中最核心的职责是什么?
- A.负责决策并编排整个任务流程
- B.负责与远端 Server 建立协议会话并收发消息← 正确答案
- C.负责存储大模型的权重与训练参数
- D.负责渲染前端界面并处理用户点击
答案:B。MCP Client 的本质是协议通道,负责握手、消息发送和响应配对。决策编排是 Host 的职责,存储权重和渲染界面更是与 MCP 无关。就像接线员只负责接通和传话,不替老板决定该找谁。
Q2. MCP Client 与 Server 建立连接时,第一步发生的动作是?
- A.客户端直接调用 tools/list 获取工具列表
- B.客户端发送 initialize 请求进行握手← 正确答案
- C.服务端主动推送工具到所有已注册客户端
- D.客户端建立数据库连接并执行建表语句
答案:B。MCP 协议要求先发送 initialize 请求完成握手,确认协议版本和能力后再进入就绪状态。tools/list 必须等握手完成后才能使用,服务端也不会主动推送工具列表。就像打电话第一句要报身份,而不是直接开始念订单。
Q3. 下列哪个属于 MCP Client 运行期的消息处理职责?
- A.向 Server 发送 tools/call 并校验响应 ID← 正确答案
- B.训练一个新的工具选择模型
- C.修改 Server 端工具的函数体实现
- D.为 Agent 生成用户界面按钮文案
答案:A。运行期 Client 要做的事是构造请求、发送消息、按 ID 配对校验响应。训练模型是 Agent 侧的事,修改 Server 端代码和生成界面文案根本不发生在 Client 的职责范围内。总机员只负责传话和对账,不负责改对方答复内容。
Q4. 一个 Agent 需要连接多个 MCP Server,正确的做法包括?
- A.为每个 Server 创建独立的 Client 会话实例← 正确答案
- B.用会话注册表维护 Server 名称到会话的映射← 正确答案
- C.让所有请求共享同一个会话并手动修改目标地址
- D.隔离各会话状态和消息 ID 空间← 正确答案
答案:ABD。多 Server 管理的核心是“独立会话 + 注册表路由 + 状态隔离”。共享一个会话并手动改地址会导致消息 ID 冲突和工具清单混淆,是错误的做法。这就像一条电话线不能同时接通多个机构,每条线都要独立管理。
Q5. 重试机制中“指数退避”的核心思想是?
- A.每次重试的等待时间按固定值递增
- B.每次重试的等待时间按指数规律增大← 正确答案
- C.所有重试都在同一次循环中立即完成
- D.失败次数越多,重试间隔应当越短
答案:B。指数退避让等待时间按 0.2s、0.4s、0.8s 翻倍增长,既给服务恢复时间,又避免雪崩。固定值递增只是等距重试,立即完成和越挫越勇的间隔方向都与退避相反。这就像接线员发现占线后会等更久再拨,而不是越拨越勤。
Q6. 客户端重放一条 tools/call 请求时,如何避免 Server 端重复执行副作用?
- A.使用不同的请求 ID 发送两条相同消息
- B.复用原请求 ID 并配合 Server 端的幂等处理← 正确答案
- C.直接关闭连接后重新初始化一个新会话
- D.把请求方法从 tools/call 改成纯通知类型
答案:B。幂等重放的关键是让 Server 识别“这条消息我处理过”。复用原请求 ID,Server 就能返回上次结果而不重复执行。换新 ID 等于新请求,关闭连接和改成通知都解决不了重复执行问题。好比同一张转办单不能换编号再送一次。
Q7. 关于 Host 与 Client 的职责划分,正确的是?
- A.Host 负责编排任务并决定调用哪些工具← 正确答案
- B.Client 负责维护与 Server 的协议会话← 正确答案
- C.Host 可以绕过 Client 直接与 Server 通信
- D.Client 通过回调把结果交还给 Host← 正确答案
答案:ABD。Host 是决策层,Client 是传输层。Host 不能绕过 Client 直连 Server,否则就破坏了协议封装;Client 通过回调把结果和通知交给 Host,保持单向依赖。就像秘书处不能抢过电话线自己喊话,总机员也不能替秘书处做决定。
Q8. 不同语言 MCP SDK 的主要差异体现在?
- A.异步模型与内置传输协议的支持度不同← 正确答案
- B.协议消息格式完全不同导致无法互通
- C.只有 Python SDK 能连接远程 HTTP Server
- D.所有 SDK 的 API 形态完全一致
答案:A。SDK 差异集中在异步模型、传输层支持(stdio、HTTP+SSE、Streamable HTTP)和能力完善度。协议消息格式是统一的,否则无法互操作;API 形态也各不相同。就像不同品牌总机按键布局不同,但电话线标准是一致的。
Q9. MCP 协议中一次完整工具调用涉及哪些要素?
- A.唯一的请求 ID 与工具名称和参数← 正确答案
- B.请求与响应的 ID 配对校验← 正确答案
- C.调用结果以及是否出错的错误标记← 正确答案
- D.工具内部训练数据集的版本号
答案:ABC。工具调用三要素:请求结构(id、方法名、参数)、响应配对(同 id 返回)、结果标记(isError 区分业务错误)。训练数据集的版本号与协议调用无关。这就像一张转办单必须有编号、内容、回执,才能算一次完整通联。
Q10. 关闭 MCP Client 连接时的正确做法是?
- A.直接让程序退出,靠操作系统回收资源
- B.先结束会话消息再关闭传输并清理状态← 正确答案
- C.只在连接池空闲时关闭否则会造成死锁
- D.断网后立刻丢弃本地保存的全部历史记录
答案:B。优雅关闭要按顺序执行:停止接收新消息、关闭底层传输、清理本地会话状态和未完成请求。直接退出虽然进程结束会回收内存,但依赖宿主环境不优雅;MCP 没有“连接池空闲才关闭”的约束。下班前挂断电话、合上记录本,才算完整收尾。