我真正开始认真看飞书 MCP 和飞书 CLI,不是因为想做一篇技术选型文章,而是因为它们先后进入了我的日常工作流。

工作里,smartclaw 先接了飞书 MCP,后来又接了飞书 CLI;个人生活里,我也分别在 Claude Code 和 Codex 里把飞书 MCP、CLI 都接了一遍。只有 MCP 的时候,最直观的感受是 token 消耗非常快:工具定义一多,上下文还没真正开始干活就先被吃掉一大截。后来 CLI + skills 接进来以后,体验反而发生了一个很具体的变化——我甚至把自己处理飞书相关事情的主战场,从 Claude cowork 转到了 Claude Code。

这个变化让我想把两套东西拆开看清楚:同一份 OpenAPI,为什么飞书会同时做出两套形态差异这么大的 Agent 连接方式?lark-mcp 把 API 自动生成成 1271 个原子工具;lark-cli + skills 则把十几个高频域人工策展成命令和任务级 shortcut。我在本机把两套真实源码、工具描述、shortcut 实现,以及它们到底层 REST 的逐条映射全摊开看完之后,最大的收获不是“MCP 和 CLI 谁更先进”,而是看清了同一份 API 在面向 Agent 消费时,为什么会自然分裂成两种连接方式。

先把结论摆出来,后面逐层拆:

MCP 和 CLI 不是两个互相竞争的协议,是同一条「覆盖 × 质量」前沿上的两个点。 把它们分开的,不是谁的接口设计更高明——两边的调用方其实是同一个会推理的模型——而是模型通过什么界面消费这套能力:是在上下文里做结构化的工具调用(MCP:模型选工具、填参数,由 host 执行并回结构化结果),还是像一个终端操作员,把命令字符串吐给一个不会推理的 shell 去执行、再读回文本(CLI)。消费方式不同,最优解自然分叉。

有趣的是,公开关注度的结果几乎一边倒:晚出生 11 个月的 CLI,拿到了飞书 MCP 仓库 20 倍的 star,且飞书 MCP 仓库已经沉寂、CLI 还在每天发版。这个数字比较的是飞书这两套具体封装,不是 MCP 协议整体的生态热度;至少从公开仓库活跃度看,飞书自己的投入重心明显偏向了 CLI + skills。

这篇就是把这次拆解讲清楚:飞书 MCP 到底自动生成了什么、没解决什么;CLI + skills 的人工策展层到底贵在哪里、值在哪里;两个面共享的内核在哪;那 20 倍差距在飞书这个样本里说明了什么、又说明不了什么;以及把它放回 2026 年 MCP 协议繁荣与实现层反思的真实坐标后,我们能从中抽出什么判断框架。

1. 两个包,摊开看

先别急着下结论。把这两个 npm 包摊在台面上、看清它们到底长什么样——这篇后面所有判断,都是从这张表里长出来的。

@larksuiteoapi/lark-mcp(MCP 面)。 打开编译产物,核心是一个 gen-tools 目录:从飞书的 OpenAPI spec 自动生成,一个 REST endpoint 对一个 tool。数下来——1271 个工具、52 个域(POST 540 / GET 435 / DELETE 124…),另外只有 2 个是人手写的复合工具。但 1271 是库存,不是暴露面:server 启动默认只注册一个 preset.default19 个(IM 5 + 多维表格 7 + 文档 6 + 通讯录 1),其余按需 -t 才开。

@larksuite/cli(CLI 面)。不是 1:1 镜像,是双层结构。薄 schema 层120 个方法 / 9 个服务(calendar、drive、im、mail…),与 REST 1:1、可 schema 自省、每个方法直链官方文档。厚 shortcut 层:约 126 个 +命令,跨约 11 个域(base 68 · task 12 · mail 11 · im 10…),常常 1:N——一条命令编排多个接口、按参数分流、或补上客户端逻辑(名称→ID 解析、自动分页、查询 DSL)。

两边的关系,才是关键。 看着天差地别,底下其实站在同一份归一化的描述符 IR 上:MCP 的每个 tool 是一条数据描述符(名字 / 给模型读的描述 / 参数 schema / REST path / method);CLI 的 schema 自省输出也是一份结构化 IR(id / path / httpMethod / docUrl,甚至带每个参数的 example)。「能力」被做成了数据——所以同一份 spec,自动渲染出 1271 个 MCP tool,也自动渲染出 CLI 的薄 schema 层;而 CLI 真正值钱的那 ~126 个厚 shortcut,是人工堆在它之上的,不在自动生成之列。这条区别(自动生成 vs 人工策展),是后面一切的根。

lark-mcp(MCP 面) lark-cli(CLI 面)
与 API 的关系 自动生成 · 1:1 薄层 1:1 + 厚层 1:N
规模 1271 工具 / 52 域 120 方法 / 9 服务 + ~126 shortcut
默认暴露 preset.default ≈ 19 个 命令树按域分
人工成分 仅 2 个复合工具 shortcut 层 + Skill 操作手册
共同底座 一份描述符 IR:name/description/schema/path/method 同左(CLI schema 输出即 IR)

架构图:IR 自动渲染出“自动生成层”(MCP 全部 1271 工具 + CLI 薄 schema);CLI 的 ~126 shortcut 与 Skill 层是“人工策展层”、叠在薄层之上、价值所在;最终服务 Agent

三个数字先记住:MCP 1271 个工具、默认只开 19 个CLI 120 个薄命令 + 约 126 个 shortcut两个面共用一份 IR。下面分四步说清楚:MCP 到底是什么;CLI + skills 到底是什么;它们共享的内核在哪;以及用户为什么用 20 倍的 star 把票投给了 CLI。

2. MCP 到底是什么

光这组数字,先推翻一个常见误解,也暴露出一个更关键的真实边界。

误解是:「把一千多个工具一股脑丢给模型」——并没有。 1271 是库存,默认只暴露十几个;把 1271 个一次性塞进上下文,恰恰是 MCP 最被诟病的反模式(第 6 节会算这笔账),而飞书的默认配置本身就在躲它。

真实边界是:MCP 对模型的预期,本来就是 tool calling。 随便翻开一个工具,它就是一条纯数据描述符:名字、给模型读的描述、参数 schema,外加 REST 路径和 HTTP 方法。模型在单次工具调用里做的,确实就是选哪个工具、按 schema 填哪些参数;至于背后路径怎么拼、方法是 GET 还是 POST、token 往哪塞,是一段约 30 行的通用 handler 照着描述符替它做掉的。模型不处理 REST 执行细节。

但这也意味着,模型确实要自己拼工具调用链路。它真正要自己干的,是把多步业务串起来。工具是原子的(一个工具 = 一个接口),「先查 ID → 再调写接口 → 失败重试」这种工具链编排没人替它做。这一条不是误解,反而要标出来——因为把「怎么正确地把原子能力串成业务」交给谁,是做平台最核心的一个决策,也是后面 MCP 与 CLI 全部分叉的真正起点。

把这些拼起来,MCP 的真身才清楚:它不是“更好的 API”,而是一套统一的 Agent-Service 接口协议——真正规范的,是“任意 Agent 用同一种方式发现、调用任意服务”,核心能力是运行时的工具发现(连上 server,server 主动报有哪些工具,Agent 不必提前读文档)。

但它有一个先天弱点,拆完更确信:MCP 规范了 transport,没规范语义。 每个厂商定义的工具名、参数结构都不一样,于是生态的碎片化,只是从“接入方式碎片化”平移成了“工具语义碎片化”。这个洞,是后面一切的伏笔。

3. CLI + skills 到底是什么

如果说 MCP 的关键词是协议、发现、原子工具,那 CLI + skills 的关键词就是策展、任务封装、操作规程。它不是把 MCP 换成命令行这么简单,而是在同一份 API 之上多叠了两层人工判断:先把高摩擦 API 包成 shortcut,再把怎么安全使用这些 shortcut 写进 Skill。

先用 MCP 面做个对照:它与 API 严格 1:1,1271 个工具覆盖 52 个域,边际成本几乎为零。模型会推理,所以它能消费“原子能力”——哪怕需要自己串三步。飞书在这个面上做的所有功夫,是克制地精选默认集 + 偶尔把高频固定流程封成复合工具(如“建文档+灌内容”一步到位)。

CLI + skills 走的是另一条路:人工策展,求质量。 这里有个反直觉的数字:CLI 只暴露了大约 120 个方法。但“120”不是“覆盖差”,是两级主动收窄

  • 第一级,域选择(52 → 12):CLI 只纳入十几个面向终端用户的域,砍掉的 731 个全是企业后台、HR、PaaS 长尾(corehr 218 个、hire 178 个……)。这些 API 真人都很少直接碰,更别说放进一个要好用的命令行。(三个域数字不矛盾:schema 的 9 个服务是这十几个策展域的子集——有些域只有 shortcut、没有 1:1 命令。)
  • 第二级,域内三分流:每个接口,要么进薄薄的 schema 命令层(原子读写,1:1),要么被包成一个厚 shortcut,要么哪都不进、靠通用 api 命令兜底。

关键在那层厚 shortcut。它封装的单位是**“任务”而不是“接口”**,筛选标准只有一条:

凡是裸 API 对 Agent 有摩擦的地方,就包一层。筛选标准是“摩擦”,不是“重要”。

我把飞书 shortcut 命中的摩擦归成六类,每一类都对应一个“人能脑补、Agent 会卡死”的点:

摩擦类型 实证(飞书 shortcut)
ID 解析(Agent 只有名字、没有 ID) +chat-search:靠群名查 chat_id
多接口编排 / 补全 +messages-search:内部再调 mget 和 batch_query 补全
条件分流 +record-upsert:按有没有 record_id 走 POST 或 PATCH
可靠性 +messages-send:内建幂等键
安全 +resources-download:强制安全的相对输出路径
身份约束 每个 shortcut 显式标 bot-only / user-only

摩擦密度高的域,shortcut 就多:多维表格 68 个(裸 API 几乎条条有坑)、任务 12、邮件 11、IM 10。这层不是“再封装一遍 API”,是“把人类工程师的隐性 know-how 显式编码进去”。

这里还要把 Skill 层单独拎出来,否则“CLI + skills”容易被听成一个模糊口号。Skill 不是第三套 API,也不是新的执行环境;它本质上是写给 Agent 读的操作手册 + 路由规则 + 工作流约束,把“什么时候用哪个域、先读哪份 reference、哪些命令不能乱调、遇到歧义要不要追问”这些人类经验显式写下来。比如 Base skill 会规定:Base 场景只走 lark-cli base +... shortcut,不要退回裸 api;写记录前先读字段结构;公式 / lookup 字段要先看专门 guide;批量写入有 200 条限制。Calendar skill 更像一个工作流守门员:涉及预约会议或查会议室时,必须先读 schedule-meeting workflow;没有明确时间时不能直接 +room-find;创建日程前遇到候选时间 / 会议室方案要先让用户确认。

所以三层关系应该这样看:schema 层给原子能力,shortcut 层把高摩擦 API 包成任务,Skill 层告诉 Agent 怎么在真实语境里安全地选择和编排这些任务。 真正让 CLI 面变好用的,不只是命令存在,而是这三层叠在一起后,Agent 少猜了很多东西。

CLI 还补上了一批 MCP 完全没有的工程能力,全都因为它工作在一个 shell + 文本管道里:出口格式(--format json/csv/table)、自动翻页(--page-all)、预览(--dry-run)、身份切换(--as user/bot),以及一个 MCP 侧普遍的缺口——危险操作安全:CLI 给 70 个方法标了 danger:true,破坏性命令必须带 --yes 显式确认。

到这里,“消费方式决定形态”这条线就闭合了:模型在上下文里做结构化工具调用、能容忍原子能力 → MCP 求广度即可;模型把命令字符串吐给不会推理的 shell,少了 MCP 那种 host-level 的结构化 tool-call schema 约束——命令当然可以做参数解析和校验,但很多选择错误、链路错误、业务语义错误,仍然要到 CLI 执行后才暴露 → CLI 必须通过 shortcut 和 Skill,把摩擦在交付前就尽量消干净。

4. 真正的内核,不是哪一个面,是底下那份 IR

§1 已经点出,两个面其实共用同一份描述符 IR。这件事值得单独展开——因为那份 IR,才是这套体系真正的资产,而不是 MCP 或 CLI 任何一个面。把它完整摆出来(飞书源码里叫 McpTool),就一条纯数据,不是一段代码:

interface McpTool {
  name: string;          // 规范点分名:bitable.v1.appTableRecord.create
  description: string;   // 唯一的自然语言字段,喂给 LLM
  schema: any;           // 参数(zod),按 data/path/params 分区
  path?: string;         // REST 模板,含 :占位符
  httpMethod?: string;
  accessTokens?: string[]; // ['tenant','user']
}

两个细节决定了它为什么是内核:自然语言只有 description 一个字段,其余全是结构化元数据;而 path + httpMethod 必备——这正是第 2 节“不依赖 SDK 也能调”的底气。前面那段约 30 行的通用 handler 之所以能派发全部上千个工具,靠的就是它:把点分名拆开、沿 SDK 对象树逐级下钻;一旦 SDK 没跟上某个新接口,就回退到用描述符里的 path + httpMethod 直接打裸 HTTP。

这条“path 回退逃生通道“是我最欣赏的设计:它把生成层(要全覆盖)和 SDK 封装层(永远慢半拍)解耦,新接口零等待。而更大的启发是那句话——把”调用方式“做成数据,而不是代码。 正因为能力是数据,同一份 IR 才能自动渲染成 MCP 的 1271 个工具、以及 CLI 的薄 schema 层;spec 一变,重新生成、人不碰生成物。但有一句别说过头:能这样自动渲染的,只是”机械镜像“那一层;CLI 真正的价值——那 ~126 个厚 shortcut——是人工堆在 IR 之上的,恰恰不在自动生成之列(这正是第 5 节”可规模化是错觉“的伏笔)。

对一个想做 Agent 接入的平台,这是第一条可迁移结论:你真正要攒的资产,不是 MCP server,也不是 CLI,是底下那份所有面共用的 spec/IR。 只有这样,质量改进才能“改一次、全量传播”,而不是锁死在某一个面的人肉维护里。

5. 然后,开发者注意力给了一个信号——20 倍

如果故事停在第 4 节,它只是一个工整的“两者各有所长”。但有趣的是,公开关注度给出的数字,和这个工整的结论并不在一条线上。Star 不是使用量,也不是留存率,但它至少代表开发者愿意关注、收藏、传播哪一个入口。我把两个仓库的真实数据并排放(拆解当天,2026 年 6 月的快照):

lark-openapi-mcp lark-cli
Stars 742 14,552(≈20×)
创建时间 2025-04 2026-03(晚 11 个月)
最后提交 2025-08(沉寂约 10 个月 2026-06(仍每天发版

晚出生 11 个月,拿到 20 倍的 star,而且飞书 MCP 仓库已经沉寂、CLI 还在日更——从公开维护节奏看,飞书的投入重心至少明显偏向了 CLI + skills。 我盯着这张表想了很久,结论收敛成三条:

  1. 用户感受得到“单次质量”,感受不到“覆盖广度”。 没有人体验得到那 731 个长尾 API 的存在;每个人只在自己那十几个域里干活,而那里 CLI 明显更好用。广度是给仪表盘看的,质量是给人用的。
  2. 真正让人感知到产品价值的,是那层 skills 包。 开发者关注的不是“裸能力”,而是“任务级的 know-how”——是那个让 Agent 真的能把事干成的东西。它对任何想把能力开放给 Agent 的平台启示都最直接:真正的工作量不只在把接口暴露出去,更在这层 know-how。
  3. 质量改进的可规模化,是个分层的错觉。 能“改一次生成器、全量受益”的,只是描述质量那一层(第 6 节“写工具=写 prompt”);而真正拉开体验的摩擦消除与多步编排,本就不在生成器里,只能人肉一条条堆。MCP 占着前者、听起来更可规模化,飞书却没继续投;CLI 把后者那块不可规模化的硬骨头啃了,反而赢下当下。

(这里先排除一个干扰项:20× 不是“CLI 触达环境更广”赢来的——可达性两边大体相当,没有 shell 的环境甚至只有 MCP 能用。这点放到第 7 节展开。)

把这三条压成一句,就是这篇文章最想让你记住的:

把 API 自动生成成一堆 MCP 工具,是 table stakes——谁都能做,单独拿出来很难形成用户感知价值。 真正决定生死的,是上面那层摩擦消除 + 任务封装 + skills。20 倍的 star 差距,至少把这件事指得很清楚。

6. 把它放回 2026:MCP 的繁荣,与同时爆发的反思

但我必须给上面这个结论加一个时间戳和一个边界,否则它会被误读成“MCP 没用”。不是的。第 5 节只是在说:飞书这个样本里,自动生成的 MCP wrapper 没有赢过人工策展的 CLI + skills。 它不能推出“MCP 协议生态不行”。2026 年的真实图景,比“CLI 赢了”复杂得多。

一边是 MCP 在协议层的胜利:越来越多主流 Agent 平台都在向 MCP 兼容靠拢。作为“面向 AI 的统一集成层”,MCP 正在成为事实默认。也就是说,“飞书 MCP 仓库 star 少”和“MCP 协议在变繁荣”并不矛盾:前者衡量的是一个具体 provider wrapper 的产品吸引力,后者衡量的是跨平台集成协议的采用面。

另一边,反思也在 2026 年集中爆发,而这部分才是信息差所在:

  • 上下文成本失控。 有报告指出,MCP 在 Agent 真正干活之前,光是工具定义就吃掉 40–50% 的上下文窗口。我在飞书这套上看到的 1271 个工具,正是这个问题的极端形态——所以它默认只开 19 个,不是偶然。
  • 用脚投票的不止飞书用户。 2026 年 3 月,Perplexity 的 CTO 公开宣布转向“传统 API + CLI 工具”、放弃 MCP,理由和我拆出来的高度一致:token 消耗居高不下、鉴权摩擦、Agent 自主性反而下降。

更值得吃透的,是 Anthropic 自己给出的两个解法,因为它们指向了前沿正在往哪移:

  • 「给 Agent 写工具」就是给 Agent 写 prompt。 工具描述的微小改进能带来巨大效果——接口质量,本质就是描述质量。这跟我在 CLI 那层看到的“把隐性 know-how 显式编码”,是同一件事的两种说法。
  • 让 Agent 写代码来调工具,而不是把工具全塞进上下文。 把 MCP 工具暴露成一个可探索的文件系统,Agent 按需读取特定模块——这就是渐进式披露:不预加载全部能力,让 Agent 逐层探索、按需取用。

这条很重要,因为它直接改写了第 5 节的结论边界:当模型的工具检索与编排能力变强,MCP 那个“广度 + 零边际成本”的优势,有可能在长尾上重新反超 CLI 的人肉策展。 飞书 MCP 里其实已经埋了一个 recall 元工具——“用自然语言检索该调哪个 API”,本质是 RAG over tools,就是冲着这个未来去的。所以“CLI 赢了”是当下的结论,不是终局的结论。前沿这条线,还在移动。

而且 MCP 还押着另一条赌注,和模型能力无关,纯粹是结构性的:它不依赖 shell / CLI 环境。 这件事今天已经有小样——在没有 shell 的托管 / 沙盒 Agent 环境里(比如 Claude 的 cowork 沙盒),CLI 的二进制根本 exec 不起来,只有 MCP 接得通。但真正的想象空间在更远处:手机 App、智能眼镜、乃至还没出现的新 AI 设备,都不可能去跑一个命令行二进制,却都能说一套协议。当 Agent 从开发者的终端走向千万消费级设备,“协议原生”就从一个小众优点,变成 CLI 结构上根本跟不过来的护城河。CLI 赢的是“长在终端里”的当下;MCP 赌的是“Agent 终将离开终端”的明天。

7. 从飞书样本抽出的判断框架

拆完这一整圈,飞书样本给出的不是一个“站 MCP 还是站 CLI”的答案,而是一组更可迁移的判据。

第一刀,按消费方式切。 这是整篇的主轴(注意:两种场景的调用方都是会推理的模型,分的是它怎么消费、在什么场景下消费):

  • 服务集合不确定、要运行时才知道调谁(通用 Agent,连会遇到哪些服务都未知)→ 偏 MCP 的原子能力 + 运行时发现。
  • 确定性场景、agent-in-loop、要审计或确认、或高风险操作 → 偏 CLI 的策展 + skills。

这里要顺手戳破一个我前面也信过的错觉:「CLI 触达的环境更广」——并不成立。在开发者本地和常见桌面 Agent 环境里,两者的可达性大体相当;没有 shell 的环境(托管沙盒,乃至未来的移动端 / 设备)甚至只有 MCP 能用(见第 6 节)。所以选 CLI 是为它那层人工策展的质量,不是为了“能跑在更多地方”。

第二刀,按“一方还是三方”切。 这是我更早就想清楚的一条,和上面正交:你自己的官方 Agent 调自己的内部接口,最短路径是 Function Calling 直连,根本不需要 MCP 那层“服务发现 + 工具描述 + 模型选择”的开销;只有当你要把能力开放给任意第三方 Agent、接入整个生态时,MCP 那套统一协议才开始有价值。确定性高、对接服务少而明确的场景,硬上 MCP 是徒增延迟和不确定性。

第三刀,如果只能投一套,先做哪个。 我的倾向是:先做 CLI + skills 拿当下的质量与采纳,MCP 随后补上。 但这里要把 MCP 拆成两件事:自动封装那层是 table stakes,谁都能做、晚一点上不丢分;而“协议原生、能触达终端之外”那条(第 6 节)是更长线的结构性赌注——先做 CLI 只是排序,不是说那条不重要。两个都做,本质是对冲——MCP 占广度 + 协议原生触达,CLI + skills 占深度 + 体验。

还有三条从这次拆解里掉出来、对做平台普遍成立的结论:

  • 底座一定共用一份 spec/IR,让质量改进能“改一次、全量传播”,别锁死在不可规模化的人肉策展里。
  • shortcut / 工具的筛选标准是“摩擦”不是“重要”:ID 解析、编排、幂等、安全、分页、身份这六类摩擦,命中几条就值得封一层。
  • 危险操作必须有标记 + 确认机制(danger + 显式确认)——这是 MCP 侧普遍的缺口,也是一个你可以做得比飞书更好的点。

而所有这些之上,别忘了那条更大的判断:API 永远是地基,不是天花板。 无论上层是 CLI、是 MCP、还是 Agent 自己读文档,最终调的都是同一组原子 API;接口形式还在收敛,但原子 API 的质量是不会过时的投资。

8. 收尾:护城河不在自动封装层

把这一圈连起来:飞书 MCP 和飞书 CLI 不是两套互斥路线,而是同一份 IR 渲染出的两个面,被“消费者是谁”逼出分叉;而 20 倍的 star 差距至少提醒我们,把 API 自动生成成工具的那一层——谁都能做的那一层——很难单独构成护城河。

真正值钱的,是上面那层:把人类工程师的隐性 know-how,一条条显式编码成“摩擦已被消干净”的任务封装。而这层最反讽的地方在于——它恰恰是那个不会自动规模化的部分。 自动生成边际成本为零却没人要;人肉策展贵得要死却赢得了当下。这跟我上一篇文章的结尾撞到了同一堵墙:技术上能做的事,最后卡住它的,往往不是技术。

更远处或许有一个终态:当 API 文档被充分结构化、机器可读,它和一个 MCP 的工具定义其实就是同一个东西——元数据即文档,文档即接口,“API 集成”这个概念本身淡出。但我们还没到那。今天这个时点,瓶颈依然很朴素:是谁愿意花人力,把那层摩擦一条条抹平。

这也是飞书这组样本真正有价值的地方:它把“协议接入”和“任务可用”之间那层最贵、最不自动化、也最容易被低估的工作,摊到了台面上。