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

MCP 与 CLI 双剑合璧:AI 数据分析工作流的最佳实践

MCP 与 CLI 双剑合璧:AI 数据分析工作流的最佳实践

探索用 MCP、执行用 CLI:把验证过的查询固化为可重复脚本。

文章基于 BigdataSight 作者的真实工作流,说明 MCP 与 CLI 并非二选一,而是接力关系:MCP 让 AI 客户端在对话中发现工具、检查 schema、预览数据并生成查询,适合探索式分析;CLI 则把验证过的 SQL 固化为可重复执行的命令,便于脚本化和日常重跑。作者以一个统计各服务昨日失败率的实例贯穿全文,演示了先看 schema 再写查询、规避 cancelled 状态与跨天记录等坑点,再通过「Copy as Command」保存为 shell 脚本。长任务可由 MCP 提交并保留任务 ID,关闭连接后从终端取回结果,并提醒退出状态码、文件覆盖、任务 24 小时过期及数据可能发送给模型提供商等边界。

当你用 AI 助手探索数据时,往往想追问、核对计算、换个角度再试一次;而一旦找到有用的查询,又希望保存下来,在下次数据导出时直接重跑。MCP(模型上下文协议)和 CLI(命令行界面)恰好分别满足这两类需求。本文基于 BigdataSight 作者的真实工作流,拆解两者如何配合,并给出可复用的实践方法。

MCP 与 CLI 数据分析工作流

为什么 MCP 与 CLI 不是二选一

MCP 让 AI 客户端能够发现工具和上下文资源,适合在对话中完成探索式分析;CLI 则把验证过的查询固化为可重复执行的命令,适合纳入脚本和日常流程。作者同时维护两个接口,核心逻辑是:探索用 MCP,执行用 CLI。

这种分工并不新鲜,但很多人在实际使用中容易走极端——要么全程在聊天窗口里手动复制 SQL,要么一开始就写脚本,结果调试成本过高。真正高效的做法是让两者接力:先用 MCP 把数据摸清楚,再把确认过的逻辑交给 CLI 固化。

MCP(Model Context Protocol,模型上下文协议) 是由 Anthropic 于 2024 年底提出并开源的标准化协议,用于让 AI 客户端(如 Claude Desktop、各类 IDE 助手)以统一方式连接外部工具、数据源和上下文资源。它的核心抽象包括 tools(可调用的动作,如执行查询)、resources(可读取的上下文,如 schema 和文件内容)以及 prompts(可复用的提示模板)。服务端只需实现一次协议,任意兼容的客户端都能发现并使用这些能力,无需为每个客户端单独适配。这正是文中「AI 客户端能发现工具和上下文资源」的含义——探索阶段不必手写 API 调用,助手可自行读取列结构、预览数据并组织查询。

CLI(Command Line Interface,命令行界面) 在这里特指把数据查询封装为可执行命令(如 bds)。与 MCP 的交互式、会话式调用不同,CLI 的输入是明确的参数或 JSON 请求,输出是可重定向到文件的标准流,天然适合放入 shell 脚本、cron 定时任务或 CI 流程。CLI 的关键特性是退出状态码和确定性重放:同一命令在相同数据上可重复执行,便于自动化校验。MCP 负责「问」,CLI 负责「跑」,二者面向的是工作流的不同阶段而非竞争关系。

实例:找出失败最多的服务

假设有一份来自多个服务的执行记录 runs.csv,目标是统计昨天(UTC 时间 10 月 18 日)各服务的失败次数和失败率,只计 succeeded 和 failed 两种状态,按失败次数排序。

数据如下:

run_id,service,status,finished_at
r1,billing,failed,2026-10-18 09:00:00
r2,billing,succeeded,2026-10-18 10:00:00
r3,billing,failed,2026-10-18 11:00:00
r4,search,succeeded,2026-10-18 12:00:00
r5,search,failed,2026-10-18 13:00:00
r6,ingest,succeeded,2026-10-18 14:00:00
r7,billing,cancelled,2026-10-18 15:00:00
r8,billing,failed,2026-10-19 00:00:00

注意两个坑:r7 是 cancelled 状态,不应计入分母;r8 发生在 10 月 19 日零点,落在统计窗口之外。这类细节靠肉眼检查容易遗漏,也正是 MCP 探索阶段的价值所在。

用 MCP 先摸清 schema

通过 MCP 连接 AI 客户端后,可以直接让助手检查文件列名、预览几行数据,再生成查询。作者的提示词大致是:先展示 schema 和预览,再按 UTC 时间统计 10 月 18 日的成功与失败次数,返回完成数、失败数和失败率,按失败数排序,并在执行前展示 SQL。

这一步的关键是 先看 schema 再写查询。如果时间戳存成了文本、或者状态字段用的是 error 而不是 failed,助手能根据实际情况调整 SQL。确认无误后得到的查询如下:

SELECT
    service,
    COUNT(*) AS finished_runs,
    SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) AS failed_runs,
    ROUND(
        100.0 * SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END)
        / COUNT(*),
        2
    ) AS failure_pct
FROM runs
WHERE finished_at >= TIMESTAMP '2026-10-18 00:00:00'
  AND finished_at < TIMESTAMP '2026-10-19 00:00:00'
  AND status IN ('succeeded', 'failed')
GROUP BY service
ORDER BY failed_runs DESC, service;

结果清晰:billing 完成 3 次、失败 2 次,失败率 66.67%;search 完成 2 次、失败 1 次,失败率 50%;ingest 完成 1 次、零失败。被取消的 r7 和跨天的 r8 都被正确排除。

把查询固化成 CLI 命令

SQL 验证通过后,作者在 BigdataSight 1.2 中把它保存为命令:打开数据源,在「Settings → External Access」中选择该源并开启「Structure and data」访问权限,然后通过「Run → Copy as Command…」复制命令,窗口里可以选择 shell、结果行数上限和超时时间。

通过「Command Line → Set Up bds…」安装 bds 工具后,把复制出的命令保存成 daily-failures.sh,运行方式很直接:

sh ./daily-failures.sh > daily-failures-result.json

生成的命令会自动带上数据源选择和查询请求,输出文件是 JSON 格式的查询响应。这里有两个操作细节容易被忽略:一是先检查命令的退出状态再使用结果;二是 > 会覆盖已有文件,想保留历史结果就每次换一个新文件名。

更进一步,可以让 AI 助手把日期范围和数据源提取成参数,做成可复用脚本。但作者提醒,脚本上线前要在已知日期上试跑一遍,确认逻辑无误再纳入日常工作流。

退出状态码(exit status) 是 shell 中每个命令结束后返回给调用方的整数,0 表示成功,非零表示失败,可通过 $? 读取。文中强调「先检查命令的退出状态再使用结果」,原因是重定向符 > 会在命令运行前就创建或清空目标文件:如果查询因权限、超时或语法错误而失败,输出文件仍会存在,但内容可能是空的或错误信息。若不检查状态码就直接把该文件交给下游处理,会得到难以定位的静默错误。稳妥写法是 sh ./daily-failures.sh > out.json && echo done,或显式判断 if [ $? -ne 0 ]; then ...。

shell 重定向与引号 也是脚本化时的高频坑点:> 覆盖文件、>> 追加;JSON 请求中含双引号,直接用单引号包裹或通过 printf '%s\n' 传入可以避免 shell 提前解释。文中把请求通过管道 | 喂给 bds jobs get --request -,其中 - 约定表示「从标准输入读取」,这是 CLI 工具处理长参数或结构化输入的常见模式。

任务交接:一个入口开始,另一个入口取回

对于耗时较长的查询或导出,BigdataSight 1.2 Pro 支持独立任务。做法是让 AI 客户端把操作作为任务提交,保留返回的任务 ID,然后关闭 MCP 连接,稍后从终端查询进度。

检查任务状态:

printf '%s\n' '{"version":1,"jobID":"TASK_ID_FROM_RECEIPT"}' |
  bds jobs get --request -

任务完成后取回结果:

printf '%s\n' '{"version":1,"jobID":"TASK_ID_FROM_RECEIPT"}' |
  bds jobs result --request -

作者用同一份八条记录做了验证:直接在 SQL 中查询、通过 MCP 提交、关闭连接后,CLI 和新的 MCP 会话都取回了相同的三行汇总结果。这说明任务交接机制在跨入口场景下是可靠的。

需要注意,重跑保存的查询会基于当前数据源重新计算,而取回已完成任务得到的是那次运行捕获的结果。如果数据源发生了变化,保留早期结果反而有利于对比。另外,任务在提交 24 小时后过期,运行期间要保持 Mac 不休眠,取回结果需要相应的数据源访问权限和 Pro 授权。

异步任务(job)与同步查询 的差异在于生命周期和结果归属。同步查询是「请求—等待—返回」的一次性调用,连接断开即中止;异步任务则由服务端持久化,提交后立即返回一个 job ID(文中称为任务 ID 或 receipt),调用方可随时凭此 ID 查询状态或取回结果,即使原连接已关闭。这种模式适合耗时导出、大数据量扫描或需要跨越客户端重启的场景。

任务 ID 相当于一次运行的回执:它绑定的是那次执行的输入与输出,而非数据源的当前状态。因此文中区分了两种语义——重跑保存的查询是基于当前数据重新计算,取回任务是读取历史快照。这一区别在数据源持续写入时尤为重要,历史结果可用于对比和审计。任务通常设有过期时间(文中为 24 小时),过期后 ID 失效、结果不可再取,需要重新提交。

两种界面怎么选

作者的判断标准很实际:在连接的 AI 客户端里探索数据时用 MCP,数据源发现、查询结果和追问都在一个对话里完成;需要重复计算或写进脚本时用保存好的 CLI 命令。

两者其实都同时支持探索和执行——带终端访问权限的 AI 编程助手也能查看 CLI 帮助并直接跑查询,连接的 MCP 客户端同样能重复已知查询。真正的区别在于周边工作流:MCP 需要客户端支持服务端的工具,脚本则要自己处理 shell 引号、退出状态和 JSON 输出。

实践建议与数据边界

对于打算复用的计算,作者建议把 SQL、数据源选择、日期、时区、状态定义和结果行数上限与输出一起保存。这样下次运行前有完整的上下文可供审查和调整,而不是面对一个不知道从哪来的 JSON 文件。

数据安全方面有一个必须注意的边界:查询在本地 Mac 上执行,但返回给 AI 客户端的 schema、预览和结果可能会发送给模型提供商。选择分享哪些内容时,要检查客户端的数据设置。

本地 CSV 和 Parquet 查询可以用 BigdataSight 的免费 Viewer 体验,Pro 版本增加更多格式、远程数据源、对比、更广的导出范围和独立任务。文中步骤基于 BigdataSight 1.2。

对经常在 AI 助手里做数据分析的人来说,MCP 与 CLI 的组合不是工具堆砌,而是一条自然的工作流:让 AI 负责理解和验证,让脚本负责重复和稳定。

#MCP#CLI#AI 数据分析#模型上下文协议#命令行工具#数据分析工作流#SQL 查询#BigdataSight
分享:

相关推荐