1. 动手之前:远程编译工具要解决的真实痛点
先交代一下背景。我在团队里正好扛着一条持续迭代的构建链路,本地开发机是 Windows,CI 却跑在 Linux 容器上,每次提交之前最怕的不是代码写得烂,而是"我本地编不过,CI 肯定也编不过"或反过来。更麻烦的是,有些编译任务必须用固定版本的交叉工具链,本地装一套、服务器再装一套,版本对齐就够折腾半天。
后来 AI 编程助手成了日常主力,Copilot、Codex 这类工具能直接读懂工程上下文、生成大段改动,但问题也跟着来了:它们生成的代码,能不能编译通过,得等我把改动同步回本地,再手动跑到终端敲构建命令才知道。这个"生成-验证"的闭环断裂,让 AI 辅助开发的效率打了折扣。我就在想,能不能让 AI 自己把代码放到一台统一的编译服务器上验证?顺着这个思路,就做了 CloudBuilder MCP 远程编译工具。
这个工具本质上是把"编译"这件事,以 MCP(Model Context Protocol)标准协议暴露给 AI 客户端。AI 能做的事被大大扩展了:它拿到工作区文件后,可以直接通过 MCP 调用远程编译器完成构建,再把编译日志、产物路径拿回来分析、迭代修错。也就是说,AI 不只是"写代码",还真正拥有"验证代码"的执行环境。
这篇文章适合谁看:一是正在做 AI Coding 工具链集成、想让 Agent 具备真实构建能力的开发者;二是维护大型工程、想统一编译环境、消除"本地能过 CI 挂"这套脏活的人;三是单纯对 MCP 协议实战感兴趣,想看看 tools / resources / prompts 到底怎么设计才能扛住真实场景。
我会从协议设计、执行链路、安全隔离、客户端接入这几个维度,把我踩过的坑、做过的取舍全部摊开讲。这篇文章不是入门教程,而是"生产环境到底怎么落地"的实录。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. MCP 模块怎么切:为什么最终选了 resources + tools 的组合
2.1 三种原语的分工,别一上来就全上 tools
MCP 协议提供了三种核心原语:resources(资源)、tools(工具)、prompts(提示词模板)。刚设计 CloudBuilder 时,我第一版很 naive,把所有能力都塞进 tools,也就是只暴露一个 compile 方法,AI 往里面传源码内容。用了一阵子发现特别傻:AI 每次编译都要把整个项目代码塞进参数里,token 消耗大不说,传参格式稍不对就报错。
后来重新拆解,我明确了分工:文件读取走 resources,AI 通过 mcp__cloudbuilder__workspace://struct/ 这类 URI 去枚举工作区文件结构,通过 mcp__cloudbuilder__workspace://file/{path} 读取指定文件内容。编译构建走 tools,只负责干"远程执行命令"这一件事。
这个拆分不只是表意清晰的问题,它还直接影响 AI 的调用效率。真实场景里,AI 往往需要先看一眼项目的编译配置(比如 CMakeLists.txt、pom.xml、tsconfig.json),再决定用哪条指令去构建。如果文件内容都通过 tools 的 inputSchema 传,一次调用就可能有几千上万个字符,而 MCP 对工具参数是有长度限制的(我测量过,部分客户端对单个工具入参的极限在 100KB 左右),很容易触发截断。
2.2 inputSchema 到底能不能嵌套类型?实测结论与坑
有件事我必须先说清楚,因为社区里问的人特别多:MCP tools inputSchema 是否支持类型嵌套?按照 JSON Schema 规范,嵌套是天然支持的。协议规范里 inputSchema 就是一个 JSON Schema 对象,支持 object、array、properties、$ref 等完整定义。我在实际实现里测试过三层的嵌套结构,比如:
json复制{
"type": "object",
"properties": {
"buildConfig": {
"type": "object",
"properties": {
"compiler": { "type": "string", "enum": ["gcc", "clang"] },
"flags": { "type": "array", "items": { "type": "string" } }
},
"required": ["compiler"]
},
"target": { "type": "string" }
},
"required": ["buildConfig", "target"]
}
在 TypeScript SDK 和 Python SDK 里都能正常解析,我的自定义 Client(独立跑通的 MCP host)也能按嵌套结构反序列化。但这里有个隐蔽的坑:部分成熟客户端(比如某知名 IDE 插件)对工具入参做了浅层校验,一旦遇到嵌套 object,它只把最外层结构展示给用户,内层字段根本不渲染,导致用户以为这个工具"不支持嵌套"。
