[控场AI]
· 10 分钟阅读· 5,053 字

MCP + CLI > MCP vs. CLI:协议没输,是Agent用错了

MCP + CLI > MCP vs. CLI:协议没输,是Agent用错了

MCP 被唱衰是因其被糟糕实现,MCP 管远程、CLI 管本地才是正解。

文章反驳了"MCP 不行、CLI 才是未来"的流行论调,指出问题不在 MCP 协议本身,而在于大多数 Agent 的 harness 把 MCP 工具当作全量加载的 prompt-time 函数调用,导致上下文膨胀、成本飙升。MCP 规范其实已提供修复方案——渐进式工具发现、code mode、sub-agents——只是多数 client 未实现。作者主张让 MCP 与 CLI 各司其职:MCP 负责远程 server 发现、鉴权和访问控制,CLI 作为 Agent 与 MCP 之间的本地接口。Apify 开源的 `mcpc` 正是这一思路的落地:Agent 只需一个 Bash() 工具,通过 `--help` 学习用法,即可用上完整 MCP 能力。评测显示 mcpc 在不少任务中比原生 CLI 更快,但 token 效率仍有优化空间。

MCP + CLI > MCP vs. CLI 原文标题截图

过去一年,AI 工程圈流行一个简单粗暴的结论:MCP 不行,CLI 才是未来。Perplexity 的 CTO 据称在内部宣布要从 MCP 转向 API 和 CLI;OpenClaw广告 有意不支持 MCP;Garry Tan 的评价更直接——"MCP sucks honestly"。这条推文在 X 上拿到了 1.6k 赞,情绪拉满。

但这篇文章的立场是:他们只对了一半。问题是真的,但诊断错了。 坏掉的不是 MCP 协议本身,而是大多数 Agent 使用 MCP 的方式。解决方案不是扔掉协议,而是停止糟糕地使用它。

问题出在 harness,不在协议

大多数 Agent 把 MCP 工具当成 prompt-time 函数调用来处理。连上一个 server,所有工具定义立刻塞进上下文窗口;调用一次工具,完整结果也落在上下文里。十个 server、每个五个工具,还没开始干活,每一轮就已经付出数千 token 的代价。结果不断堆积,上下文腐烂,Agent 变慢变笨,而模型根本不需要看到的数据也一并进入了模型。

这些糟糕体验并没有写进 MCP 规范。MCP 本身已经提供了修复方案:Anthropic 的 tool search tool 和 Cursor 的 dynamic context discovery 实现了渐进式工具发现;Cloudflare 和 Anthropic 都写过 code mode;还有拆分上下文的 sub-agents。问题在于大多数 MCP client 根本不实现这些能力。协议跑得比生态快。

反过来看 CLI 为什么好用——很大程度上是"误打误撞"。Agent 不会一次性加载 CLI 的全部文档,而是在需要时读 --help;CLI 天然以代码方式运行,可以用管道和 shell 脚本串联;而且每个模型都对 shell 烂熟于心,因为训练数据里有五十年的积累。但 CLI 的短板也很明显:它是一个本地黑盒,没有标准传输、没有标准鉴权、没有发现机制,也无法限定或拦截它对外部服务做了什么。这正是为什么 Agent 有 MCP connectors,却没有 CLI connectors。

什么是 harness? 在 Agent 语境下,harness 指的是模型之外、负责把模型接到工具和环境的整套执行框架——包括如何把工具定义塞进上下文、如何解析模型返回的调用意图、如何把执行结果再喂回模型。同一个 MCP server,用不同的 harness 去接,表现可能天差地别:一个把全部工具 schema 一次性铺满上下文的 harness,会让模型每轮都背着数千 token 的噪声;一个按需检索工具、把大结果留在上下文之外只回传摘要的 harness,则能显著降低开销。所以当有人说"MCP 很慢/很贵"时,真正出问题的往往是 harness 的设计决策,而不是 MCP 的 wire protocol。

什么是 code mode? Code mode 的核心思路是:与其让模型对每个工具发起一次单独调用、每次调用都往返一次模型上下文,不如让模型写一段小程序(通常是一段脚本或代码块),在沙箱或宿主运行时里连续调用多个工具,只把最终结果回传。这样做的好处有三:一是省掉多次模型往返的 token 成本;二是天然支持循环、条件、管道等编排逻辑;三是中间数据不必进入模型上下文,避免污染和上下文腐烂。Anthropic 和 Cloudflare 都写过相关实践,mcpc 的 --json 也是这一思路的落地形式。

MCP 管远程,CLI 管本地

正确的做法是让两者各司其职。MCP 继续担任标准的远程接口:server 发现、鉴权、访问控制。CLI 则成为 Agent 与 MCP 之间的本地接口。Apify 开源了 mcpc,一个通用的 MCP CLI 客户端,架构非常清晰:

┌──────────┐   Bash()   ┌────────┐    MCP    ┌────────────┐
│ AI agent │ ─────────► │  mcpc  │ ────────► │ MCP server │
└──────────┘            └────────┘           └────────────┘
                                     Sessions, OAuth, Tools,
                                     Resources, Prompts,
                                     Tasks, x402, ...

Agent 只需要一个 Bash() 工具来调用 mcpc,通过 --help 学习用法,就能与 MCP server 交互。它可以开箱即用地使用完整的 MCP 协议能力:持久会话、OAuth 2.1(含企业 SSO)、tools、resources、prompts、异步任务、skills、x402 支付,以及基于 --json 的 code mode。mcpc 支持 MCP 2026-07-28 并向后兼容旧版本,内部不含 LLM,启动快、依赖少。附带好处是:同一台机器上,一次登录和一组活跃会话可以在多个 Agent 之间共享。

MCP 的传输与鉴权机制。 MCP 目前主流有两种传输方式:本地进程通过标准输入输出通信的 stdio,以及面向远程服务的 Streamable HTTP(早期还有已弃用的 HTTP+SSE)。远程场景下,MCP 规范把授权交给 OAuth 2.1,要求 server 暴露受保护资源元数据,client 据此完成发现、授权码流程和 token 刷新。这套机制的价值在于"标准化":任何兼容的 client 面对任何兼容的 server,都能用同一套方式完成鉴权、限定权限范围和撤销访问,而不必为每个第三方服务单独写一套 API key 逻辑。这正是 MCP 与裸 CLI 最关键的区别——CLI 能在本地跑得很好,却难以承载"谁被授权访问哪个远程资源、访问范围多大、能否审计"这类企业级问题。

在 shell 里长什么样

下面是一段实际的 shell 工作流,展示了从安装到渐进式工具发现的全过程:

brew install apify/tap/mcpc          # 或: npm install -g @apify/mcpc

mcpc login mcp.apify.com             # OAuth 一次;token 存入 OS keychain
mcpc connect mcp.apify.com @apify    # 建立持久会话
mcpc @apify                          # 查看 server 信息、能力、指令
mcpc @apify grep "crawler"           # 渐进式工具发现
mcpc @apify tools-get search-actors  # 仅在需要时取某个工具的 schema
mcpc @apify tools-call search-actors keywords:="tiktok scraper"

而 code mode 更关键——Agent 写一段脚本,而不是为每次调用都往返一次自己的上下文:

mcpc @apify tools-call search-actors keywords:="tiktok scraper" limit:=1 --json \
  | jq -r '.content[0].text | capture("`(?<actor>[^`]+)`").actor' \
  | xargs -I {} mcpc @apify tools-call fetch-actor-details actor:="{}" --json

这就意味着,无论 Agent 自己的 MCP client 是否支持渐进式发现和 code mode,都能通过 mcpc 用上这两项能力。

渐进式工具发现(progressive tool discovery) 指的是一种按需加载工具定义的模式:Agent 一开始并不把所有工具的名称、描述、参数 schema 都塞进上下文,而是先拿到一份工具清单或通过检索方式找到相关工具,只有真正要用某个工具时,才去取它的完整 schema。这与"连接即全量加载"的朴素做法形成对比。对于连接了多个 server、每个 server 又有几十个工具的场景,渐进式发现能把常驻上下文的 token 从数千压到几百。Anthropic 的 tool search tool 和 Cursor 的 dynamic context discovery 都在做这件事,mcpc @apify grep "crawler" 与 tools-get 则是以 CLI 命令的形式把它暴露出来,让不具备该能力的 Agent 也能受益。

评测说了什么

Apify 构建了 connector-bench 来量化 mcpc 相对 CLI 和朴素 MCP 实现的效率。每次运行给 Agent 同样的跨 server 任务,但使用三种不同的 harness:把所有工具加载进上下文的原生 MCP、相同服务的原生 CLI、以及 mcpc。评测跟踪的是累计成本随墙上时钟时间的变化。

在一个 Apify MCP server 对比 Apify CLI 的 Actor 发现场景中,很多测试里 mcpc 比原生 CLI 更快完成任务,尽管有时成本更高。作者对此的解释很坦诚:原生优化的 CLI 通常比通用 MCP CLI 包装器更简洁、token 效率更高。但他们相信优化空间很大,mcpc 的性能会逐渐收敛到原生 CLI 的水平。

connector-bench 的评测方法。 这类评测的核心在于控制变量:给同一个 Agent 完全相同的任务,只替换它背后的 harness——原生 MCP(全量工具入上下文)、对应的原生 CLI、以及 mcpc 包装层。指标不是单看"耗时"或"成本"中的某一个,而是跟踪累计成本随墙上时钟时间的变化曲线,因为真实使用中一个 Agent 可能连续执行几十步任务,任何单点的快或省都可能被后续步骤的累积开销反超。这种设计能揭示一个容易被忽略的事实:更快的 harness 未必更省 token,更省的也未必更快,二者需要在具体任务分布上做权衡。作者也据此坦承原生优化 CLI 在 token 效率上往往占优,而 mcpc 的优势更多体现在完成任务的速度和对完整 MCP 能力的开箱支持上。

别再喊 CLI beats MCP

结论其实很朴素:MCP + CLI 胜过两者单独使用。 即便是被认为"故意不支持 MCP"的 OpenClaw,实际上也在通过 mcporter——一个 MCP 转 CLI 的转换器——使用 MCP,这本身就印证了这一点。问题从来不是协议,而是 Agent 把 MCP 实现得很差。

MCP 官方有十种语言的 SDK,TypeScript、Python、Go 都有,但唯独没有 shell 的——而 shell 恰恰是最通用的编程语言。mcpc 就是想填这个空缺,让任何拥有代码运行时的 Agent 都能用上完整的 MCP。

对开发者来说,这件事的启示不在于选边站队,而在于分清接口的层次:远程连接、鉴权、发现交给 MCP;本地编排、脚本化、token 节约交给 CLI。把两者对立起来,本身就是一种错误的抽象。

#MCP#MCP CLI#mcpc#AI Agent#Model Context Protocol#渐进式工具发现#code mode#AI 工具链
分享:

相关推荐