1. 争论的起点:我们到底在吵什么?
最近在AI开发者和工具链的圈子里,一场关于“CLI vs MCP vs Skills”的争论热度不低。乍一看,这像是一场关于技术选型的路线之争,仿佛在问:我们该用命令行工具、新兴的MCP协议,还是传统的技能(Skills)框架来构建AI Agent?但如果你深入参与过讨论,或者像我一样在实际项目中同时接触过这三者,你会隐约觉得不对劲——大家似乎都在用尽全力回答一个错误的问题。
这场争论的源头,很大程度上源于AI Agent开发从“玩具”走向“生产”过程中遇到的现实瓶颈。早期,我们可能用一个脚本调用OpenAI的API,配上简单的提示词工程,就能做出一个能聊天的机器人。但随着需求复杂化,Agent需要读取文件、搜索网络、操作数据库、调用第三方API。这时,工具扩展能力就成了刚需。CLI(命令行界面)作为最古老、最普适的“工具调用”方式首先被想起;MCP(Model Context Protocol)作为一种新兴的、旨在标准化AI与工具交互的协议,带来了新的想象;而Skills,作为一个更上层的、功能聚合的概念,也一直存在于各大AI平台的叙事中。于是,比较就开始了:哪个更快?哪个更强大?哪个是未来?
但关键在于,CLI、MCP、Skills三者根本不在同一个维度上。把它们放在一起做“VS”比较,就像在问“螺丝刀、USB接口、智能手机哪个更好用?”一样。螺丝刀(CLI)是一个具体的、底层的工具形态;USB接口(MCP)是一种连接协议和标准;而智能手机(Skills)则是一个功能集合或应用层抽象。它们的定位、解决的问题域和适用层级完全不同。纠结于“选哪个”,恰恰忽略了构建一个健壮、可扩展AI Agent所需的核心架构思考。真正的核心问题应该是:我们如何为AI Agent设计一套灵活、安全、可维护的工具调用与能力扩展体系?在这个体系下,CLI、MCP、Skills各自扮演什么角色,又如何协同工作?
2. 拆解三位“参赛者”:本质、定位与能力边界
要停止无谓的争论,首先得看清每个概念的真正面目。我们得抛开营销话术,从技术实现和设计哲学层面来理解它们。
2.1 CLI:古老而强大的“原子工具”
CLI,命令行界面,是程序员最熟悉的老朋友。在AI Agent的语境下,CLI通常指的是让Agent能够执行系统命令行指令的能力。
- 本质:一种交互界面和执行通道。它暴露的是操作系统或应用程序的底层功能。
- 如何工作:AI Agent(通过代码)生成一个字符串形式的命令(如
ls -la,git status,python script.py),然后在一个子进程中执行它,并捕获其标准输出、标准错误和退出码。 - 优势:
- 普适性:几乎任何系统功能,只要有CLI,就能被调用。这是其最大的力量源泉。
- 威力强大:可以完成文件操作、进程管理、软件安装等深度系统集成。
- 生态成熟:存在海量的命令行工具,从
ffmpeg处理媒体到kubectl管理集群,无所不包。
- 劣势与风险:
- 安全性黑洞:赋予AI直接执行任意CLI命令的能力是极其危险的。一个提示词注入或模型幻觉可能导致
rm -rf /(删除根目录)之类的灾难性后果。 - 结构化程度低:输出是纯文本,需要额外的解析(如正则表达式)才能被AI理解和使用,容易出错。
- 状态管理难:CLI命令通常是离散的、无状态的,让AI维护一个连贯的CLI会话上下文比较复杂。
- 安全性黑洞:赋予AI直接执行任意CLI命令的能力是极其危险的。一个提示词注入或模型幻觉可能导致
在AI Agent开发中,CLI能力通常作为一个“最后手段”或“基础设施层”存在。例如,一个自主编码Agent可能需要运行npm install或docker build。但这个过程必须被严格约束在一个沙箱环境或经过安全审查的命令白名单中。
2.2 MCP:雄心勃勃的“连接器标准”
MCP(Model Context Protocol),由Anthropic提出,是近期最受关注的新协议。它试图解决的核心问题是工具调用的标准化和动态发现。
- 本质:一个通信协议和资源抽象层。它定义了AI模型(客户端)与工具(服务器)之间如何交换信息。
- 如何工作:
- MCP Server:每个工具(如文件系统、数据库、搜索引擎)实现为一个MCP服务器。这个服务器启动后,会向MCP客户端宣告自己提供了哪些“资源”(Resources)和“工具”(Tools)。
- MCP Client:AI应用(如Claude Code、Cursor)内置或集成MCP客户端。启动时,它可以连接到一个或多个MCP服务器。
- 动态发现与调用:客户端自动发现服务器提供的所有资源和工具列表。当AI模型需要时,可以直接按名调用这些工具,工具的执行结果会以结构化的方式(通常是JSON)返回。
- 优势:
- 标准化:统一了工具的描述、发现和调用方式,避免了为每个工具写一遍适配代码。
- 动态性:工具可以热插拔。启动新的MCP服务器,AI立即就能使用其功能,无需修改客户端代码或重新部署。
- 结构化数据:输入参数和输出结果都有明确的模式(Schema),便于AI理解和处理。
- 安全性提升:相比开放CLI,MCP服务器可以对工具能力进行更精细的封装和权限控制。
- 挑战与现状:
- 新兴协议:生态还在早期,虽然已有文件系统、SQLite、Brave搜索等官方和社区服务器,但覆盖范围远不及CLI工具生态。
- 复杂度转移:你需要为每个想集成的功能编写或配置一个MCP服务器,这本身就有一定门槛。
- 依赖特定客户端:需要你的AI应用支持MCP客户端协议才能受益。
MCP的愿景是成为AI世界的“USB标准”,让工具即插即用。它处于比CLI更高的抽象层,关注的是“如何安全、规范地暴露功能”。
2.3 Skills:功能导向的“应用模块”
Skills(或称为Tools、Capabilities)是一个更上层的概念,在不同平台有不同实现,但核心思想一致:将一组相关的、为实现特定目标而设计的功能封装成一个可调用的单元。
- 本质:一种功能聚合和业务逻辑抽象。一个Skill内部可能包含多个API调用、条件判断、数据处理流程。
- 如何工作:以OpenAI的GPTs或自定义Action为例,一个“订机票Skill”可能背后做了这些事情:
- 理解用户意图(如“下周一北京飞上海”)。
- 调用航班搜索API获取选项。
- 过滤并排序结果。
- 格式化信息返回给用户。
- (如果需要)进一步调用支付API。 这个复杂的流程对AI模型来说,只是一个名为
book_flight的Skill/Tool。
- 优势:
- 高抽象,易使用:对AI模型友好,直接对应业务目标,无需理解底层实现细节。
- 功能强大:可以封装非常复杂的多步骤工作流。
- 可复用:设计良好的Skill可以在不同Agent间共享。
- 劣势:
- 开发成本高:每个Skill都需要单独设计、开发和维护。
- 灵活性较低:Skill的边界是固定的,如果需求稍有变化,可能就需要修改Skill或创建新的。
- 静态绑定:通常需要在Agent开发时预先定义好可用的Skills列表,缺乏MCP那样的动态性。
Skills关注的是“做什么”,它站在业务和用户体验的层面,是最终呈现给用户和AI模型的能力单元。
3. 重构问题:从“三选一”到“三位一体”的架构设计
当我们厘清了三者的本质,就会发现“CLI vs MCP vs Skills”是一个伪命题。一个成熟、强大的AI Agent系统,完全可能、也应当同时包含这三者,让它们在架构的不同层级各司其职。关键在于设计清晰的层次和交互关系。
一个我称之为“能力栈”的参考架构可以这样分层(自底向上):
基础设施层(CLI作为基石):这是与操作系统和基础服务交互的底层。例如,Agent需要管理Docker容器、执行系统诊断、批量处理文件。这时,通过一个高度受限、沙箱化、命令经过严格审核的白名单CLI接口来提供这些能力是最高效的。这一层的设计原则是安全与可控,绝不能直接暴露
bash或cmd。协议与集成层(MCP作为骨干):这一层负责集成内外部服务。对于数据库、CRM系统、内部搜索、专有API等,为它们开发或配置对应的MCP服务器是理想选择。MCP协议提供了标准的连接、发现和调用方式。当需要新增一个数据源(比如连接公司的MongoDB集群)时,你只需部署对应的MCP服务器,Agent就能自动获得其能力。这一层的设计原则是标准化与可扩展。
业务能力层(Skills作为界面):这一层面向具体的业务场景。利用底层和骨干层提供的能力,构建高价值的Skills。例如,一个“生成季度数据分析报告”的Skill,内部可能依次调用了:MCP层的“数据库查询工具”获取数据,MCP层的“图表生成服务”制作图表,以及基础设施层的“CLI文件压缩工具”打包报告。这一层的设计原则是场景化与用户体验。
Agent核心与编排层(Harness):这是大脑和指挥官。它包含LLM推理引擎、记忆、规划、决策等核心逻辑。它不直接实现具体功能,而是通过一个**“工具使用Harness”**来协调下层能力。这个Harness负责:
- 路由:根据任务描述,决定是直接回复,还是调用某个Skill、MCP工具或CLI命令。
- 参数组装与校验:将LLM的自然语言输出转换成工具调用所需的参数。
- 错误处理与重试:管理工具调用失败时的备选方案。
- 会话管理:维护工具调用历史,作为上下文供LLM参考。
这个架构中,Harness是关键。正如一些讨论中指出的,Harness是一套包裹在AI Agent核心推理逻辑之外的基础设施层。它不代替Agent做决策,而是为Agent安全、高效地使用各种能力(无论是CLI、MCP还是Skill)提供了一套统一的框架和护栏。它才是那个应该被更多讨论的“核心问题”。
4. 实战推演:以“自动部署服务”Agent为例
让我们通过一个具体场景——构建一个能“根据代码变更自动测试并部署服务”的AI Agent——来看看这个架构如何运作。
目标:开发者向Git仓库推送代码后,Agent能自动执行测试,通过后部署到预发环境。
架构实现:
基础设施层(CLI):
git命令:拉取最新代码、查看差异。docker命令:构建镜像、清理旧容器。kubectl(或docker-compose)命令:在隔离的测试环境中部署服务。- 安全设计:Agent不拥有直接执行这些命令的权限。而是通过一个安全的“执行器服务”来代理。Agent向执行器发送经过校验的指令对象(如
{“command”: “git”, “args”: [“pull”, “origin”, “main”], “cwd”: “/safe/path”}),由执行器在严格控制的上下文中运行。
协议与集成层(MCP):
- GitHub/GitLab MCP Server:提供更结构化的代码库操作,如“获取某PR的变更文件列表”、“创建评论”,比原始CLI更友好。
- 测试报告MCP Server:连接团队的测试框架(如JUnit, pytest),以结构化方式获取测试结果和覆盖率报告。
- 日志聚合MCP Server:部署后,Agent可以通过此服务器实时获取并分析应用日志,判断启动是否成功。
- 通知服务MCP Server:集成Slack或钉钉,发送部署状态通知。
业务能力层(Skills):
skill_analyze_code_change:分析代码变更,判断影响范围(是前端、后端还是数据库脚本)。skill_run_targeted_tests:根据变更范围,决定运行哪套测试用例(单元测试、集成测试或E2E测试)。skill_deploy_to_staging:协调整个部署流程,包括备份、构建、部署、健康检查。skill_rollback_if_failed:如果健康检查失败,自动执行回滚流程。
Agent核心与Harness:
- 触发:收到Webhook,得知main分支有更新。
- 规划:LLM核心分析任务,规划步骤:获取变更 -> 分析影响 -> 运行测试 -> 部署 -> 验证。
- 执行与编排(Harness工作):
- 调用
skill_analyze_code_change。该Skill内部使用GitHub MCP Server获取变更文件。 - 根据分析结果,调用
skill_run_targeted_tests。该Skill内部可能先通过CLI执行器启动测试环境,再通过测试报告MCP Server获取结果。 - 若测试通过,调用
skill_deploy_to_staging。该Skill内部按顺序调用:CLI执行器构建镜像 -> MCP服务器检查镜像仓库 -> CLI执行器执行部署命令 ->日志聚合MCP Server监控启动状态。 - 如果验证失败,Harness会触发
skill_rollback_if_failed。
- 调用
- 总结:通过
通知服务MCP Server向团队频道发送本次自动化部署的总结报告。
在这个例子里,CLI、MCP、Skill不再是选择题,而是根据任务特点被放在最合适的位置。CLI做它最擅长的底层系统操作(但被安全封装),MCP作为与各种服务交互的标准桥梁,Skill则封装了复杂的业务工作流,提供简洁的接口给Agent核心。
5. 避坑指南:架构落地的关键决策与常见陷阱
设计思路很美好,但落地时处处是坑。结合我过去几个项目中的经验,分享几个关键的决策点和容易踩的坑。
5.1 安全性:第一道也是永久的防线
- CLI执行的沙箱化是必须的:绝对不要让Agent进程直接拥有执行shell的权限。必须通过一个代理服务,该服务运行在严格的权限下(如非root用户,使用容器或命名空间隔离),并且只允许执行预定义命令列表(白名单)。所有命令参数都必须经过严格的校验和清洗,防止注入攻击。
- MCP服务器的权限最小化:每个MCP服务器都应该以最小必要权限运行。访问数据库的MCP服务器,就应该只有该数据库的只读或特定表的读写权限,而不是数据库管理员权限。
- Skill的输入验证:即使底层工具安全,Skill本身也要对输入进行业务逻辑层面的验证。例如,一个“发送邮件”的Skill,应该验证收件人地址格式,并可能有一个内部允许列表。
5.2 工具发现与路由:Harness的核心智慧
- 静态注册 vs 动态发现:对于核心、稳定的能力(如内部数据库查询),可以在启动时静态注册到Harness。对于临时性、可插拔的工具(如一个临时接入的第三方数据分析服务),则利用MCP的动态发现机制。Harness需要同时支持这两种模式。
- 路由策略:当多个工具都能完成类似任务时(比如既有CLI的
curl也能进行HTTP请求,也有一个专门的http_requestMCP工具),Harness需要有一套路由策略。可以根据工具的性能、稳定性、输出结构化程度来决策。初期可以简单配置优先级,后期可以引入基于历史成功率的智能路由。
5.3 错误处理与韧性:Agent不应该是脆弱的
- 工具调用必须有超时和重试:网络调用、CLI命令都可能挂起。Harness必须为每个工具调用设置合理的超时,并设计重试逻辑(特别是对于幂等操作)。
- 优雅降级:如果最优的工具(如MCP搜索服务)不可用,Harness应该能自动降级到备用方案(如一个简单的CLI
curl调用公共搜索API,或直接告知用户能力暂时不可用)。 - 错误信息的结构化:工具返回的错误应该是结构化的,方便Harness和LLM理解。例如,
{"error": "DATABASE_CONNECTION_FAILED", "message": "无法连接数据库: 10.0.0.1:3306", "suggestion": "请检查网络或数据库服务状态"}比单纯的"Connection refused"更有用。
5.4 开发与维护成本:平衡理想与现实
- 不要为了MCP而MCP:如果一个功能非常简单,且只有一两个地方调用,为其专门开发一个MCP服务器可能得不偿失。直接写一段安全的调用代码嵌入到Skill或Harness中更快捷。MCP的价值在需要被多个Agent复用、或需要动态插拔时最能体现。
- Skill的粒度设计:Skill不是越细越好,也不是越粗越好。过细会导致Agent需要频繁组合调用,增加复杂度和延迟;过粗则不够灵活,复用性差。一个好的经验法则是:一个Skill应对应一个完整的、用户可理解的业务操作单元。比如“预订会议室”是一个好Skill,“查询会议室空闲状态”和“创建会议室预约”如果经常被独立使用,也可以拆成两个。
- 文档与契约:无论是CLI白名单、MCP服务器的Schema,还是Skill的输入输出,都必须有清晰的文档。这不仅是给开发者的,也是给LLM的。清晰的工具描述能极大提升LLM调用工具的准确率。
6. 展望:超越争论,关注演进的趋势
所以,别再问“CLI vs MCP vs Skills”了。真正值得关注的是这个领域正在发生的、更底层的演进趋势:
- 工具调用的标准化(MCP是先行者):未来可能会出现不止MCP一种协议,但工具调用的标准化趋势不可逆转。这能降低开发成本,促进生态繁荣。
- Agent核心框架的成熟(Harness概念的深化):会出现更多像LangChain、LlamaIndex、Semantic Kernel这样,专注于Agent编排、规划、工具使用的高级框架。它们会内置更强大的Harness,更好地处理我们上面讨论的路由、安全、错误处理等问题。
- 安全与合规成为内置特性:未来的Agent开发平台会将安全沙箱、权限模型、审计日志作为一等公民来设计,而不是事后的补救措施。
- 从“工具使用”到“技能学习”:目前的模式主要是“调用”。更远的未来,Agent或许能通过观察或少量示例,自动学习如何使用一个新工具(或Skill),甚至组合出新的工作流,这才是真正的“智能”。
作为构建者,我们的思维应该从“选择一种技术”转变为“设计一个系统”。在这个系统里,CLI、MCP、Skill都是可选的、有价值的组件。你的任务是根据具体场景的需求、团队的技术栈和安全要求,像搭积木一样,将它们有机地组合起来,并用一个稳健的Harness将它们牢牢绑定在一起,最终打造出一个既强大又可靠的AI Agent。这才是我们应该花费精力去争论和探索的正确问题。