☰
MCP 不是银弹:Agent 工具接入架构的选型与重构
2026/10/1 16:26:42 网站建设 项目流程

1. 从「删掉薄封装」说起:MCP 到底在解决什么问题

最近圈子里关于 MCP 的讨论突然多了起来,起因是不少团队在复盘自己的 Agent 项目时发现,当初为了接工具而引入的那层 MCP 封装,现在看起来越来越像一块鸡肋。有人直接把它删了,换成更直接的 API 调用或者 CLI 桥接,跑下来效果反而更稳。于是就有了那个很扎眼的问题:MCP 是不是要退出历史舞台了?

先把结论放前面:MCP 不会消失,但「把 MCP 当成万能胶水」的用法确实在退场。这两件事必须分开看,混在一起谈就容易得出极端结论。

MCP 全称 Model Context Protocol,本质是一套让模型和外部工具、数据源之间对话的协议规范。它要解决的核心痛点很具体:在没有统一协议之前,每接一个工具就要写一套适配代码,工具 A 用函数调用,工具 B 用 HTTP 接口,工具 C 只能走命令行,Agent 侧要维护一堆分支逻辑。MCP 想做的事情,就是把这些差异收敛到一层标准接口上,让 Agent 只需要认识一种「说话方式」。

这个思路本身没有问题,问题出在落地时的抽象层级选择。很多团队一开始就把 MCP 当成唯一的接入层,所有工具无论轻重都往 MCP Server 里塞,结果就是:一个本来三行代码就能调通的 API,被包成了一个需要启动进程、维护连接、处理握手协议的 MCP 服务。这就是所谓的「薄封装」——封装带来的复杂度,超过了它挡住的复杂度。

我见过一个很典型的例子:某个团队要接一个内部查询接口,接口本身就是一个 GET 请求带 token。他们花了大概两天时间写了一个 MCP Server,又花了一天调试连接稳定性,最后发现直接用 SDK 里的 HTTP 工具调用,十分钟就能跑通。这不是 MCP 的错,是选型时没有判断「这个工具值不值得走 MCP」。

所以这一轮讨论的真正价值,不是宣判 MCP 死刑,而是逼着大家重新想清楚一件事:Agent 的连接架构到底该怎么分层。哪些走 MCP,哪些走原生 API,哪些走 CLI,哪些干脆内联进代码,这个决策才是核心。

2. Agent 连接架构的四种形态与选型逻辑

2.1 API、SDK、CLI、MCP 各自的位置

要谈重选,先把四个选项摆清楚。这四个词在热搜里反复出现,但很多人对它们的边界其实是模糊的。

API是最底层的契约,就是一组约定好的请求和响应格式。它不关心谁调用、怎么调用,只负责「你给我什么,我还你什么」。SDK是 API 的语言级封装,把 HTTP 细节、鉴权、重试、序列化都包好,让你用熟悉的语言直接调方法。CLI是面向人的命令行入口,但因为它本质上是「可执行的确定性程序」,所以特别适合被 Agent 当成工具来调用。MCP则是面向模型的协议层,它定义的是「模型如何发现工具、描述工具、调用工具」。

把这四者画成一条线,从下到上是:API → SDK → CLI → MCP。越往上,抽象越高,对模型越友好,但引入的中间层也越多。选型的本质,就是判断你的场景需要多高的抽象。

2.2 什么工具适合走 MCP

我的经验是,满足下面两三个条件的工具,走 MCP 是划算的:

  • 工具数量多且会动态变化:比如一个平台有几十个能力,今天加一个明天改一个,用 MCP 做统一注册,Agent 侧不用改代码就能发现新工具。
  • 需要跨多个 Agent 或客户端复用:同一个工具能力,既要给桌面端 Agent 用,又要给服务端 Agent 用,MCP 作为中间层能省掉重复适配。
  • 工具有状态或需要长连接:比如浏览器自动化、数据库会话这类,MCP Server 可以维护连接生命周期,比每次调用都重建要高效。
  • 工具本身复杂,需要描述性元数据:参数多、有枚举、有依赖关系,MCP 的 schema 描述能让模型更准确地调用。

反过来,下面这些情况就别硬上 MCP:

  • 工具就一个简单接口,参数固定,调用频率也不高。
  • 工具已经有成熟的 SDK,直接调方法比走协议更直接。
  • 工具是本地命令行程序,CLI 调用已经足够确定。
  • 团队没有精力维护 MCP Server 的进程管理和错误处理。

2.3 「删掉薄封装」背后的判断标准

所谓薄封装,就是封装层做的事情,几乎等于它挡住的复杂度。判断标准很简单:如果去掉这层封装,调用方的代码量没有明显增加,那这层封装就是多余的。

举个具体的对比。假设要调用一个文本摘要接口:

走 MCP 的路径大概是:启动 MCP Server 进程 → 建立连接 → 模型发现工具 → 构造符合 schema 的参数 → 发送请求 → 处理协议层错误 → 解析结果。中间任何一环出问题,排查起来都要跨层。

走 SDK 的路径是:导入 SDK → 初始化客户端 → 调用方法 → 拿到结果。出错就是标准的异常,堆栈清晰。

当工具只有一个、参数简单、调用不频繁时,后者的总成本明显更低。这就是为什么很多团队在项目跑顺之后,会把那些「为了统一而统一」的 MCP 封装拆掉,换回直接调用。

但要注意,拆封装不等于否定 MCP。拆掉的是那些不该走 MCP 的工具,留下的是真正需要协议层的部分。一个健康的架构,往往是 MCP、SDK、CLI 混用的,各管各的。

3. 实操:如何判断一个工具该走哪条路

3.1 一张决策表帮你快速定位

与其凭感觉,不如用一张表把判断标准化。下面这张表是我在实际项目里反复用过的,按顺序问自己几个问题,基本能定位到合适的接入方式。

判断维度倾向 MCP倾向 SDK/API倾向 CLI
工具数量多且动态少且固定中等,偏本地
调用方数量多客户端复用单一调用方本地 Agent
参数复杂度高,需 schema 描述中低低,命令行参数
状态需求需要长连接/会话无状态进程内状态
维护成本承受度高低中
错误处理要求需要协议层统一标准异常即可退出码判断

用的时候从上往下问,如果前几行都指向 MCP,那基本可以确定;如果大部分指向 SDK 或 CLI,就别硬套 MCP。

3.2 一个真实的重构案例

我之前参与过一个 Agent 项目,最初的设计是「万物皆 MCP」。团队花了大概三周,把七八个工具全部包成了 MCP Server,包括一个简单的天气查询、一个内部文档搜索、一个代码执行沙箱。

跑了一个月之后问题开始暴露:

  • 天气查询的 MCP Server 偶尔会因为进程重启导致连接断开,Agent 侧要处理重连逻辑。
  • 文档搜索本身有成熟的 SDK,走 MCP 之后反而丢掉了 SDK 自带的分页和缓存能力。
  • 代码执行沙箱确实需要 MCP,因为它要维护一个长期运行的隔离环境。

重构的时候我们做了三件事:

  1. 天气查询直接改成 SDK 调用,删掉 MCP Server,代码从两百多行降到三十行。
  2. 文档搜索改回 SDK,但保留一个轻量的 MCP 包装,只用于向模型暴露「有哪些搜索能力」。
  3. 代码执行沙箱继续走 MCP,因为它的状态管理和隔离需求是真实存在的。

重构后整体代码量减少了约四成,故障率明显下降。这个案例说明的不是 MCP 没用,而是MCP 应该用在它真正产生价值的地方。

3.3 参数与配置的取舍细节

在具体配置层面,有几个容易被忽略的点。

超时设置。走 MCP 时,超时要在协议层和工具层各设一次,两层超时要协调,否则会出现「工具已经返回但协议层还在等」的假死。走 SDK 时通常只需要设一次。我的习惯是 MCP 层超时略大于工具层,留出协议开销的余量。

鉴权传递。MCP 的鉴权有两种模式:一种是 MCP Server 自己持有凭证,Agent 不感知;另一种是 Agent 把凭证透传给 Server。前者更安全,但灵活性差;后者灵活,但凭证会经过更多环节。涉及敏感凭证时,优先选前者。

错误语义。MCP 的错误码和 HTTP 错误码不是一一对应的,映射时容易丢信息。比如一个 401 在 MCP 层可能被统一成「未授权」,但具体是 token 过期还是权限不足就分不清了。这时候要么在 MCP Server 里保留原始错误信息,要么干脆这个工具不走 MCP。

提示:任何涉及凭证透传的设计,都要先确认凭证不会出现在日志、错误信息和模型上下文里。这是最容易被忽略的安全细节。

4. 常见问题与排查技巧实录

4.1 连接类问题的排查顺序

MCP 相关的报错里,连接问题占了大头。我整理了一个排查顺序,基本能覆盖八成情况。

第一步,确认 MCP Server 进程是否真的起来了。很多时候报「连接失败」,其实是 Server 根本没启动,或者启动后立刻退出了。看进程列表和启动日志是最快的判断。

第二步,确认连接地址和端口。MCP 支持多种传输方式,本地进程用标准输入输出,远程用网络传输。地址写错、端口被占用、防火墙拦截,都会表现为连接失败。

第三步,确认握手是否完成。MCP 有初始化握手流程,如果 Server 版本和客户端不兼容,握手会失败。这时候看日志里的协议版本号,对比两端是否一致。

第四步,确认鉴权。如果前面都正常但还是连不上,大概率是 token 问题。token 过期、格式错误、权限不足,都会在这一步暴露。

4.2 工具调用返回异常的定位方法

工具能连上但调用返回异常,排查思路和连接问题完全不同。

先看是协议层异常还是工具层异常。协议层异常通常是参数不符合 schema、方法名拼错、返回格式不合法。工具层异常是工具本身执行失败,比如接口返回 500、命令行退出码非零。

区分方法很简单:看错误信息里有没有协议相关的关键词。如果错误提到 schema、method、invalid params,那是协议层;如果提到具体的业务错误、HTTP 状态码、退出码,那是工具层。

协议层异常优先检查 schema 定义和实际传参是否一致。我遇到过好几次是 schema 里写了枚举值,但模型传了一个枚举外的值,协议层直接拒绝。这种问题在 SDK 调用里不会出现,因为类型系统会提前拦住。

工具层异常就回到工具本身的调试。把同样的参数用 CLI 或 SDK 手动跑一遍,看是否复现。如果手动跑正常、走 MCP 异常,那问题在封装层;如果手动跑也异常,那问题在工具本身。

4.3 高频问题速查表

现象可能原因排查动作
连接超时Server 未启动/端口占用查进程、查端口
握手失败协议版本不匹配对比两端版本号
鉴权失败token 过期/格式错重新签发、检查格式
参数被拒schema 与实际不符核对 schema 定义
调用无响应超时设置不合理检查两层超时配置
结果解析失败返回格式不合法抓原始返回内容
频繁断连进程不稳定查 Server 日志、资源占用

4.4 几个踩过的坑

坑一:把 MCP 当成服务发现用。有团队想让 MCP 动态发现工具,结果工具列表一变,Agent 侧的行为就不稳定。工具发现是 MCP 的能力之一,但不代表所有工具都该动态发现。固定的工具直接写死更稳。

坑二:忽略进程生命周期。MCP Server 是独立进程,它的启动、重启、退出都需要管理。很多团队只写了启动逻辑,没写异常退出后的重启,结果 Server 挂了之后 Agent 一直报连接失败。

坑三:在 MCP 层做业务逻辑。MCP 层应该只做协议转换,业务逻辑放在工具本身。把业务逻辑塞进 MCP Server,会导致这层越来越重,最后又变成一个需要维护的「大泥球」。

坑四:凭证管理混乱。多个 MCP Server 各自持有凭证,凭证轮换时要一个个改。建议把凭证管理集中到一处,MCP Server 从统一的地方读取。

5. 重选架构时的落地建议

5.1 从最小可用集开始

不要一上来就设计一套完整的连接架构。先挑两三个最核心的工具,用最简单的方式接进去,跑通之后再逐步扩展。扩展的过程中,你会自然发现哪些工具需要 MCP,哪些不需要。

这个思路的好处是,架构是「长」出来的,不是「设计」出来的。设计出来的架构往往过度抽象,长出来的架构更贴合实际需求。

5.2 给每层定一个清晰的职责

我的习惯是给每一层定一条不可逾越的边界:

  • API/SDK 层:只负责和外部系统通信,不做任何面向模型的适配。
  • CLI 层:只负责把确定性操作暴露成命令,不做状态管理。
  • MCP 层:只负责协议转换和工具描述,不做业务逻辑。
  • Agent 层:只负责决策和编排,不直接处理底层通信细节。

边界清晰之后,任何一层出问题都能快速定位,也不会出现「这个逻辑到底该放哪」的纠结。

5.3 保留退路

无论选哪种接入方式,都要保证能相对容易地换掉。具体做法是:在 Agent 和工具之间留一个薄薄的适配层,Agent 只依赖这个适配层的接口,不直接依赖具体的接入方式。这样将来从 MCP 换成 SDK,或者反过来,改动都局限在适配层。

这个适配层不要做太多事,它的存在意义就是「隔离变化」。做多了就又变成薄封装了,得不偿失。

5.4 监控与可观测性

连接架构重选之后,监控要跟着调整。MCP 层要监控连接数、握手成功率、协议错误率;SDK 层要监控调用延迟、错误码分布;CLI 层要监控退出码和耗时。这些指标分开看,才能快速判断问题出在哪一层。

我个人的体会是,架构的复杂度应该和问题的复杂度匹配。工具简单,接入就简单;工具复杂,才值得上协议层。MCP 不是银弹,也不是包袱,它只是一个工具。用对了地方,它省事;用错了地方,它添乱。这一轮「删掉薄封装」的讨论,本质上是在帮大家找回这个判断力。

最后再分享一个小技巧:每次引入一个新的接入方式之前,先问自己「如果不用它,最坏会怎样」。如果答案是「也没什么大不了」,那就不用。这个习惯帮我省掉了不少过度设计的功夫。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询