简介:很多开发者在做 Agent 工具接入时,容易把 CLI 与 MCP 简单对立起来,甚至按“本地用 CLI、远程用 MCP”来划分。本文从调用方需求、部署位置、协议能力、复用性、安全与维护成本等维度系统对比两类接入方式,帮助技术负责人和开发者在实际场景中做出更合理的架构决策。
在 AI Agent 应用快速落地的阶段,工具接入成为影响智能体能力边界的关键环节。一个 Agent 是否能稳定、高效、安全地调用外部工具,直接决定了它在真实业务中的可用性。开发团队在接入一项既有能力时,常常会面对一个看似二选一的问题:是继续用命令行入口,还是改造成模型上下文协议接入?
很多技术人员会形成一种直觉判断:MCP 是专为 AI 模型设计的,所以比 CLI 更合适;或者按部署位置划分,本地工具走 CLI,远程服务走 MCP。但在真实工程实践中,这种直觉往往会把“能力实现”和“接入协议”混为一谈,导致重复开发、维护成本上升,甚至在架构评审中暴露出对协议边界的理解偏差。
本文试图厘清三个核心问题:
CLI 是一种成熟的能力暴露方式。一个命令行工具通常包含以下要素:
CLI 的核心价值在于,它为脚本、开发者、CI 流程和自动化系统提供了一个统一且可组合的执行入口。一个稳定维护的 CLI 意味着业务逻辑已经被封装成可以被外部进程调用的形式,调用方不关心内部实现,只需要正确组织参数并解析输出。
MCP 是一种约定客户端与服务端如何发现、描述和调用能力的协议。它并不替代业务逻辑本身,而是规定了以下环节的交互方式:
MCP 支持的传输方式包括基于本地进程的标准输入输出连接,也包括基于网络的服务端传输方式。前者适用于本地进程间通信,后者适用于跨主机的远程调用。
理解这两个对象之后,就可以看出一个关键事实:CLI 描述的是“怎么执行一个能力”,MCP 描述的是“怎么发现并调用一个能力”。它们处于不同的抽象层次,并不是天然互斥的替代关系。
这个说法混淆了协议先进性与能力实现的价值。一个工具能力的核心在于它实际完成的业务操作,比如查询订单、创建工单、触发部署、检索文档等。CLI 和 MCP 都是抵达这些能力的通道。如果团队已经有一个经过测试、文档齐全、被多个脚本和开发者使用的 CLI,那么业务逻辑的重用价值远高于通道形式的更换。把 CLI 直接废弃,转而用 MCP 重写一遍工具逻辑,往往不会产生新的业务价值。
更合理的做法是:保留 CLI 作为底层能力实现,在其上增加一层 MCP 包装服务,由这个包装层负责协议交互和参数映射。这样,原来的命令行入口继续服务于开发者和自动化脚本,MCP 入口服务于 AI Agent,两者共享同一份业务逻辑。
这个判断的问题在于将部署位置与协议类型错误地绑定。MCP 可以通过标准输入输出连接本地子进程,同一个协议在本地环境中完全可用;反过来,CLI 本身也可以请求远程接口,本地命令完全可能是一个远程服务的客户端封装。因此,“本地”与“远程”并不是区分两种方案的有效维度。
部署位置需要单独评估,它影响的是连接方式、网络延迟、权限模型和运维责任,而不是协议类型本身。一个本地运行的 MCP 服务可以通过标准输入输出与宿主进程通信,一个远程 MCP 服务可以通过网络端点暴露;一个本地 CLI 可以调用远程 API,一个远程主机上的 CLI 也可以通过 SSH 等方式被调用。多个维度的排列组合都是成立的。
JSON 确实是一种高效、通用的结构化数据格式,但它本身不构成协议。一个 CLI 输出 JSON,只能说明调用方可以通过解析 JSON 获取结果,但调用方仍然需要自行解决以下问题:
这些问题正是 MCP 试图通过协议约定来解决的。如果只是让 MCP 客户端启动一个输出 JSON 的 CLI,而该 CLI 没有按照协议约定提供工具描述、参数结构和调用接口,那么得到的只是“启动了进程”,并没有实现“接入了能力”。
CLI 的能力发现依赖外部文档、帮助命令或约定俗成的知识。调用方需要预先知道命令名称、参数顺序和输出格式。这种信息通常是静态的,需要手动维护。
MCP 协议定义了服务端主动声明能力的机制。客户端在建立连接后,可以查询服务端提供了哪些工具,每个工具的参数 schema 和描述信息。这种能力发现是动态的,适合模型在运行时根据任务需求选择合适的工具。
CLI 的参数传递遵循操作系统的进程参数规则。参数通常是扁平的字符串数组,复杂结构需要序列化后作为单个参数传递,校验逻辑由命令内部自行处理。调用方需要提前了解参数的顺序、命名规则和转义方式。
MCP 的参数基于结构化 schema 描述。客户端可以在发起调用前,根据服务端提供的参数定义进行校验和补全。模型生成的结构化参数可以直接映射为协议规定的格式,减少了中间转换环节。
CLI 的退出码和标准错误输出是主要的错误反馈通道。调用方需要约定退出码的含义,并解析标准错误中的信息。对于长时间运行的任务,CLI 通常只能通过阻塞等待或轮询方式获取状态。
MCP 在协议层面约定了错误返回的结构,同时可以支持更丰富的调用状态反馈。对于异步任务,服务端可以在协议框架内返回任务标识,客户端通过后续查询获取执行状态。
CLI 每次调用通常是一个独立的进程生命周期。进程启动、执行、退出,调用之间不保持连接状态。这种模式简单,但对于高频调用场景,进程启动开销不可忽视。
MCP 的连接是持续的。在基于标准输入输出的本地传输中,客户端与服务端进程在会话期间保持通信通道;在网络传输中,连接的生命周期由客户端和服务端协商管理。持续连接可以承载多次工具调用,减少重复初始化开销。
如果一个工具能力只服务于一个特定的 Agent 宿主,那么宿主可以自行维护工具描述、参数映射和结果解析,此时 CLI 的接入成本相对较低。
但如果同一项能力需要被多个宿主调用,而这些宿主都实现了 MCP 客户端能力,那么提供标准化的 MCP 服务端接口可以显著降低重复接入成本。工具描述、参数结构和调用方式通过协议统一提供,宿主无需各自维护适配逻辑。
CLI 的安全模型取决于执行环境。调用方需要控制谁可以执行命令、命令以什么用户身份运行、命令可以访问哪些系统资源。审计通常依赖操作系统的日志机制。
MCP 的安全模型需要考虑连接层的认证与授权、工具级别的权限控制、参数注入风险以及服务端对客户端身份的验证。网络传输方式下,还需要考虑传输加密和访问来源限制。这些安全机制需要根据具体传输方式和部署环境额外设计,协议本身并不完全规定所有安全细节。
| 对比维度 | CLI | MCP |
|---|---|---|
| 解决的问题层次 | 执行入口 | 能力发现与调用协议 |
| 能力发现 | 依赖文档、帮助命令或约定 | 服务端动态声明工具与参数 schema |
| 参数传递 | 操作系统进程参数,扁平化 | 结构化参数,带类型约束 |
| 连接模式 | 每次调用独立进程 | 持续连接,可承载多次调用 |
| 调用方 | 开发者、脚本、CI、自动化系统 | AI Agent 宿主、MCP 客户端 |
| 部署位置 | 本地或远程均可 | 本地标准输入输出或网络端点均可 |
| 多宿主复用 | 每个宿主需自行适配 | 协议统一提供,减少重复接入 |
| 与业务逻辑关系 | 可以是业务逻辑的直接封装 | 通常是业务逻辑之上的协议适配层 |
| 维护成本 | 工具描述和 schema 由调用方维护 | 工具描述和 schema 由服务端维护 |
| 适合场景 | 单一宿主、已有稳定 CLI、快速集成 | 多宿主复用、需要动态能力发现、统一接入规范 |
如果团队已经有一个稳定的 CLI 工具,并且当前只有一个 Agent 宿主需要接入该能力,最务实的做法是直接适配。宿主侧维护工具描述、参数映射和结果解析逻辑,将模型生成的结构化参数转换为命令行参数,再解析命令输出。这种方式的优势在于不引入额外服务进程,不改变现有工具的维护方式,接入路径最短。
需要付出代价的地方在于:工具描述和 schema 由宿主侧维护,如果未来有多个宿主接入,同一份描述可能需要重复维护。此外,每次调用都会经历进程启动和退出,高频调用场景下需要评估性能影响。
当一项能力需要被多个 Agent 宿主调用,或者团队内部希望建立统一的工具接入标准时,MCP 的价值就更为突出。通过提供符合 MCP 规范的服务端接口,工具描述、参数结构和调用方式被集中管理,宿主只需实现客户端协议即可发现和调用能力。新增宿主时不需要重新编写适配逻辑。
在实现上,可以选择用 MCP 服务端包装已有的 CLI。服务端负责接收协议请求、进行参数校验、调用底层命令、解析输出并按照协议格式返回结果。业务逻辑继续复用,协议层与执行层分离。这种架构既保留了既有资产,又提供了标准化的接入能力。
部署位置的选择应该独立于协议类型。如果一个工具涉及敏感的本地资源访问,比如本地文件系统、本地进程管理、本机网络环境等,那么将 MCP 服务端以本地进程方式启动,通过标准输入输出与宿主连接,是一个合理的选择。协议在本地生效,不产生网络暴露面。
如果工具能力部署在远程服务端,并且需要被多个宿主通过标准协议调用,那么以网络端点形式提供 MCP 服务端接口更为合适。此时需要额外关注连接认证、传输加密和访问控制等安全因素。
CLI 在这些场景中同样可以工作。本地 CLI 可以访问远程 API,远程主机上的 CLI 可以通过安全的远程执行通道被调用。但多个宿主通过远程方式调用 CLI 时,宿主动态发现能力、参数 schema 的维护和错误处理的一致性都需要额外设计。
选型的起点不是“CLI 还是 MCP 哪个更好”,而是先回答以下问题:
综合以上因素,可以形成如下判断:
无论选择哪种接入方式,都应当避免将业务核心逻辑与接入协议深度耦合。将业务能力封装为可以被命令行、服务端接口或其他方式调用的独立层,CLI 和 MCP 服务端都只是该业务层的适配入口。这样未来切换接入方式时,核心业务代码不受影响。
在高频调用场景下,CLI 的进程启动开销可能会累积。如果每一次模型决策都需要多次工具调用,而每次调用都要创建和销毁进程,整体延迟可能上升。MCP 的持续连接模式可以减少这部分开销,但也带来了连接管理和进程生命周期维护的复杂度。需要根据实际调用频率和延迟容忍度进行压测评估。
CLI 的退出码和标准错误输出需要被完整解析并转换为对调用方有意义的错误信息。MCP 的错误返回结构也需要与业务错误对应。在包装已有 CLI 时,建议定义一个清晰的错误映射层,避免调用方收到难以理解的底层错误。
本地进程连接方式下,MCP 服务端进程以什么用户身份运行、可以访问哪些本地资源、哪些操作需要额外确认,这些问题都需要在设计阶段明确。网络端点方式下,需要实施身份认证、来源限制和传输加密。无论哪种方式,工具调用日志和审计记录对于问题定位和合规都是必要的。
当工具能力迭代时,CLI 和 MCP 服务端都需要考虑向后兼容。CLI 的参数变化可能影响所有调用方;MCP 服务端的工具描述和参数 schema 变化可能影响所有宿主。建议在协议层做好版本管理和兼容性策略,允许新旧宿主在过渡期内共存。
CLI 与 MCP 并不是同一层面的对立选项。CLI 解决的是一项能力如何被执行,MCP 解决的是调用方如何发现、描述和调用一项能力。现实中最合理的架构往往不是二选一,而是根据调用方需求、复用范围和部署环境进行组合。
“本地用 CLI,远程用 MCP”这类直觉判断的问题在于把部署位置与协议类型错误绑定。MCP 完全可以通过标准输入输出连接本地进程,CLI 也完全可以访问远程接口。JSON 输出同样不等于协议实现,能力发现、参数 schema 和调用约定才是协议的核心。
选型的正确起点是调用方的接入需求和维护成本。单一宿主、已有稳定 CLI 时,直接适配通常更简单;多宿主复用、需要统一接入规范时,MCP 的价值更为显著。已有 CLI 可以通过 MCP 服务端包装实现业务逻辑复用,部署位置则应独立评估。最终决策需要综合依赖安装、版本维护、调用开销、权限管理和团队运维能力,而不是依赖一个简单的二分法。