OpenCode + MCP 接入 NanoBanana:终端里一句话完成 AI 图像编辑
最近折腾了一段时间的 OpenCode把它当成日常主力终端助手之后我发现单纯用来写代码、改代码已经满足不了我了。直到我把 Ace Data Cloud 的 NanoBanana 图像编辑模型通过 MCP 协议接进了终端那种不切窗口、不打开浏览器、一句话直接改图的体验真的是用过就回不去。这篇文章就把我这次实战的完整过程记录下来包括选型思路、MCP 配置、最小可用实现、常见坑位和排查方法给想在终端里搭 AI 图像编辑能力的朋友一份可以直接抄的作业。1. 项目整体设计与思路拆解1.1 终端里的图像编辑到底解决了什么问题先说痛点。以前我在项目里要处理图片基本逃不过这几个场景给产品图换背景、调整配图尺寸、把截图里的水印区域做处理、批量给一组图调风格。传统做法是打开 Photoshop 或者在线工具一张一张操作。批量一点的用 Python 脚本调 Pillow但改图逻辑复杂的时候脚本写起来也头大。再后来有 AI 修图工具了又要在浏览器里传图、写提示词、等结果、下载再回来继续写代码。工具链一长注意力就被切碎了。把 AI 图像编辑接进终端本质上是把图像处理能力变成开发工作流里的一个函数。你在终端里一行自然语言模型完成编辑返回结果图片路径。整个过程不离开命令行也不打断编码思路。对我这种长期泡在终端里的人效率提升不是一点半点是工作流层面的整合。1.2 为什么选 OpenCode MCP而不是别的方案市面上终端 AI 助手不少Claude Code、Codex CLI、Cursor 的命令行模式各有各的长处。我最终选 OpenCode原因有几个。第一它在终端里的交互体验做得比较细腻多模型切换很顺滑免费模型和商业模型都能挂。第二它对 MCP 的支持是原生级别配置一个 JSON 就能把外部工具接进来不需要写插件或者 hack。第三它足够开放不绑定某一家模型我自己有 NanoBanana 的 API Key直接能往里塞。MCP 这个协议是选择的关键。如果没有 MCP我想把图像编辑能力接进终端就得给 OpenCode 写插件或者自己搞一套进程通信方案那工作量就大了。MCP 把模型与外部工具之间的连接方式标准化了我只需要实现一个 MCP Server把 NanoBanana 的 API 包装成工具OpenCode 就能自动发现并调用。这就是标准化的价值。还有一个加分项OpenCode 支持多 Agent 和 Skills 机制。这意味着我不光能调图像编辑工具还能把读取图片、调用编辑、保存结果、写日志串成一条自动化链路这个后面实战部分我会细说。1.3 整体架构一句话说清楚链路整个链路不算复杂我画个思路给大家拆开看OpenCodeMCP Host ↓ 通过 MCP 协议stdio / HTTP MCP ServerNanoBanana Adapter ↓ 通过 HTTPS 调用 REST API Ace Data Cloud NanoBanana 图像编辑模型 ↓ 返回编辑后的图片数据 MCP Server 保存文件并返回路径 ↓ 结果回传给 OpenCode 终端里直接看到输出和结果OpenCode 在这一架构里扮演的是 MCP Host也就是发起方我写的那层适配服务是 MCP Server负责把自然语言指令翻译成 NanoBanana API 参数再把结果转换成 OpenCode 能识别的格式。要注意MCP Server 不一定要自己写如果官方或者社区已经提供了现成的 NanoBanana MCP Server直接配置 URL 就行。我做这期实战的时候官方适配服务已经支持常见图像编辑操作了但如果你想定制编辑逻辑自己搓一个也不难后面第 3 章会给一个最小实现示例。2. 核心概念MCP、OpenCode 与 NanoBanana 速览2.1 MCP 协议AI 世界的万能插座MCP 全称 Model Context Protocol也就是模型上下文协议。你可以把它理解成 AI 应用和外部世界之间的USB-C 接口。在 MCP 出现之前AI 要调用外部能力基本是各家搞各家的OpenAI 有 Function CallingAnthropic 有 Tools开源项目再各自包装一套 JSON-RPC 通信开发者每接一个助手就要写一遍适配逻辑。MCP 把这件事标准化了只要 MCP Server 实现了协议任何支持 MCP 的客户端都能直接用。MCP 协议里最常见的三个原语是tools、resources和prompts。图像编辑这种能力对应的是 tools也就是工具。一个工具包含名字、描述、输入参数 Schema 和实际执行逻辑。OpenCode 通过 MCP 客户端列出服务器提供的工具列表根据用户的自然语言描述自动选择调用哪个工具、传入什么参数。整个调用链路对用户是透明的你只需要在终端里说需求就行。传输方式上本地开发最常用的是stdio也就是 OpenCode 启动一个子进程通过标准输入输出和 MCP Server 通信。远程场景可以用 HTTP SSE。我这次实战用的是 stdio因为适配服务就在本机跑省去网络开销排查问题也方便。2.2 OpenCode终端 AI 助手里的一匹黑马OpenCode 是 SST 团队开源的一款终端 AI 编程助手。它最大的特点是在终端里给你一个完整的 AI 协作环境你能直接让它读项目代码、改文件、执行命令还可以通过 MCP 挂载各种外部工具。界面是 TUI 风格不花哨但该有的都有对话历史、Diff 预览、Token 用量统计、模型切换面板。安装方式很简单只要本机有 Node.js 18 以上版本执行一条命令就能装好这个我在第 3 章会演示。OpenCode 支持的主流模型服务商几乎全覆盖从 OpenAI、Anthropic 到 Ollama 本地模型都可以配置。它还有一个很实用的功能可以设置不同项目的模型偏好比如这个项目用便宜的模型那个项目用更强的模型方便控制成本。OpenCode 对 MCP 的支持做得非常直观。全局 MCP 写在~/.config/opencode/opencode.json项目级 MCP 写在当前目录的opencode.json里。配置项就是标准的 MCP 客户端格式指向 MCP Server 的启动命令或者 URL。它启动时会自动发现这些配置把工具列表合并到对话上下文里。也就是说我不用每次手动声明我有一个图像编辑工具配置好之后模型自己就知道该用哪个。2.3 NanoBananaAce Data Cloud 的多模态图像模型NanoBanana 是 Ace Data Cloud 平台推出的多模态模型主打图像理解与编辑能力。和传统 CV 模型不太一样NanoBanana 走的是理解生成的路线它能看懂图里的物体、场景、关系然后根据自然语言指令对图片做修改。常见的操作包括物体替换、背景重绘、风格迁移、图片扩展、清晰度修复等。我用下来感觉它的优势在于指令理解比较自然。比如你说把左边的人去掉用背景填充它不需要你精确标注坐标框直接理解语义然后执行。API 调用方式也简单本质上就是发送一张图片和一段文本指令模型返回编辑后的图片。Ace Data Cloud 提供了标准的 REST 接口也支持在多个主流云平台上一键部署所以接入成本不高。需要说明的是我在本次实战里是直接调用 NanoBanana 的 HTTP API通过自建的 MCP Server 做适配。如果你拿到的 API 格式跟我不完全一样没关系核心思路是一样的把图像编辑能力抽象成工具的输入输出剩下的交给 MCP 协议。3. 实操过程与核心环节实现3.1 环境准备装好 Node.js 和 Python动手之前先把环境准备好。OpenCode 依赖 Node.js我建议直接用 18 以上的 LTS 版本npm 随 Node.js 一起装上。检查方法很简单终端里跑两条命令node -v npm -v看到版本号输出就行。如果你的机器上还没有 Node.js推荐用 nvm 安装方便后续切换版本。另外后续我写 MCP Server 示例用的是 Python因为 Python 在处理图片和调用 HTTP API 上最省事。建议装 Python 3.10 以上版本并且准备好requests库python3 --version pip install requests提示如果你更习惯 Node.js 写 MCP Server也没问题协议本身跟语言无关。我后面给的示例是 Python 版但逻辑在 Node 里同样能实现。3.2 安装 OpenCode 并完成基础配置一切就绪后安装 OpenCode 只需要一条命令npm install -g opencode-ai装完之后直接输入opencode就能启动。首次启动需要配置模型服务商。OpenCode 配置文件默认在~/.config/opencode/opencode.json如果你跟我一样不想手动建目录可以在 OpenCode 里输入/config命令它会自动生成一个可以编辑的配置文件。我的基础配置长这样{ $schema: https://opencode.ai/config.json, model: gpt-4o, provider: { openai: { api_key: 你的上头 API Key, model: gpt-4o } } }你完全可以换成自己喜欢的模型。OpenCode 在启动时会给模型发送系统提示词列出当前可用的工具。挂上 MCP 之后模型会自动感知到图像编辑工具的存在不需要额外在提示词里写你会调用图像编辑工具这种话。3.3 获取 NanoBanana 的 API Key接下来去 Ace Data Cloud 平台。注册账号之后在控制台找到 API Key 管理页面生成一个专属 Key。拿着 Key 看文档里图像编辑接口的调用说明通常你会需要知道三个关键信息接口的 URL、请求头的鉴权方式、请求体的字段格式。这里我说明一下不同区域的 Ace Data Cloud 控制台地址不完全一样但操作路径基本一致都是在API 凭证或者Access Keys里新建一个 Key。拿到之后建议立刻把它存到一个环境变量里不要写死到代码中。export NANOBANANA_API_KEY你的Key3.4 编写一个最小的 MCP Server把图像编辑能力暴露出来这是整个实战最核心的一步。我们要写一个 MCP Server监听 stdio 传来的 JSON-RPC 请求把图像编辑能力以工具的形式暴露出来。由于 MCP 的握手、工具发现、调用流程需要严格按照协议规范实现我先给一个最简版它包含三个关键环节初始化响应、工具目录列出、工具调用。#!/usr/bin/env python3 import json import sys import os import requests NANOBANANA_API_KEY os.environ.get(NANOBANANA_API_KEY, ) EDIT_ENDPOINT https://api.ace-datacloud.com/v1/nanobanana/edit def read_message(): # MCP stdio 协议消息以 Content-Length 为前缀 content_length 0 while True: line sys.stdin.readline() if not line: return None line line.strip() if line.startswith(Content-Length:): content_length int(line.split(:)[1].strip()) if line : break if content_length 0: return None payload sys.stdin.read(content_length) return json.loads(payload) def write_message(obj): payload json.dumps(obj).encode(utf-8) sys.stdout.write(fContent-Length: {len(payload)}\r\n\r\n) sys.stdout.write(payload.decode(utf-8)) sys.stdout.flush() def handle_initialize(): return { protocolVersion: 2024-11-05, capabilities: {tools: {}}, serverInfo: {name: nanobanana-mcp, version: 0.1.0} } def handle_tools_list(): return { tools: [ { name: edit_image, description: 使用 NanoBanana 模型编辑图像支持换背景、抠图、调色、物体替换等任务。传入图片路径和自然语言编辑指令。, inputSchema: { type: object, properties: { image_path: { type: string, description: 待编辑图片的本地路径或 URL }, instruction: { type: string, description: 用自然语言描述想要的编辑效果 }, output_path: { type: string, description: 编辑结果的保存路径默认写到同目录的 nanobanana_output.png } }, required: [image_path, instruction] } } ] } def call_edit_image(args): image_path args.get(image_path) instruction args.get(instruction) output_path args.get(output_path, os.path.join(os.path.dirname(image_path), nanobanana_output.png)) with open(image_path, rb) as f: files {image: f} data {instruction: instruction} headers {Authorization: fBearer {NANOBANANA_API_KEY}} resp requests.post(EDIT_ENDPOINT, headersheaders, filesfiles, datadata) resp.raise_for_status() result resp.json() if image in result: with open(output_path, wb) as f: f.write(result[image].encode(latin1)) return {content: [{type: text, text: f图片编辑完成结果已保存到 {output_path}}]} else: return {content: [{type: text, text: f调用失败{result}}]} def handle_tools_call(request): params request.get(params, {}) tool_name params.get(name) arguments params.get(arguments, {}) if tool_name edit_image: try: result call_edit_image(arguments) return {content: result.get(content, [{type: text, text: 执行完成}])} except Exception as e: return {content: [{type: text, text: f图像编辑报错{str(e)}}]} return {content: [{type: text, text: f未知工具: {tool_name}}]} def main(): while True: msg read_message() if msg is None: break method msg.get(method) if method initialize: write_message({jsonrpc: 2.0, id: msg.get(id), result: handle_initialize()}) elif method tools/list: write_message({jsonrpc: 2.0, id: msg.get(id), result: handle_tools_list()}) elif method tools/call: write_message({jsonrpc: 2.0, id: msg.get(id), result: handle_tools_call(msg)}) elif method notifications/initialized: write_message({jsonrpc: 2.0, id: msg.get(id), result: {}}) if __name__ __main__: main()这段代码的核心逻辑并不复杂。MCP 通过带Content-Length头部的 JSON-RPC 消息通信read_message做的是解析标准输入里的协议帧write_message负责把响应写回标准输出。tools/list返回工具目录声明了edit_image这个工具以及它的参数格式tools/call接到调用请求后把图片文件和指令发给 NanoBanana API然后把结果图片保存到本地。注意我这里用的是简化版协议处理。生产环境建议直接用官方 MCP SDK它已经把协议层封装好了能少踩很多边界条件的坑。Python 可以看mcp官方库Node.js 看modelcontextprotocol/sdk。我后面会在常见问题里展开讲。3.5 在 OpenCode 中注册 MCP Server把上面的 Python 脚本保存成nanobanana_mcp.py然后修改 OpenCode 的配置文件把这个 MCP Server 注册进去。我这里用项目级配置举例在当前项目的opencode.json中加入{ mcp: { nanobanana: { type: stdio, command: python3, args: [/path/to/nanobanana_mcp.py], env: { NANOBANANA_API_KEY: 你的Key } } } }注意env里的 Key 可以写在配置里也可以省略直接依赖系统环境变量。为了安全我更推荐后者。保存配置后重启 OpenCode模型会自动感知到这个 MCP 工具。你在对话里问一句你现在有哪些图像编辑能力模型通常会把edit_image工具的使用方式总结出来。3.6 端到端测试一句话让 AI 改图基础配置完成现在来验收。我先准备一张测试图片放在项目目录下然后打开 OpenCode输入把 this.jpg 的背景换成夜空的星空人像保持不变保存为 new_this.pngOpenCode 会把这句话解析成工具调用自动给edit_image传参。执行过程中你能在终端里看到工具调用的详细记录包括模型选择了什么指令、传了什么参数。大概几秒钟后模型回复图片编辑完成结果已保存到 new_this.png。我实测这个流程跑通的那一刻有点小激动——以前要打开网页上传图片、写提示词、下载的流程现在一句话就在终端里完成了而且是直接嵌在我写代码的语境里。而且因为图片路径是本地路径后续我可以在同一个会话里继续让模型做二次编辑、生成 HTML 页面展示、甚至写一段 Python 脚本处理同一目录下的其他图片整个工作流是非常连贯的。4. 实战把图像编辑指令玩出花4.1 常见指令与提示词模板工具跑通了接下来就是怎么用得顺手。我在实际使用中总结了一些高频率的指令模板可以直接复制进 OpenCode 对话里。注意控制好指令的颗粒度太模糊的指令模型会自由发挥太死板的指令又限制了模型的理解空间。给一个参考背景替换把 {图片路径} 的背景替换为 {场景描述}保持前景主体不变抠图把 {图片路径} 中的 {物体} 抠出来背景改为透明调色让 {图片路径} 的画面更通透明亮色调偏暖一点物体移除把 {图片路径} 中 {位置/描述} 的物体移除用周围环境自然填充风格迁移把 {图片路径} 转成日系动漫风格图片扩写扩大 {图片路径} 的画布把周围环境合理地补全实际效果相当稳定。有一次我拿一张产品图要求把产品放在一个木质桌面上带柔和自然光模型处理得比我想象中自然阴影和反光都处理得比较合理。还有一次是团队活动合照我想把背景从室内换到草地人脸边缘基本没出现明显的抠图痕迹。4.2 批量处理与脚本化工作流单张图片处理只是开胃菜。接进终端最大的好处是能跟脚本和命令组合使用。配合 OpenCode 的 Agent 能力我可以让它一口气处理整个目录下的图片遍历当前目录的 ./raw_images 文件夹把所有 jpg 图片统一调亮一档调整成 1024x1024 方形保存到 ./processed_imagesOpenCode 会自己写一段循环脚本逐个调用图像编辑工具或者直接生成 Python 代码批量处理。这种AI 自动读目录、自动处理、自动保存的体验在以前需要我先手写脚本再逐个验证现在基本一句话搞定。如果你想更精细地控制批量任务还可以在 MCP Server 侧增加一个batch_edit_images工具输入一个图片列表和统一指令返回处理结果列表。这样调用一次就完成整批任务效率和 Token 消耗都更友好。4.3 和其他 MCP Server 组合的玩法MCP 协议最迷人的地方在于可组合性。除了 NanoBanana我还在 OpenCode 里挂了文件系统 MCP Server 和 Git MCP Server。组合起来可以实现一些很有意思的工作流。比如设计团队给我发来 UI 切图我可以直接让 AI 读取图片、自动重命名、批量压缩、然后推到 Git 仓库全程不离开终端。再比如写技术文章时我让 AI 基于某个截图生成配图说明再自动把图片尺寸统一插入到 Markdown 文档里。工具之间通过模型统一调度省掉了很多手动切换的步骤。当然MCP 的工具组合也有讲究后面我会说一些控制工具数量的建议工具太多反而会干扰模型的判断。5. 常见问题与排查技巧实录5.1 高频问题速查表我在整个接入和调试过程中遇到过不少问题这里整理成一张速查表基本覆盖了 90% 的坑现象可能原因排查和解决方案OpenCode 启动时提示 MCP Server 连接失败MCP Server 进程启动报错或者 stdio 通信帧格式不对先手动执行python3 nanobanana_mcp.py看有没有报错再检查Content-Length头是否正确推荐换用官方 MCP SDK模型说找不到图像编辑工具MCP Server 没有正确注册或配置 JSON 写错检查opencode.json里的command和args是否指向正确的脚本路径重启 OpenCode用/mcp命令查看当前 MCP 状态调用工具时报认证错误API Key 没传对或者环境变量没生效在终端执行echo $NANOBANANA_API_KEY确认有值如果使用env字段配置注意 JSON 转义返回图片保存失败输出路径不存在或 API 返回的图片字段格式不是预期格式确保输出目录已创建先打印 API 响应结构确认image字段的实际格式二进制还是 Base64图片编辑效果不理想提示词不够清晰或图片本身分辨率过低把指令写得更具体比如增加位置、色彩、材质描述原图尽量用高分辨率图片工具调用参数被模型猜错工具描述和参数 Schema 写得不够清晰优化description把常见用法写进描述给参数增加enum或default值约束批量处理时频繁超时单张图片处理时间过长网络不稳定在 MCP Server 侧增加超时重试逻辑用异步方式并行处理多张图片5.2 我踩过的几个坑第一个坑是 MCP stdio 协议的手写解析。一开始我没用官方 SDK自己解析Content-Length前缀结果在 Windows 下换行符不同导致消息解析错位OpenCode 一直说连接失败。折腾半天后发现是\r\n和\n混用的问题。所以如果只是正常使用建议直接用官方 MCP SDK别重复造轮子。第二个坑是工具描述写得太简短。最开始我把edit_image的描述写成编辑图片模型经常不知道该传几个参数有时漏传instruction有时把image_path和instruction搞混。后来我参考 Claude 的工具描述规范把描述改成带示例的详细说明模型调用的准确率明显上升。工具描述就是模型的使用说明书值得多花几分钟写清楚。第三个坑和环境变量有关。我在配置里用env字段传 API Key结果 Key 里有个特殊字符JSON 格式没转义导致 MCP Server 启动就报错。排查了半天才发现是配置解析的问题。后来我干脆不往配置文件里放密钥了直接在.bashrc或.zshrc里 export让 Python 进程从环境里读省心很多。第四个坑是关于模型自主选择工具的过滤机制。我在 OpenCode 里挂了多个 MCP Server 后发现模型偶尔会选错工具比如明明要编辑图片却调了文件系统的写入工具。解决方法是把每个 MCP Server 的工具数量控制住只暴露必要的工具并且在关键工具的描述里写清楚使用场景和优先级。工具越少模型的选择准确率越高。重要提示MCP Server 的env配置块在 OpenCode 里是可选的。我强烈建议把关键密钥放到系统环境变量而不是明文写在opencode.json里避免配置文件被误提交到 Git 仓库。5.3 排查 MCP 调用链路的基本技巧遇到问题不要慌按链路逐段排查效率最高。先确认 MCP Server 进程本身是否正常启动可以在终端单独执行启动命令直接在里面手动发几个 JSON-RPC 请求验证。接着看 OpenCode 的日志输出它启动时会打印 MCP 连接状态和工具列表。最后再关注 NanoBanana API 侧的响应在 MCP Server 里加一行日志把请求参数和返回状态打出来。三层链路逐层确认基本能锁定问题出在哪一段。我还习惯在 MCP Server 里加一个ping工具专门用来测试连通性。模型调用这个工具能确认密钥、网络、服务状态是否正常省去很多无谓排查。6. 一些实在的经验总结整个项目跑下来我最深的一个感受是MCP 的价值不在于某一个工具接得好而在于它让 AI 从只能聊变成了能干活。图像编辑只是我接的第一个能力后面我打算把更多日常任务都通过 MCP 暴露到终端里比如数据库查询、CI 触发、云资源操作都可以按同样的思路接进来。在实操层面几个习惯帮我省了不少事。第一MCP Server 尽量保持简单和单一职责一个 Server 只做一件事比如图像编辑就只管图像编辑不要什么都往里塞。第二工具描述和参数 Schema 是沟通的关键多花点时间把描述写好模型的调用准确率会显著提升。第三密钥管理一定要用环境变量别写进配置文件。第四调试时先用最简单的工具验证链路再逐渐增加复杂度。最后再分享一个小技巧在 OpenCode 里可以用/mcp命令随时查看已连接的 MCP Server 和工具列表方便快速确认配置是否生效。如果你一开始搭不起来也可以先用社区现成的 NanoBanana MCP Server 跑通流程再回来研究定制化实现。先把链路走通再逐步优化这是所有工具集成交接项目里最稳妥的路线。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →