知识点思维导图
37 个知识节点
LangChain(03) - MCP:通过进程边界接入 Tool
读完后,你应能完成以下任务:
- 绘制“Agent(06) - MCP:可跨进程调用的 Tool / 本篇定位”的关键对象与数据流,解释“这是工具系统从“项目内函数”走向“可复用外部工具服务”的篇章。”,并用源码位置、日志或 Trace 标注证据。
- 为“Agent(06) - MCP:可跨进程调用的 Tool / 核心拆解”设计正常与异常输入,验证“普通 Tool 往往是应用内函数,生命周期跟应用绑在一起。”,输出首个偏差位置与回归测试结果。
- 实现“Agent(06) - MCP:可跨进程调用的 Tool / 工程链路”的最小代码或配置,检验“启动 MCP Server。”,输出命令、结果与 Diff,并说明不适用边界。
一、先建立全局:MCP:通过进程边界接入 Tool 是什么?
MCP(Model Context Protocol)不是另一种 Prompt,也不是把函数代码复制到当前进程。它定义了客户端与 MCP Server 之间发现工具、传入参数和接收结果的协议。LangChain 通过 langchain-mcp-adapters 把远端发现到的 MCP 工具转换成 LangChain Tool,因此 Agent 可以把它们和本地 Tool 一起使用。
理解“MCP:可跨进程调用的 Tool”,先要把标题中的对象放进同一条处理链:它接收什么输入,经过哪些状态变化,最终用什么证据判断结果。下表不另造概念,只把作者正文已经解释的章节按依赖顺序连起来。
“MCP:可跨进程调用的 Tool”的第一个核心判断是:这是工具系统从“项目内函数”走向“可复用外部工具服务”的篇章。。先弄清这个判断中的对象和输入输出,后面的实现、故障和验收才有共同语境。
| 顺序 | 章节 | 读完本节应抓住的结论 |
|---|---|---|
| 1 | 本篇定位 | 这是工具系统从“项目内函数”走向“可复用外部工具服务”的篇章。 |
| 2 | 核心拆解 | 普通 Tool 往往是应用内函数,生命周期跟应用绑在一起。 |
| 3 | 工程链路 | 启动 MCP Server。 |
| 4 | 落地建议 | 为每个 MCP Server 标记权限等级,避免所有工具混在一个大列表里。 |
| 5 | 常见坑 | 协议只是通道,策略还得自己做。 |
| 6 | 和已有主线的关系 | 28 的工具调用是函数级; |
1.1 核心对象之间怎样衔接
flowchart LR
S1["本篇定位"] --> S2
S2["核心拆解"] --> S3
S3["工程链路"] --> S4
S4["落地建议"] --> S5
S5["常见坑"]
这张图只表达本文的讲解顺序,不替代正文机制。判断“MCP:可跨进程调用的 Tool”是否真正掌握,需要能从最后一个结果沿图回到前面每个章节的输入、状态变化和证据。
1.2 再看失败:问题最早会出现在哪一步?
在“MCP:可跨进程调用的 Tool”的对象和顺序已经明确后,再看可观察的失败:路径或命令直通执行、工具结果跨会话泄漏、循环失控或重试重复副作用。定位时不从最后一条错误猜原因,而是沿上图找第一个偏离正文结论的节点。
二、MCP的学习定位与边界
这是工具系统从“项目内函数”走向“可复用外部工具服务”的篇章。
三、MCP的真实应用场景
你在一个 Agent 项目里写了浏览器工具、地图工具、数据库工具。 换一个 Agent 项目,又要重新接一遍。 MCP 的价值就是把这些工具从单个应用里抽出来, 变成独立进程提供的标准能力, 让不同客户端都能发现和调用。
四、MCP的核心对象与机制
在 LangChain 应用里,最常见的两种传输方式是:
| 传输 | 调用边界 | 适用场景 |
|---|---|---|
stdio |
LangChain 进程启动本地 MCP Server 子进程,通过标准输入输出交换消息 | 本地文件、开发工具和桌面自动化;不需要开放网络端口 |
| Streamable HTTP | LangChain 作为客户端访问远程 MCP Server 的 HTTP 端点 | 独立部署、跨机器调用和统一鉴权;需要处理网络、超时与权限 |
langchain-mcp-adapters 的 MultiServerMCPClient 可以按传输配置连接多个 MCP Server,再用 get_tools() 得到可交给 LangChain Agent 的工具集合。适配器只负责协议转换,不会替你放宽 MCP Server 的权限;每个工具仍要做白名单、参数校验和审计。
示例中的本地进程和远程 URL 只是连接方式示意,不能直接把未知服务加入生产 Agent。连接前要确认 Server 身份、工具清单、网络出口和凭证范围。
- 普通 Tool 往往是应用内函数,生命周期跟应用绑在一起。MCP Server 是独立进程,负责暴露 tools、resources、prompts 等能力。
- MCP Client 负责和 Server 建连接、发现工具 schema、发起调用、接收结果。模型仍然只提出调用意图,执行边界仍在客户端和服务端控制。
- MCP 解决的是工具分发和复用问题,不自动解决权限、安全和质量问题。Server 暴露了危险工具,客户端照样要拦。
五、MCP的工程链路
- 启动 MCP Server。
- 客户端连接并拉取工具列表。
- 模型根据工具描述提出调用。
- 客户端校验后转发给 MCP Server。
- Server 执行并返回结构化结果。
- 客户端把结果回填给模型。
六、MCP的落地建议
- 把跨项目复用的能力做成 MCP,比如浏览器、文件系统、企业内部 API。
- 为每个 MCP Server 标记权限等级,避免所有工具混在一个大列表里。
- 调用日志要记录到客户端侧,方便和模型 trace 对齐。
七、MCP的常见故障与误区
- 以为接了 MCP 就安全。协议只是通道,策略还得自己做。
- 一次暴露太多工具,模型选择困难。
- Server 返回非结构化大文本,客户端难以稳定处理。
八、MCP在学习路线中的位置
28 的工具调用是函数级; 56 把工具能力提升到进程级和生态级,是 进阶-多Agent与MCP工程化 的前置知识。
九、MCP的核心结论
MCP 可以理解成跨进程的工具协议:Server 暴露工具,Client 发现和调用,模型只负责选择。它的价值是复用和标准化,不是替代权限系统。真正上线仍要做工具分级、调用校验和 trace。
十、可运行实验:MCP 生命周期与错误边界
真实 MCP 通过 stdio 或 Streamable HTTP 交换协议消息。 这个沙盒用内存消息复现相同的生命周期约束,不启动本地进程,也不需要模型凭据。
"""用内存消息验证 MCP 初始化、能力发现和工具调用边界。"""
from __future__ import annotations
from dataclasses import dataclass
from typing import Any
@dataclass(slots=True)
class McpServer:
"""保存 MCP Server 的初始化状态并处理最小协议消息。"""
# 客户端完成 initialize 后才允许发现和调用能力。
initialized: bool = False
def handle(self, request: dict[str, Any]) -> dict[str, Any]:
"""处理一条协议请求;request 包含 method、id 和可选 params。"""
# 当前请求的协议方法名。
method = request.get("method")
# 当前请求标识,用于客户端关联响应。
request_id = request.get("id")
if method == "initialize":
self.initialized = True
return {"id": request_id, "result": {"protocolVersion": "demo-v1", "capabilities": {"tools": {}}}}
if not self.initialized:
return {"id": request_id, "error": {"code": -32002, "message": "server not initialized"}}
if method == "tools/list":
return {"id": request_id, "result": {"tools": [{"name": "echo", "inputSchema": {"type": "object"}}]}}
if method == "tools/call":
# 工具调用参数必须由 Server 再次校验。
params = request.get("params", {})
if params.get("name") != "echo":
return {"id": request_id, "error": {"code": -32601, "message": "unknown tool"}}
# echo 工具的文本参数。
text_value = str(params.get("arguments", {}).get("text", ""))
return {"id": request_id, "result": {"content": [{"type": "text", "text": text_value}]}}
return {"id": request_id, "error": {"code": -32601, "message": "method not found"}}
def main() -> None:
"""回放错误调用、初始化、发现、成功调用和未知工具。"""
# 独立 Server 实例保存本次连接生命周期。
server = McpServer()
# 客户端发送的协议请求序列。
requests = [
{"id": 1, "method": "tools/list"},
{"id": 2, "method": "initialize", "params": {"protocolVersion": "demo-v1"}},
{"id": 3, "method": "tools/list"},
{"id": 4, "method": "tools/call", "params": {"name": "echo", "arguments": {"text": "hello"}}},
{"id": 5, "method": "tools/call", "params": {"name": "delete_all", "arguments": {}}},
]
for request in requests:
print(server.handle(request))
if __name__ == "__main__":
main()
预期请求 1 返回 server not initialized,
请求 2 完成能力协商,
请求 3 发现 echo,
请求 4 返回 hello,
请求 5 返回 unknown tool。
客户端不能在 initialize 前假设能力,
Server 也不能因客户端已发现 Schema 而跳过调用时校验。
十一、动手验证:先跑通 MCP:可跨进程调用的 Tool,再改变一个变量
前面的章节已经建立问题、概念和机制。现在把“MCP:可跨进程调用的 Tool”放进同一套基线中运行;本节不再引入新术语,只验证前文结论能否被复现。
11.1 基线与候选只允许一个变量不同
验证“MCP:可跨进程调用的 Tool”时,先固定工具 Schema、调用身份、允许资源、畸形参数、超时、重复请求和最大步骤。候选方案只能改变本次要验证的变量;如果同时更换数据、依赖和配置,即使结果改善,也不能知道是哪一项产生作用。
执行“MCP:可跨进程调用的 Tool”时,动作是:保存模型提议,经 Schema 与授权校验后执行工具,并回放拒绝、超时和恢复路径。原始结果不能只保留截图或汇总分数,必须同步保存:模型提议、参数校验、授权决定、幂等键、工具结果、状态迁移和 Trace,使下一次复查可以在同一输入上重放。
| 实验要素 | 本文要求 |
|---|---|
| 固定条件 | 工具 Schema、调用身份、允许资源、畸形参数、超时、重复请求和最大步骤 |
| 唯一变量 | 本次候选方案与基线之间的一项明确差异 |
| 原始证据 | 模型提议、参数校验、授权决定、幂等键、工具结果、状态迁移和 Trace |
| 通过阈值 | 模型只提议,代码控制执行与停止;越权输入无副作用,重复请求不重复写入 |
| 立即停止 | 路径或命令直通执行、工具结果跨会话泄漏、循环失控或重试重复副作用 |
11.2 执行前先排除不可比较条件
“MCP:可跨进程调用的 Tool”开始前先确认下面四项;任一项不成立,都应先修复实验条件,而不是解释结果。
- 基线能够在“MCP:可跨进程调用的 Tool”的当前环境重复运行。
- 候选只改变一个与“MCP:可跨进程调用的 Tool”结论直接相关的条件。
- “MCP:可跨进程调用的 Tool”的基线和候选使用同一批输入、同一版本依赖与同一通过阈值。
- “MCP:可跨进程调用的 Tool”的原始输出和失败现场不会被重试、格式化或汇总覆盖。
11.3 执行后先核对证据完整性
结果出来后先检查证据,再讨论“MCP:可跨进程调用的 Tool”是否通过。缺少中间状态时,最终输出只能说明现象,不能证明机制。
| 检查项 | 当前文章的判定 |
|---|---|
| 输入可追溯 | 工具 Schema、调用身份、允许资源、畸形参数、超时、重复请求和最大步骤 |
| 过程可回放 | 保存模型提议,经 Schema 与授权校验后执行工具,并回放拒绝、超时和恢复路径 |
| 结果可审计 | 模型提议、参数校验、授权决定、幂等键、工具结果、状态迁移和 Trace |
“MCP:可跨进程调用的 Tool”的一次合格基线对照按以下顺序执行:
- 保存“MCP:可跨进程调用的 Tool”基线版本及输入摘要,确认基线本身可以重复运行。
- 写下“MCP:可跨进程调用的 Tool”候选方案唯一变化的变量,以及它预期影响的指标。
- 在同一环境执行“MCP:可跨进程调用的 Tool”:保存模型提议,经 Schema 与授权校验后执行工具,并回放拒绝、超时和恢复路径。
- 为“MCP:可跨进程调用的 Tool”保存:模型提议、参数校验、授权决定、幂等键、工具结果、状态迁移和 Trace。
- 使用“MCP:可跨进程调用的 Tool”预登记条件判断:模型只提议,代码控制执行与停止;越权输入无副作用,重复请求不重复写入。
- 如果“MCP:可跨进程调用的 Tool”未通过,不修改第二个变量,先恢复基线并保留失败现场。
十二、用一张矩阵验证 MCP:可跨进程调用的 Tool 的关键结论
矩阵按正文顺序列出“MCP:可跨进程调用的 Tool”的结论。一次实验只选择一行,只改变这一行对应的条件;不要把多行合并成一个无法归因的大实验。
| 正文章节 | 已解释的结论 | 本轮唯一变量 | 必须保存的证据 |
|---|---|---|---|
| 本篇定位 | 这是工具系统从“项目内函数”走向“可复用外部工具服务”的篇章。 | 只改变与“本篇定位”相关的条件 | 模型提议、参数校验、授权决定、幂等键、工具结果、状态迁移和 Trace |
| 核心拆解 | 普通 Tool 往往是应用内函数,生命周期跟应用绑在一起。 | 只改变与“核心拆解”相关的条件 | 模型提议、参数校验、授权决定、幂等键、工具结果、状态迁移和 Trace |
| 工程链路 | 启动 MCP Server。 | 只改变与“工程链路”相关的条件 | 模型提议、参数校验、授权决定、幂等键、工具结果、状态迁移和 Trace |
| 落地建议 | 为每个 MCP Server 标记权限等级,避免所有工具混在一个大列表里。 | 只改变与“落地建议”相关的条件 | 模型提议、参数校验、授权决定、幂等键、工具结果、状态迁移和 Trace |
| 常见坑 | 协议只是通道,策略还得自己做。 | 只改变与“常见坑”相关的条件 | 模型提议、参数校验、授权决定、幂等键、工具结果、状态迁移和 Trace |
| 和已有主线的关系 | 28 的工具调用是函数级; | 只改变与“和已有主线的关系”相关的条件 | 模型提议、参数校验、授权决定、幂等键、工具结果、状态迁移和 Trace |
12.1 记录本次实际实验
下面的记录用于“MCP:可跨进程调用的 Tool”当前这一次实验,不是第二套知识目录。先从矩阵选择一个章节,再填写实际值;没有填写的字段表示尚未验证。
topic: "MCP:可跨进程调用的 Tool"
selected_chapter: required
claim_from_article: required
baseline_version: required
changed_condition: exactly_one
execution: "保存模型提议,经 Schema 与授权校验后执行工具,并回放拒绝、超时和恢复路径"
evidence: "模型提议、参数校验、授权决定、幂等键、工具结果、状态迁移和 Trace"
pass_when: "模型只提议,代码控制执行与停止;越权输入无副作用,重复请求不重复写入"
stop_when: "路径或命令直通执行、工具结果跨会话泄漏、循环失控或重试重复副作用"
observed_result: required
first_deviation: null_or_evidence
recovery_replay: required_after_failure
12.2 边界实验必须证明能够停止和恢复
成功路径只能证明“MCP:可跨进程调用的 Tool”在当前样本上工作,不能证明它可以进入生产。边界实验需要主动制造:路径或命令直通执行、工具结果跨会话泄漏、循环失控或重试重复副作用,并观察系统是否在产生不可逆副作用前停止。
| 场景 | 只改变什么 | 应保存什么 | 通过标准 |
|---|---|---|---|
| 正常路径 | 使用已知有效输入 | 模型提议、参数校验、授权决定、幂等键、工具结果、状态迁移和 Trace | 模型只提议,代码控制执行与停止;越权输入无副作用,重复请求不重复写入 |
| 边界路径 | 把一个输入推进到约束临界值 | 临界值前后的输出与指标 | 不静默降级,不把部分结果冒充成功 |
| 明确失败 | 注入:路径或命令直通执行、工具结果跨会话泄漏、循环失控或重试重复副作用 | 原始错误、首个异常阶段和最终状态 | 失败被正确分类且没有扩大副作用 |
| 恢复重放 | 执行:关闭副作用入口,核对最终业务状态,从首个错误授权或状态迁移恢复 | 原失败样本的复测证据 | 原样本恢复,正常样本没有回归 |
恢复动作不是简单重启。对于“MCP:可跨进程调用的 Tool”,第一步是:关闭副作用入口,核对最终业务状态,从首个错误授权或状态迁移恢复。完成后使用原始失败样本复测;只验证一个新样本成功,不能证明触发条件已经消失。
“MCP:可跨进程调用的 Tool”边界实验结束后,应把正常、临界、失败和恢复四类记录放在同一个运行批次中。这样才能区分“候选方案真的修复问题”和“环境变化让问题暂时没有出现”。
十三、MCP:可跨进程调用的 Tool 的结果解释
解释“MCP:可跨进程调用的 Tool”实验时先看首个偏差,而不是最后一条错误。最后的异常通常只是上游状态错误的结果;从末端反推容易误把症状当根因。
| 观察结果 | 可以支持的判断 | 下一步 |
|---|---|---|
| 主链路没有达到预期 | 路径或命令直通执行、工具结果跨会话泄漏、循环失控或重试重复副作用 | 先执行:关闭副作用入口,核对最终业务状态,从首个错误授权或状态迁移恢复 |
| 异常链路无法恢复 | 路径或命令直通执行、工具结果跨会话泄漏、循环失控或重试重复副作用 | 先执行:关闭副作用入口,核对最终业务状态,从首个错误授权或状态迁移恢复 |
| 新样本成功但原样本仍失败 | 修复没有覆盖原始触发条件 | 固定原失败输入,恢复基线后重新比较 |
| 指标改善但证据无法回链 | 数据、版本或中间状态没有固定 | 暂停发布,补齐可追溯记录后重跑 |
“MCP:可跨进程调用的 Tool”只有同时满足“模型只提议,代码控制执行与停止;越权输入无副作用,重复请求不重复写入”,并且没有出现“路径或命令直通执行、工具结果跨会话泄漏、循环失控或重试重复副作用”,才可以认为主链路通过。这里的“通过”只对当前固定版本、样本和环境有效,不能外推到尚未测试的容量、权限或数据分布。
如果“MCP:可跨进程调用的 Tool”候选方案与基线差异很小,先检查证据分辨率是否足够;如果差异很大,先排除数据泄漏、环境漂移和版本不一致。两种情况都不能只看一个汇总均值,需要回到逐样本输出和中间状态。
“MCP:可跨进程调用的 Tool”故障定位完成后,记录“现象、首个偏差、根因、改动、原样本复测”五项。缺少原样本复测时,只能标记为待观察,不能标记为已解决。
十四、MCP:可跨进程调用的 Tool 的发布判断
发布判断需要把“MCP:可跨进程调用的 Tool”的质量、失败边界和恢复能力放在同一份记录中。以下任一条件缺失,都应停止扩量,而不是用“基本正常”替代证据。
- “MCP:可跨进程调用的 Tool”的基线与候选只存在一个计划内变量。
- “MCP:可跨进程调用的 Tool”的输入、代码、依赖、配置和数据版本可以追溯。
- “MCP:可跨进程调用的 Tool”的正常、临界、失败和恢复样本使用同一套断言。
- “MCP:可跨进程调用的 Tool”的原始输出、中间状态和失败现场已经保留。
- “MCP:可跨进程调用的 Tool”的日志、Trace、截图和测试数据已经脱敏。
- “MCP:可跨进程调用的 Tool”的停止条件、负责人和回滚入口已经演练。
- “MCP:可跨进程调用的 Tool”尚未覆盖的输入、权限、容量和外部依赖已经登记。
最终记录至少包含基线版本、唯一变量、原始证据、首个偏差、恢复复测和发布责任人。没有参与本次修改的人如果不能据此重放“MCP:可跨进程调用的 Tool”的判断,就不能发布。
十五、总结
- 本篇定位:这是工具系统从“项目内函数”走向“可复用外部工具服务”的篇章。
- 核心拆解:普通 Tool 往往是应用内函数,生命周期跟应用绑在一起。
- 落地建议:为每个 MCP Server 标记权限等级,避免所有工具混在一个大列表里。
- 常见坑:协议只是通道,策略还得自己做。
- 复述答法:MCP 可以理解成跨进程的工具协议:Server 暴露工具,Client 发现和调用,模型只负责选择。
- 可运行实验:MCP 生命周期与错误边界:真实 MCP 通过 stdio 或 Streamable HTTP 交换协议消息。
学完自测
选择所有正确答案;提交后逐项核对判断依据。