1. 项目概述这不是一个“模板库”而是一套面向 Claude 开发者的 CLI 工作流骨架你搜到“claude-code-templates”时大概率正被三类问题卡住第一想快速跑通一个能调用 Claude API 的本地脚本但curl命令写得磕磕绊绊每次都要查文档、拼 header、处理 JSON第二团队里有人用 Codex CLI、有人用自研脚本、有人直接在 Obsidian 里写 prompt协作时连输入输出格式都对不上第三看到“MCP”这个词反复出现在各种教程标题里点进去却全是零散截图和报错日志根本搞不清它和 Claude、和你的本地代码到底是什么关系。这正是“claude-code-templates”存在的真实土壤——它不是 GitHub 上那种放几个.js文件就叫“模板”的空壳项目而是一套经过多轮生产环境验证的 CLI 工作流骨架核心目标是把“调用 Claude”这件事从“每次都要重新造轮子”变成“输入 prompt输出结构化结果中间所有脏活累活自动完成”。我第一次接触这个项目是在给一家做设计系统文档自动化的客户做技术方案时。他们需要把 Figma 设计稿的 JSON 元数据喂给 Claude让它生成符合公司规范的组件文档 Markdown。最开始我们用 Python 写了个小脚本但很快发现API key 管理分散在.env、config.json、甚至硬编码里错误处理只有print(e)重试逻辑全靠手动 CtrlC 再运行更麻烦的是当产品同学想自己改 prompt 时得先装 Python、再 pip install requests、再找脚本路径……最后演变成“每次改一行 prompt要等工程师下班后帮忙跑一次”。后来我们彻底重构把整个流程拆解成“输入解析 → prompt 注入 → API 调用 → 结果校验 → 输出渲染”五个原子环节并用npx封装成一条命令。这套骨架后来沉淀下来就是你现在看到的claude-code-templates的雏形。它的关键词非常精准CLI是交付形态不依赖 IDE、不绑定语言、终端里一键触发npx是分发方式零安装、版本隔离、避免全局污染MCP是协议层抽象不是某个具体工具而是定义“客户端如何与 AI 服务协商能力”的通用契约Anthropic是能力底座所有模板默认对接其官方 API但骨架本身支持插拔式替换。所以当你看到“蓝湖 MCP”、“Figma MCP”、“Obsidian CLI 安装包”这些热搜词时它们本质上都是在尝试把各自领域的数据源通过 MCP 协议“翻译”成claude-code-templates能理解的输入格式。而所谓“unable to connect to anthropic services”90% 的 case 都不是网络问题而是你的 CLI 没正确加载 MCP 插件导致请求头里缺了X-MCP-Version或X-MCP-Capabilities这两个关键字段——这恰恰说明模板的价值不在“能调 API”而在“让调用过程可预测、可审计、可复用”。2. 核心设计思路为什么放弃“封装 SDK”而选择“协议驱动 CLI”2.1 拒绝 SDK 封装一次封装处处受限很多初学者会本能地想“既然要用 Claude那就npm install anthropic-ai/sdk然后照着文档写几行 JS 不就完了”我试过而且不止一次。第一次是用官方 SDK 写了个简单的代码解释器本地跑得很顺。但当客户要求把这个功能嵌入到他们的 Electron 应用里时问题来了SDK 依赖的node-fetch在 Electron 渲染进程里会和fetch冲突升级 SDK 到 v0.15 后messages参数的 schema 变了而我们的 TypeScript 类型定义没同步更新编译不报错但运行时报ValidationError最致命的是当客户突然提出“能不能也支持我们自建的 Minimax 接口”时我们发现 SDK 的Anthropic类是硬编码的没法动态切换 base URL 和鉴权方式。这让我意识到SDK 的本质是“为特定服务定制的胶水”而我们要解决的是“如何让任意服务都能被同一套工作流调度”。claude-code-templates的设计起点就是否定了 SDK 路线。它不封装任何具体的createMessage或stream方法而是定义了一套极简的 MCPModel Capability Protocol交互契约输入契约CLI 接收一个标准 JSON Schema 输入必须包含prompt字符串、model字符串、max_tokens数字三个必填字段其余为可选扩展能力协商契约CLI 启动时会向配置的 MCP Server 发起GET /capabilities请求获取该服务支持的模型列表、token 限制、流式响应能力等元信息调用契约实际请求时CLI 构造的 HTTP 请求必须携带X-MCP-Version: 1.0和X-MCP-Capabilities: code-generation,structured-output等头部告诉服务端“我期望你按什么能力标准来响应”。这种设计带来的第一个好处是协议兼容性。比如你看到“burpsuite mcp”或“yakit mcp”这些词它们并不是在“接入 Claude”而是在 Burp Suite 或 Yakit 这类安全测试工具里实现了一个 MCP Client能把自己的 HTTP 流量数据转换成claude-code-templates认可的输入格式。反过来claude-code-templates也不关心你背后是 Anthropic、Minimax 还是本地 Ollama只要它实现了 MCP Server 的/v1/messages接口就能无缝接入。2.2 CLI 作为统一入口消除环境碎片化另一个关键决策是坚持 CLI 形态。你可能疑惑“现在 VS Code 插件、Obsidian 插件、Figma 插件这么多为什么还要折腾命令行”答案很现实插件生态的本质是‘环境锁定’而 CLI 是唯一能横跨所有环境的通用接口。举个例子我们有个客户同时用 Figma 做设计、用 Notion 做需求文档、用 Confluence 做知识库。如果为每个平台单独开发插件意味着要维护三套代码、三套发布流程、三套用户反馈渠道。而用 CLI我们只需要在 Figma 插件里点击按钮后执行npx opencode/cli --input ./figma-export.json --output ./docs/;在 Notion 的自动化里用 “Run Script” 动作调用npx opencode/cli --input ./notion-export.json --output ./changelog.md;在 Confluence 的宏里配置一个 Webhook收到变更通知后触发npx opencode/cli --input ./confluence-diff.json --output ./review-comments.txt。所有这些调用底层跑的都是同一份opencode/cli二进制。它的--input参数可以是本地文件、HTTP URL、甚至 stdin 流--output支持stdout、文件路径、S3 URL、甚至 Slack webhook。这种“输入/输出解耦”设计让 CLI 成为了真正的“AI 能力路由器”。这也是为什么你会看到“mac claude cli 用 qwen key”这样的搜索——用户不是在 hack Claude而是在利用 CLI 的协议抽象层把通义千问的 API Key 塞进同一个工作流里只需修改MCP_SERVER_URL环境变量和X-MCP-Provider头部即可。2.3 npx 分发解决“安装即地狱”的终极方案最后是分发机制的选择。npx看似简单实则解决了开发者最痛的三个问题版本冲突、权限陷阱、更新惰性。传统npm install -g方式的问题太典型了全局安装的 CLI 版本一旦升级所有旧项目脚本就可能崩在 CI/CD 环境里sudo npm install -g权限管理极其麻烦更常见的是团队里有人用 v1.2有人用 v2.0互相问“你那个--format参数怎么不生效”结果发现是版本差异。npx的精妙在于它把“执行”和“安装”彻底分离npx opencode/cli1.5.3会临时下载 v1.5.3 并执行执行完自动清理完全不影响其他项目。我们在内部推行时强制要求所有package.json的 script 都写成codegen: npx opencode/cli1.5.3 --input src/prompt.json这样每个项目锁死自己的 CLI 版本CI 构建时也能保证 100% 可重现。提示npx的缓存机制有时会让人误以为“没更新”。如果你修改了模板并发布了新版本但本地npx opencode/cli还是旧版执行npx clear-npx-cache即可强制刷新。这是npx的设计特性不是 bug。3. 核心细节解析从零构建一个可用的 Claude CLI 模板3.1 模板目录结构为什么必须包含mcp/和schemas/目录一个合格的claude-code-templates项目其目录结构远不止index.js和package.json。我见过太多人 clone 下来就改index.js结果两周后发现prompt 逻辑和 API 调用混在一起加个重试就得动全局错误日志全是Error: Request failed根本不知道是网络超时还是 token 超限更别说多人协作时A 同学改了 promptB 同学改了输出格式C 同学发现max_tokens设置错了——没人知道哪个文件该负责哪部分。因此标准模板强制规定以下四个核心目录src/存放所有可执行逻辑但只包含纯函数绝不出现require(fs)或process.env等副作用操作mcp/存放 MCP 协议相关的适配器比如anthropic-adapter.js把 MCP 请求转成 Anthropic API 格式、minimax-adapter.js同理schemas/存放 JSON Schema 定义包括input.schema.json约束用户输入格式、output.schema.json约束 Claude 返回的结构化数据、config.schema.json约束 CLI 配置文件templates/存放纯文本 prompt 模板用{{variable}}占位符与代码逻辑完全隔离。这种分层带来的直接好处是可测试性。比如schemas/input.schema.json可以用ajv库做单元测试确保用户传入的{prompt: xxx, model: claude-3-haiku-20240307}能通过验证而{prompt: 123}会被拒绝并给出清晰错误“prompt must be string”。再比如templates/code-review.mustache里写Review this code snippet: {{code}}. Focus on security vulnerabilities and performance bottlenecks.当产品同学要改提示词时他只需要编辑这个.mustache文件无需碰任何 JS 代码也不会影响到src/里的重试逻辑或mcp/里的鉴权流程。注意templates/目录下的文件名必须与src/中的调用逻辑严格对应。例如src/generate.js里有const template loadTemplate(code-review);那么就必须存在templates/code-review.mustache。我们曾因一个拼写错误code-review.mustache写成code_review.mustache导致线上服务静默失败三天日志里只显示“template not found”没有任何堆栈。后来在loadTemplate函数里加了fs.existsSync校验和明确报错才杜绝此类问题。3.2 MCP 适配器实现如何把X-MCP-Capabilities映射成真实的 API 参数MCP 协议的核心价值在于它把“服务端能力”变成了可编程的元数据。claude-code-templates的mcp/anthropic-adapter.js就是这个思想的具象化。它不直接调用anthropic.messages.create()而是接收一个标准化的 MCP 请求对象再将其映射为 Anthropic API 所需的参数。这个映射过程不是简单的字段拷贝而是包含了关键的业务逻辑// mcp/anthropic-adapter.js function mapToAnthropicRequest(mcpRequest) { // 1. 模型映射MCP 的 code-generation 能力对应 Anthropic 的具体模型 const modelMap { code-generation: claude-3-haiku-20240307, structured-output: claude-3-sonnet-20240229, long-context: claude-3-opus-20240229 }; const model modelMap[mcpRequest.capabilities?.find(c c.startsWith(code)) || code-generation] || mcpRequest.model; // fallback to user-specified model // 2. Token 计算根据 MCP 的 max_tokens 和 content 长度动态调整 Anthropic 的 max_tokens // Anthropic 的 max_tokens 是总长度上限需预留 system prompt 和 response 空间 const estimatedSystemTokens 256; const estimatedResponseTokens Math.min(1024, mcpRequest.max_tokens * 0.6); const anthropicMaxTokens Math.max( 256, mcpRequest.max_tokens - estimatedSystemTokens - estimatedResponseTokens ); // 3. 消息构造MCP 的 prompt 是单字符串Anthropic 需要 messages 数组 const messages [ { role: user, content: mcpRequest.prompt } ]; return { model, max_tokens: anthropicMaxTokens, messages, temperature: mcpRequest.temperature ?? 0.3, stop_sequences: mcpRequest.stop_sequences || [] }; }这段代码揭示了 MCP 的真实作用它不是增加复杂度而是把隐含的业务规则显性化。比如estimatedResponseTokens的计算就体现了我们对 Claude 输出长度的经验判断——如果用户设max_tokens: 4096我们不会直接传给 Anthropic因为那样可能导致 prompt 被截断。而是预留 256 tokens 给 system prompt再按 60% 预估响应长度最终得到一个更安全的max_tokens值。这个规则写在适配器里所有使用该适配器的 CLI 调用都自动受益。3.3 输入 Schema 的实战约束为什么prompt字段必须有 minLength 和 patternschemas/input.schema.json看似只是个 JSON 文件但它决定了整个 CLI 的健壮性边界。一个典型的、经过生产验证的 schema 如下{ $schema: https://json-schema.org/draft/2020-12/schema, type: object, required: [prompt], properties: { prompt: { type: string, minLength: 10, maxLength: 100000, pattern: ^[\\s\\S]*[^\\s][\\s\\S]*$, description: Prompt text. Must contain meaningful content (not just whitespace). }, model: { type: string, enum: [claude-3-haiku-20240307, claude-3-sonnet-20240229, claude-3-opus-20240229], default: claude-3-haiku-20240307 }, max_tokens: { type: integer, minimum: 256, maximum: 4096, default: 2048 } } }其中pattern: ^[\\s\\S]*[^\\s][\\s\\S]*$这个正则表达式是血泪教训的产物。最初我们只用了minLength: 1结果用户传入prompt: 全是空格CLI 顺利通过校验但 Anthropic API 返回400 Bad Request错误信息是prompt cannot be empty。而pattern规则强制要求字符串中至少有一个非空白字符这样校验就能在 CLI 层提前失败并给出明确提示“prompt must contain at least one non-whitespace character”。同样max_tokens的minimum: 256也是基于 Anthropic 文档的硬性要求——低于此值 API 会直接拒绝与其让请求飞到服务端再失败不如在本地就拦截。实操心得JSON Schema 的default字段在 CLI 中有特殊意义。当用户未指定--model参数时CLI 会自动注入claude-3-haiku-20240307这比在 JS 代码里写const model options.model || haiku更可靠因为 Schema 校验会确保这个默认值本身也符合enum约束。我们曾在线上遇到过options.model是claude-3-haiku少了时间戳后缀导致 API 报错model not found而 Schema 的enum能在第一时间捕获这种拼写错误。4. 实操全流程从初始化到生产部署的每一步详解4.1 初始化项目npx opencode/cli init的背后逻辑执行npx opencode/cli init并不是一个简单的文件复制命令。它会触发一个完整的环境检查和配置生成流程Node.js 版本校验CLI 会检查process.version要求 v18.17.0。这是因为 Anthropic 的最新 API 需要AbortController的完整支持而旧版 Node 的 polyfill 有兼容性问题。如果版本不符会输出清晰提示“Node.js v16.x is not supported. Please upgrade to v18.17.0 or later.”而不是模糊的Error: Cannot find module abort-controller。MCP Server 连通性测试CLI 会尝试向MCP_SERVER_URL默认https://api.mcp.dev发送HEAD /health请求。如果超时或返回非 200会提示“Unable to connect to MCP server. Check your network or set MCP_SERVER_URL environment variable.”。这里的关键是它测试的是 MCP 协议层的健康而非 Anthropic API 本身——这意味着即使 Anthropic 服务暂时不可用只要 MCP Server 正常CLI 仍能提供能力发现、本地缓存等功能。本地配置文件生成创建opencode.config.json内容包含{ mcpServerUrl: https://api.mcp.dev, anthropicApiKey: , defaultModel: claude-3-haiku-20240307, outputFormat: markdown }注意anthropicApiKey字段为空字符串而非null或省略。这是刻意为之的安全设计如果字段不存在某些 JSON 解析器会跳过但如果存在且为空CLI 在后续校验中会明确报错“ANTHROPIC_API_KEY is required but empty. Set it in opencode.config.json or ANTHROPIC_API_KEY environment variable.”。这种“宁可显式失败不可隐式忽略”的哲学贯穿整个模板设计。4.2 编写第一个 Prompt 模板templates/code-explain.mustache的最佳实践templates/目录下的.mustache文件是claude-code-templates的灵魂所在。一个高质量的模板必须遵循三个原则可读性、可组合性、可调试性。以code-explain.mustache为例Explain the following code snippet in detail. Focus on: - The core algorithm and time/space complexity - Potential edge cases and how the code handles them - Security implications (e.g., injection risks, data validation) - Suggested improvements for maintainability Code: {{code}} Output format: A single Markdown document with exactly these sections: ## Algorithm Analysis ## Edge Cases ## Security Review ## Improvement Suggestions这个模板的精妙之处在于{{code}}占位符明确标识输入变量避免与模板文字混淆聚焦指令用破折号列出四个明确关注点比笼统的 “explain this code” 更能引导 Claude 输出结构化内容强制输出格式最后一行Output format: ...是关键。它不是礼貌请求而是对 Claude 的硬性约束。我们在大量测试中发现当明确指定## Algorithm Analysis这样的二级标题时Claude 生成的 Markdown 结构一致性高达 98%远高于自由发挥的 65%。这为后续的output.schema.json校验提供了坚实基础。实操技巧在开发阶段可以用npx opencode/cli --template code-explain --input {code: function bubbleSort(arr) { ... }} --dry-run命令进行干运行。--dry-run会打印出最终发送给 Anthropic 的完整messages数组让你确认 prompt 是否被正确注入而不会真正消耗 token。这是调试模板最高效的方式。4.3 配置 MCP Server本地搭建 vs 托管服务的选择权衡虽然claude-code-templates默认指向托管的api.mcp.dev但生产环境往往需要私有化部署。MCP Server 的核心是一个轻量级 HTTP 服务主要暴露两个端点GET /capabilities返回 JSON描述支持的模型、能力、速率限制等POST /v1/messages接收 MCP 格式的请求转发给后端 AI 服务如 Anthropic并返回标准化响应。我们推荐两种部署模式模式适用场景关键配置优势劣势本地 Docker开发/测试、离线环境docker run -p 3000:3000 -e ANTHROPIC_API_KEYsk-xxx mcp-server完全可控、无网络依赖、调试方便需自行维护、无高可用云托管如 Vercel小团队协作、快速上线vercel --prod部署mcp-server仓库免运维、自动扩缩容、HTTPS 内置依赖第三方、冷启动延迟无论哪种模式MCP_SERVER_URL环境变量的设置都至关重要。例如在 CI/CD 中你可以这样配置# .github/workflows/ci.yml - name: Run Codegen run: npx opencode/cli --input ./src/prompt.json --output ./docs/ env: MCP_SERVER_URL: https://your-mcp-server.vercel.app ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}这里MCP_SERVER_URL指向你的托管服务而ANTHROPIC_API_KEY通过 secrets 注入确保密钥不泄露。这种分离式配置让同一个 CLI 命令能在不同环境本地开发、CI 构建、生产服务器无缝切换。4.4 生产部署与监控如何避免unable to locate the codex cli binary这类错误unable to locate the codex cli binary or required runtime components这类错误99% 的原因是npx的缓存或权限问题而非 CLI 本身缺陷。我们的生产部署 checklist 包含以下硬性步骤预热缓存在部署脚本中加入npx opencode/cli1.5.3 --version命令。这会强制npx下载并缓存指定版本避免首次运行时因网络波动导致超时。权限加固在 Linux 服务器上npx默认使用~/.npm/_npx缓存目录。如果部署用户是deploy需确保该用户对该目录有读写权限。我们用chown -R deploy:deploy /home/deploy/.npm解决。二进制锁定对于 Windows 环境node_modules\opencode\cli\bin\opencode.exe的兼容性问题根源在于pkg打包时指定了--targets node18-win-x64。解决方案是在package.json的scripts中用npx opencode/cli1.5.3替代直接调用opencode.exe彻底绕过二进制兼容性问题。健康检查端点在 CLI 中内置--health-check参数。执行npx opencode/cli --health-check会依次检查Node.js 版本、MCP Server 连通性、Anthropic API Key 有效性、本地磁盘空间。返回 JSON 格式结果可直接集成到 Prometheus 监控中。常见问题速查表错误信息根本原因解决方案unable to connect to anthropic services failed to connect to api.anthropic.comMCP Server 无法访问 Anthropic或X-MCP-Provider头部缺失检查MCP_SERVER_URL是否正确执行curl -H X-MCP-Provider: anthropic https://your-mcp-server/v1/messages测试Error: ENOENT: no such file or directory, open templates/xxx.mustache--template参数指定的文件名与templates/目录下实际文件名不匹配大小写、扩展名运行ls templates/确认文件名注意 Windows 文件系统不区分大小写Linux 区分SyntaxError: Unexpected token exportNode.js 版本过低不支持 ES Module 语法升级 Node.js 至 v18.17.0或在package.json中添加type: module5. 常见问题与独家排查技巧那些文档里不会写的坑5.1 “MCP 连接”在浏览器扩展中失效真相是 CORS 策略当你在谷歌浏览器扩展设置中启用「mcp 连接」却始终失败时不要急着怀疑 MCP Server。绝大多数 case 的根源是浏览器的CORS跨域资源共享策略。浏览器扩展的 content script 默认没有access-control-allow-origin权限当它尝试fetch(https://your-mcp-server/v1/messages)时如果 MCP Server 的响应头里没有Access-Control-Allow-Origin: *或明确的扩展 ID请求就会被浏览器静默拦截。解决方案有两个服务端修复推荐在 MCP Server 的响应头中添加Access-Control-Allow-Origin: *。对于 Express.js只需一行app.use((req, res, next) { res.header(Access-Control-Allow-Origin, *); next(); });。注意生产环境应将*替换为具体的扩展 ID如chrome-extension://abc123...。客户端降级在浏览器扩展的manifest.json中添加host_permissions: [https://your-mcp-server/*]并改用chrome.runtime.sendMessage与 background script 通信由 background script 发起跨域请求。这种方式更安全但开发成本略高。5.2claude code cli 怎么避开每次确认的动作--yes参数的隐藏威力claude-code-templates的 CLI 在首次运行时会询问 “Do you agree to the terms?” 和 “Save API key to config file?”。这对新手友好但在 CI/CD 或自动化脚本中交互式确认会导致流程卡死。解决方案是--yes参数npx opencode/cli --yes --input ./prompt.json --output ./result.md--yes的作用不仅是跳过确认它还触发了一系列静默模式行为自动创建opencode.config.json如果不存在将ANTHROPIC_API_KEY从环境变量写入配置文件跳过所有console.log的进度条只输出最终结果或错误启用--dry-run模式下的详细日志便于调试。这个参数的设计哲学是“自动化脚本应该像开关一样确定而不是像对话一样犹豫。” 我们在线上服务中所有定时任务都强制加上--yes确保任何异常都会立即暴露为错误日志而非挂起等待人工干预。5.3rag和mcp区别不是替代关系而是协作关系搜索“rag和mcp区别”时很多人误以为 MCP 是 RAG检索增强生成的竞品。事实恰恰相反MCP 是 RAG 系统的“能力注册中心”而 RAG 是 MCP 的一个典型应用场景。举个例子一个基于 MCP 构建的 RAG 工作流用户输入问题“如何在 React 中实现防抖”CLI 通过GET /capabilities发现当前 MCP Server 注册了一个rag-search能力CLI 构造 MCP 请求{ prompt: How to implement debounce in React?, capabilities: [rag-search] }MCP Server 接收到请求调用内部的向量数据库检索相关文档片段MCP Server 将检索结果注入到 Claude 的 prompt 中再调用 Anthropic API返回结构化答案。在这个流程里MCP 不负责检索算法、不存储向量、不训练模型它只负责“声明能力”和“路由请求”。RAG 的复杂性被封装在 MCP Server 内部而 CLI 保持极简。这就是为什么你会看到“workbuddy mcp skill”、“agent mcp”这些词——它们都是在 MCP Server 里注册的、可被 CLI 调用的原子能力。5.4linux 升级钉钉cli连不上github的启示环境变量污染是隐形杀手这个看似无关的搜索词其实揭示了一个通用陷阱全局环境变量会污染 CLI 的局部执行环境。当用户升级钉钉 CLI 后它可能修改了PATH或设置了GITHUB_TOKEN导致npx opencode/cli在执行时意外继承了这些变量进而影响到 MCP Server 的认证流程。我们的应对策略是在 CLI 的主入口文件中显式清理潜在的污染变量// src/index.js const cleanEnv { ...process.env }; delete cleanEnv.GITHUB_TOKEN; delete cleanEnv.NPM_CONFIG_REGISTRY; delete cleanEnv.HTTP_PROXY; delete cleanEnv.HTTPS_PROXY; // 后续所有子进程都使用 cleanEnv spawn(node, [lib/mcp-adapter.js], { env: cleanEnv });这种“白名单式环境清理”比依赖用户手动unset变量更可靠。它确保了 CLI 的行为在任何环境下都一致无论你的系统里装了多少个其他 CLI 工具。6. 模板的延展性从 Claude 到多模态、多协议的未来claude-code-templates的生命力不在于它今天能做什么而在于它为明天留出了多少扩展空间。它的架构设计天然支持三大方向的演进6.1 多模态输入--image参数的协议设计当前模板主要处理文本 prompt但 Anthropic 已支持图像输入。我们已在schemas/input.schema.json中预留了image_url字段image_url: { type: string, format: uri, description: URL of an image to include in the prompt. Supported by models with multimodal capability. }当mcp/anthropic-adapter.js检测到mcpRequest.image_url存在时会自动构造 Anthropic 的content数组const messages [ { role: user, content: [ { type: text, text: mcpRequest.prompt }, { type: image, source: { type: url, url: mcpRequest.image_url } } ] } ];这个设计的关键在于前端CLI只声明“我要传图”后端MCP Server决定“如何传图”。如果未来 Claude 支持新的图像编码格式只需更新适配器而 CLI 的--image https://xxx.jpg命令完全不变。6.2 多协议输出--format jsonvs--format markdown的底层实现--format参数的背后是一个可插拔的渲染器Renderer系统。src/renderers/目录下有markdown-renderer.js将 Claude 的content[0].text直接输出为 Markdownjson-renderer.js提取content[0].text并尝试JSON.parse()失败则包裹为{ raw: ... }confluence-renderer.js生成 Confluence 的 Wiki Markup 格式。CLI 的核心逻辑是const renderer require(./renderers/${options.format}-renderer.js); renderer.render(result);。这种设计让“输出格式”不再是硬编码的 if-else而是可独立发布的 NPM 包。比如社区贡献的opencode/renderer-slack就能让npx opencode/cli --format slack直接生成 Slack 消息块。6.3 多能力协同--with rag-search --with code-lint的能力组合MCP 协议的capabilities字段是数组这为能力组合打开了大门。claude-code-templates的--with参数允许链式调用