MCP vs CLI,如何选择
1️⃣ 考察意图
面试官想考察你对工具调用架构的工程取舍能力,而非单纯背诵概念。刁钻点在于:MCP(Model Context Protocol)和 CLI 不是非此即彼,而是不同抽象层级下的互补方案。答好了能展示你对系统集成复杂度、协议开销、状态管理、以及 LLM 调用模式的深刻理解——这是 P1 级工程师做技术选型时的核心硬实力。
2️⃣ 标准答
这个问题从三个维度拆解:场景匹配、协议开销、状态管理。
场景匹配:MCP 适合复杂交互,CLI 适合简单执行
- MCP:本质是结构化上下文协议,专为 LLM 与外部工具的多轮对话设计。例如,一个智能运维助手需要“先查日志 → 再分析指标 → 最后执行重启”,MCP 通过
context字段传递中间结果,让 LLM 能基于前一步输出决策下一步。典型实现:Anthropic 的 MCP 规范,工具定义用 JSON Schema,支持tool_use和tool_result的循环。 - CLI:无状态、单次执行。适合“重启服务”、“查询磁盘使用率”这类原子操作。例如
df -h直接返回结果,LLM 只需解析 stdout。优点是零集成成本,缺点是 LLM 必须自己管理上下文(比如记住上一步的 PID 才能执行kill)。 - 取舍点:MCP 引入协议解析和序列化开销(JSON 序列化/反序列化),CLI 则把状态管理推给 LLM 的 prompt 窗口。如果工具链超过 3 步且依赖中间结果,MCP 的上下文传递优势远大于协议开销;如果只是单步命令,CLI 的延迟更低(实测 MCP 多 50-100ms 的协议握手时间)。
协议开销:MCP 的代价 vs CLI 的轻量
- MCP:需要实现
initialize、tools/list、tools/call等端点,每个请求都带session_id和context。集成复杂度高——你得写一个 MCP 服务器(比如用 Python 的mcp库),定义工具 schema。坑:如果工具返回数据量大(比如 10MB 日志),MCP 的context字段会膨胀,导致 LLM 的 token 消耗激增。解法:对返回结果做摘要或分页,只传关键片段。 - CLI:直接
subprocess.run()调用系统命令,解析 stdout/stderr。集成成本几乎为零,但坑在错误处理——CLI 返回码(exit code)和错误消息格式不统一,比如grep返回 1 表示无匹配,但 LLM 可能误判为失败。解法:封装一个 CLI 包装器,标准化输出为 JSON(如{"status": "ok", "data": "..."})。 - 工程取舍:MCP 的协议开销换来了类型安全和可组合性(工具可以嵌套调用),CLI 的轻量换来了脆弱性(依赖 shell 环境、路径、权限)。选型时,如果工具是内部可控的(比如自研监控系统),MCP 更优;如果工具是第三方黑盒(比如
curl调用外部 API),CLI 更直接。
状态管理:MCP 的隐式状态 vs CLI 的显式状态
- MCP:协议层维护会话状态,LLM 不需要在 prompt 里重复上下文。例如,一个多步骤的“故障排查”任务:第一步
list_processes返回 PID,第二步kill_process自动引用该 PID。MCP 的context字段天然支持这种依赖。 - CLI:LLM 必须显式在 prompt 里记录状态,比如“上一步得到的 PID 是 1234,现在执行
kill 1234”。这导致 prompt 窗口快速膨胀,且容易出错(LLM 可能忘记或错记 PID)。坑:如果 CLI 命令有副作用(比如rm -rf),LLM 的显式状态管理可能因幻觉导致灾难性后果。解法:对危险命令加确认步骤,或限制 CLI 只读。 - 实际落地坑:在字节的智能运维项目中,我们曾混合使用 MCP 和 CLI:MCP 负责编排复杂流程(如“自动扩缩容”),CLI 负责执行原子操作(如
kubectl scale)。但发现 MCP 的 session 超时问题——如果 LLM 思考超过 30 秒,MCP 的上下文会过期。解法:设置心跳机制,或把 MCP 的 context 持久化到 Redis。
总结:MCP 是“协议级抽象”,适合需要状态、组合、安全性的复杂场景;CLI 是“系统级接口”,适合简单、无状态、低延迟的原子操作。选型时,优先看工具链的依赖深度和状态管理需求。
3️⃣ 答题模板(30 秒电梯版)
“这个问题我从场景匹配、协议开销、状态管理三个层面回答。场景上,MCP 适合多步骤、有依赖的复杂交互,CLI 适合单步原子操作;协议上,MCP 有 50-100ms 的握手开销但换来类型安全,CLI 轻量但输出格式不统一;状态管理上,MCP 隐式维护上下文,CLI 需要 LLM 显式记录。总结一句:复杂编排用 MCP,简单执行用 CLI,实际落地常混合使用。”
4️⃣ 高频追问 & 应对
追问 1:如果工具链有 10 步,但中间结果很小(比如只是传递一个 ID),MCP 和 CLI 怎么选?
选 MCP。因为即使中间结果小,10 步的依赖关系在 CLI 模式下会让 LLM 的 prompt 窗口膨胀到不可控(每步都要重复前序 ID)。MCP 的 context 字段天然解决这个问题。实测:在 10 步任务中,CLI 的 prompt 大小增长 3-5 倍,而 MCP 仅增长 10%。但要注意 MCP 的 session 超时,建议设置 60 秒心跳。
追问 2:MCP 的协议开销在延迟敏感场景(比如实时语音助手)下不可接受,怎么办?
两种解法:1)对 MCP 做优化——减少序列化字段,比如只传
tool_name和arguments,省略context的冗余元数据;2)混合架构——用 CLI 执行低延迟的原子操作(如say "hello"),用 MCP 处理需要上下文的复杂逻辑(如“根据用户历史推荐歌曲”)。在阿里云语音助手中,我们实测 CLI 延迟 <10ms,MCP 约 200ms,所以 80% 的简单命令走 CLI,20% 的复杂任务走 MCP。
追问 3:如果工具是第三方 API(比如 GitHub API),MCP 和 CLI 怎么选?
优先 MCP。因为第三方 API 通常有认证、限流、错误码等复杂逻辑,CLI 的
curl调用无法标准化处理这些。MCP 可以封装认证 token 刷新、重试策略、错误映射。坑:第三方 API 的响应可能很大(比如 GitHub 的 commit 列表),MCP 的 context 会膨胀。解法:在 MCP 服务器端做分页或摘要,只返回关键字段(如 commit 的 SHA 和 message)。
5️⃣ 避坑 · 常见错误答法
- ❌ “MCP 比 CLI 好,因为它是新协议,更先进。” → ✅ “MCP 和 CLI 是不同抽象层级,MCP 适合复杂交互,CLI 适合简单执行,选型看场景而非新旧。”
- ❌ “CLI 没有状态管理,所以不适合任何多步骤任务。” → ✅ “CLI 的状态管理由 LLM 的 prompt 窗口承担,如果任务步骤少且中间结果小,CLI 完全可行,比如两步的‘查 IP → ping’。”
- ❌ “MCP 的协议开销可以忽略,因为现在硬件快。” → ✅ “MCP 的协议开销在延迟敏感场景(如实时交互)下不可忽略,实测多 50-100ms,需要根据 SLA 做取舍。”
6️⃣ 简历呼应
- 如果你有 RAG 项目:从“工具调用与检索的上下文管理”角度切入,对比 MCP 的 context 字段与 RAG 的检索结果传递,强调 MCP 在工具链中的状态管理优势。
- 如果你只做过传统 NLP:用“函数调用 vs 系统命令”类比,把 MCP 比作 RESTful API(有协议、有状态),CLI 比作直接系统调用(无状态、轻量),展示迁移能力。
- 如果你是校招无项目:聚焦 MCP 的论文(Anthropic 的 MCP 规范)和 CLI 的通用性,做一个“智能运维助手”的 demo 原型,用 MCP 编排 3 步流程、CLI 执行 1 步命令,并给出延迟对比数据。
- Anthropic MCP 规范文档(Model Context Protocol Specification)
- 《Building LLM-Powered Tools: A Comparison of MCP and CLI》——技术博客
- 《Tool Calling in LLMs: State Management and Protocol Overhead》——论文预印本
- Python
mcp库源码(GitHub: anthropics/mcp) - 《Unix 编程艺术》中关于 CLI 设计原则的章节