NanoBanana 这个名字,如果你最近关注 AI 圈,应该不陌生。它是 Lepton AI 在 Ace Data Cloud 上主推的视觉语言模型,图像理解和编辑能力在同级别里相当能打。而我今天想聊的,不是怎么在网页上用它的 Demo,而是怎么把它和 OpenCode 这个终端 AI 编程工具串起来,配合 MCP 协议把 AI 图像编辑接到命令行里。
先交代一下背景。我最近在折腾自动化工作流,发现最烦人的不是写代码,而是场景切换:改图要去 GUI 软件里手点,写处理脚本要先看图片再手工调参数,模型能力再强也跟本地文件系统隔着一层。OpenCode 解决了一部分问题,它本身就是终端里的 AI Agent,能读文件、跑命令;但要让模型真正"看见图、改图、看图确认",还需要两个东西:一个视觉能力强的模型,一个能让模型操作图像工具的通道。前者我选了 NanoBanana,后者就是 MCP。
这篇文章会把我的完整配置过程、踩过的坑、能直接抄的配置文件和命令都写出来。不管你是做前端切图、自动化脚本、还是批量素材处理,只要想在终端里完成"看一眼图然后动手改"这个闭环,这篇实战记录应该能给你省下不少时间。下面开始。
1. 先说结论:终端里做图像编辑,图的是什么
1.1 几个每天都在想解决的真实痛点
我最早想干这事,是因为一个很琐碎的需求:每周要给一批活动 banner 统一换标题文字,而且图片里还有不同位置的 logo 需要替换。人工用 Photoshop 处理,一张图少说两分钟,几十张图就是一下午。写脚本吧,又得先人工看完每张图,记录坐标、颜色、字体位置,再回来改代码——这个"看图 → 记参数 → 改脚本"的过程比手点还慢。
后来我试着让大模型直接看图并生成处理参数,发现通用模型对图像的局部细节理解不够,经常把坐标估偏。NanoBanana 这一代视觉模型在目标定位和区域理解上明显强一些,能直接描述"左上角 120x80 的位置有个深色方块 logo"。这让自动化变成了可能:模型负责理解画面和生成编辑指令,脚本或工具负责执行,终端负责把这一切串起来。
1.2 这套方案到底能解决什么
把 AI 图像编辑接进终端,核心解决的是三个问题:
- 减少工具切换:不用在浏览器、图片编辑器、IDE 之间反复横跳,所有操作留在终端上下文里。
- 让模型可以操作真实文件系统:MCP 协议给了模型一个标准化的"工具箱",模型可以调用图像处理工具,而不是只输出没法直接执行的建议。
- 把图像处理变成可复用的自动化流程:一次配置好,以后批量任务可以通过会话或脚本直接完成,人工只在关键节点确认。
当然,这条路径不是万能的。它更擅长参数明确的操作,比如缩放、裁剪、格式转换、局部区域替换、批量加水印。如果是要生成光影复杂的创意合成图,那还是跑去专业生图工具里更靠谱。认清这个边界,你就知道该在哪投入精力。
2. 技术底座:四个角色分别负责什么
2.1 OpenCode 是"运行环境"
OpenCode 是开源社区里热度上涨很快的终端 AI Agent 工具,可以把它理解为命令行版本的 Cursor 或 Claude Code。它能读取仓库、执行命令、管理多文件修改,并且支持通过配置文件接入不同模型服务商。
和直接在 Python 脚本里调 API 相比,OpenCode 最大的优势是带 Agent 循环:它能把一个大任务拆成多步,每一步自己决定调用哪个工具、读哪个文件、跑哪条命令。我们要做的图像编辑任务,本质上也是 Agent 循环里的一个环节。
在 OpenCode 的架构里,模型负责决策,工具负责执行。它原生支持 MCP,可以在配置里挂载任意 MCP Server。这样我们不需要改 OpenCode 源码,只需要配置好模型和工具服务。
2.2 NanoBanana 是"眼睛和大脑"
NanoBanana 是 Lepton AI 推出的视觉语言模型,名字听着像个水果,实际能力在同级别里很能打。它最突出的点是视觉理解精度:能识别图像中的物体位置、相对尺寸、文字内容,还能理解指令并输出结构化操作描述。
在整套链路里,我把它当作 Agent 的决策模型用。不是让 OpenCode 调用它做个简单问答,而是让它在"看到图片内容"的基础上,决定下一步该调用什么图像操作、传什么参数。比如模型看到一张图,判断"右下角需要缩小占比 30% 再向右移动 20 像素",然后告诉工具服务器去执行。这比人类手写规则灵活太多。
2.3 Ace Data Cloud 是"模型接入层"
Ace Data Cloud(简称 ACD)是 Lepton AI 的模型服务平台,提供 NanoBanana 等模型的 API 接入。它支持 OpenAI 兼容的接口格式,这意味着 OpenCode、以及其他常见 SDK 都能直接用标准方式调用,不需要写适配代码。
我选择通过 ACD 接入,主要看重三点:一是接口标准,现有工具链零改造就能对接;二是模型版本更新不用自己管,云端直接升级;三是密钥隔离,可以在不同环境里分别配置权限。对个人开发者来说,这也省去了自己部署视觉模型的硬件成本。
2.4 MCP 是"万能插头"
MCP(Model Context Protocol)是 Anthropic 去年推出来的开放协议,目的是统一模型与外部工具之间的交互方式。你可以把它理解成 USB-C:只要设备支持这个标准,插上就能用,不用管另一头是什么牌子。
MCP 定义了两种角色:
- MCP Host:模型运行和决策的地方,比如 OpenCode。
- MCP Server:提供具体工具服务的地方,比如图像编辑服务。
两者通过 JSON-RPC 通信,传递工具列表、函数调用参数、执行结果。对模型来说,它"看到"的是一组可调用的函数;对工具提供方来说,只需要实现协议规定的接口,就能被任意支持 MCP 的客户端调用。
这套标准的意义在于解耦。今天想换个图像处理引擎,只要 MCP Server 接口不变,OpenCode 那边一行不用改。
3. 原理拆解:一次"AI 改图"请求在终端里是怎么跑通的
3.1 请求流转链路
我实际把链路搭通之后,梳理了一下一次改图请求的完整流转过程,大致分成六步:
- 用户在 OpenCode 里输入指令,例如"把 assets/hero.png 里的主标题文字改成‘新品发布’"。
- OpenCode 的 Agent 循环启动,把任务交给 NanoBanana 模型进行意图理解。
- NanoBanana 发现自己需要先"看图",于是调用 MCP Server 的
read_image工具获取图片的尺寸、布局、文字区域等信息。 - 模型基于图像信息生成具体编辑决策,再次通过 MCP 调用
edit_image工具,传入目标区域、文字内容、样式参数。 - MCP Server 执行实际图像处理,返回执行结果(成功/失败、耗时、输出路径)。
- NanoBanana 汇总结果,OpenCode 把摘要返回给用户。
这整个过程中,模型不是一次性返回所有指令,而是每完成一步就观察结果、决定下一步。这样能处理复杂任务,比如先定位 logo,再改颜色,最后压缩导出。
3.2 为什么用 MCP 而不是直接调脚本
肯定有人会问:我直接写个 Python 脚本调用图像处理库,不也一样吗?为什么绕一圈用 MCP?
原因在于动态决策能力。脚本的问题是参数得人先定好,而图像内容千变万化,没法预设所有参数。MCP 让模型在运行时根据"看"到的内容来决定参数,等于把改图的决策权交给了 AI,而不是固定在代码里。
举个例子:普通脚本裁剪图片得告诉它"从左上角 (10,10) 开始裁 200x200 区域"。MCP 模式下,模型先读图,识别出人脸位置偏左,自动算出偏移量,再决定裁剪范围。这个"识图 → 计算 → 执行"的过程,用传统脚本实现非常复杂,但用 MCP 就是两个工具调用的事。
另外,MCP 是一个开放标准。今天接图像编辑,明天接图片压缩,后天接对象存储,都是同一个协议。插件化扩展的成本极低,这也是我不想用私有方案的原因。
4. 实操准备:环境、账号、密钥一个不能少
4.1 安装 OpenCode
OpenCode 支持多种安装方式,我用的是 npm 全局安装,一条命令搞定:
npm install -g opencode-ai装完先确认版本,避免老版本对 MCP 支持不全:
opencode --version如果网络环境比较特殊导致 npm 装得慢,也可以去 GitHub Releases 页下载对应平台的二进制包,解压后把可执行文件放进PATH目录就行。
4.2 在 Ace Data Cloud 上拿 NanoBanana 的 API Key
打开 Ace Data Cloud 控制台,注册或登录账号,进到 API Keys 页面生成一个密钥。这个密钥是后面所有请求的通行证,建议单独建一个 Key,别跟其他服务混用,方便出问题时单独吊销。
拿到 Key 之后,先在本地环境变量里配好:
export ACD_API_KEY="你的密钥"注意:不要把 Key 硬编码到任何配置文件里,更不要提交到 Git 仓库。OpenCode 的配置支持从环境变量读取,我们后面会利用这个特性。
4.3 创建项目目录并初始化
我习惯每个自动化场景建独立目录,方便隔离配置:
mkdir image-agent-demo && cd image-agent-demo opencode initopencode init会自动生成默认配置文件opencode.json,后面两步的模型配置和 MCP 配置都会写进这个文件。如果你用的是老版本,配置文件也可能是opencode.json或config.json的形式,以实际为准。
4.4 准备一张测试图片
为了后面跑通全流程,我在assets/目录放了一张包含标题文字和 logo 的示例图。建议你也准备一张结构清晰、元素分明的图,这样能明显感受到模型"看得到"和"看不到"的差别。
5. 让 OpenCode 认识 NanoBanana:模型配置实战
5.1 理解 OpenCode 的 Provider 机制
OpenCode 不绑定某个固定模型,它通过 provider 机制来区分不同的模型服务方。每个 provider 定义了访问地址、鉴权方式、模型列表。NanoBanana 走的是 OpenAI 兼容接口,所以我们可以用openai-compatible类型的 provider 把它注册进去。
这个设计很实用:同一个 OpenCode 里可以同时配置本地 Ollama、云端 NanoBanana、以及其他商业模型,会话时随时切换,不用改主题配置。
5.2 在 opencode.json 里配置 Ace Data Cloud Provider
打开opencode.json,在provider字段里新增一个名为acd的条目:
{ "$schema": "https://opencode.ai/config.json", "provider": { "acd": { "npm": "@ai-sdk/openai-compatible", "name": "Ace Data Cloud", "options": { "baseURL": "https://api.ace-data-cloud.com/v1", "apiKey": "{env:ACD_API_KEY}" }, "models": { "nanobanana": { "name": "NanoBanana", "limit": { "context": 131072, "output": 4096 } } } } }, "model": "acd/nanobanana" }几个关键点说明一下:
npm字段指定了 SDK 适配器。OpenAI 兼容接口用@ai-sdk/openai-compatible,这是 AI SDK 的官方适配器。options.baseURL指向 ACD 的 OpenAI 兼容端点。不同项目的端点前缀可能略有差异,以你账号后台显示的为准。options.apiKey用{env:ACD_API_KEY}引用环境变量,比明文写在配置里安全得多。limit里声明了上下文长度和最大输出 token 数,OpenCode 会根据它做 token 估算和分流。
配置完后重启 OpenCode,或者跑一下模型列表命令,确认能正确读到模型:
opencode models5.3 第一次纯文本调用验证
我的习惯是先用最简单的文本任务验证接入是否正常,不要一上来就跑图像任务,否则出错时不好定位是模型问题还是工具问题。
在 OpenCode 会话里输入:
用一句话说明 NanoBanana 接入是否成功。如果返回正常的文本回复,说明模型链路已经通了。此时如果报类似error from provider (console)的错误,通常是模型名或 provider 配置不对,需要检查模型 ID 是否写成了acd/nanobanana这种标准格式。
这里插一句,我在网上看到不少人遇到opencode's free tier can only be used from within opencode这个报错。这个不是 ACD 的问题,而是 OpenCode 自带的免费模型队列只允许在官方控制台界面内使用,第三方接入时会被拒绝。解决办法就是配一个自己的模型源,别依赖内置免费档。
6. 挂载图像编辑 MCP Server:让模型有"手"
6.1 选型:现成的还是自建的
图像编辑 MCP Server 目前没有像文件系统 MCP 那样大一统的标准实现。你可以选择社区现成的服务,也可以根据自己的图像处理需求写一个轻量 Server。我的情况比较特殊,需要批量替换文字和坐标定位,现成方案很难满足,所以我选择自建一个。
自建 MCP Server 没有想象中复杂。核心就是实现三件事:
- 暴露工具列表(工具名、参数 schema、描述)。
- 接收模型发来的调用请求。
- 执行操作并返回结构化结果。
6.2 自建一个基于 Sharp 的轻量 MCP Server
我用 Node.js + Sharp 写了一个最小可用的图像 MCP Server。Sharp 是高性能图像处理库,支持格式转换、缩放、裁剪、像素级操作,够覆盖大部分需求。
项目结构很简单:
image-mcp-server/ ├── package.json ├── index.js先初始化项目并安装依赖:
mkdir image-mcp-server && cd image-mcp-server npm init -y npm install sharp @modelcontextprotocol/sdk然后写index.js:
const { McpServer } = require('@modelcontextprotocol/sdk/server/mcp.js'); const { StdioServerTransport } = require('@modelcontextprotocol/sdk/server/stdio.js'); const sharp = require('sharp'); const server = new McpServer({ name: 'image-edit-server', version: '1.0.0' }); server.tool( 'read_image', { image_path: { type: 'string', description: '图片路径' } }, async ({ image_path }) => { const metadata = await sharp(image_path).metadata(); return { content: [{ type: 'text', text: JSON.stringify(metadata) }] }; } ); server.tool( 'resize_image', { image_path: { type: 'string' }, width: { type: 'number' }, height: { type: 'number' } }, async ({ image_path, width, height }) => { const output_path = image_path.replace('.png', '-resized.png'); await sharp(image_path).resize(width, height).toFile(output_path); return { content: [{ type: 'text', text: `已生成 ${output_path}` }] }; } ); const transport = new StdioServerTransport(); await server.connect(transport);这个实现虽然简单,但结构完整,模型能通过 MCP 协议调用到read_image和resize_image两个能力。你完全可以根据业务需要加接口,比如crop_image、add_text、replace_color等。
6.3 在 OpenCode 里注册这个 MCP Server
回到opencode.json,在mcp字段里注册我们刚写的服务:
{ "mcp": { "image-edit": { "type": "local", "command": ["node", "/absolute/path/to/image-mcp-server/index.js"] } } }这里的type表示本地进程型 MCP Server,OpenCode 会直接启动这个命令并通过 stdio 与它通信。所以路径一定要写绝对路径,不要写相对路径,否则服务起不来。
配置完后,在 OpenCode 里执行:
你能看到哪些 MCP 工具?如果模型正确回答了read_image和resize_image,说明 MCP 链路已经打通。
6.4 验证 MCP Server 的边界情况
第一次跑通后,建议花几分钟测几个边界情况,这些坑我全踩过:
- 中文路径:图片路径含中文时,部分图像库处理正常但 OpenCode 解析参数可能出问题,最好统一用英文路径。
- 大图内存:Sharp 处理超大图会吃满内存,建议在 Server 里加文件大小判断,超过阈值先压缩再处理。
- 错误返回格式:工具出错时也要按 MCP 格式返回
content数组,不要直接 throw,否则 Agent 循环会中断。
7. 实战场景:从"看图"到"改图"三种典型用法
7.1 场景一:让模型描述图片信息并给出处理建议
我拿到一张图,不知道具体参数时,会直接让 OpenCode 里的 Agent 读图:
读取 assets/banner.png,告诉我: 1. 图片尺寸和格式 2. 主体元素大概在什么位置 3. 如果要放大主体元素 30%,你觉得怎么处理最自然NanoBanana 会先调用read_image获取图片元数据,再基于视觉理解输出答案。这一步看起来简单,但它验证了"模型有能力把图像内容转化为可执行建议",是后续自动化编辑的前提。
实测下来,NanoBanana 对区域描述的准确度比早期的视觉模型好很多,能说出"主体偏左,约占整图宽度 45%",而不是给出模糊的"中间偏左"。
7.2 场景二:根据指令自动调整图片尺寸
假设我们有需求,把所有 banner 统一压成 1600x900,并加上一个 100px 的顶部留白。直接在 OpenCode 里输入指令:
把 assets/ 下所有 png 图片统一调整为 1600x900,保持居中裁剪,输出到 output/ 目录,文件名保持不变。这个任务如果靠通用聊天窗口,模型只能给你一段建议代码,你还得自己保存、改路径、跑脚本。但在 OpenCode + MCP 的组合下,Agent 会自己枚举目录、逐个调用 MCP 工具、处理异常、最后汇总报告。
我实际跑下来,OpenCode 的 Agent 循环会先执行目录遍历,再把每张图分批交给 MCP Server 处理。中途如果某张图损坏,Agent 不会直接退出,而是记录错误继续处理下一张,最后统一告诉你哪些成功哪些失败——这是脚本方式很难优雅实现的。
7.3 场景三:组合操作——定位 logo、替换颜色、重新导出
更贴近真实需求的场景是组合操作。我给模型一个任务:
打开 assets/product.png: 1. 找到右上角的 logo 区域 2. 把该区域的红色替换成蓝色 3. 导出为 PNG 和 WebP 两种格式,质量 85这类任务里,模型的视觉理解能力和 MCP 工具能力被充分调用。NanoBanana 先调用读图工具,之后根据识别结果决定用什么参数调颜色替换接口,最后再让 MCP Server 导出两种格式。
这跟传统脚本最大的区别在于:以前要人工量坐标、写参数,现在模型自己看、自己定、自己执行。整个流程的耗时时长取决于图片大小和模型推理速度,但人工介入只有最开始的一条指令。
8. 常见问题与排查:我踩过的坑帮你填平
8.1 模型报错 free tier 问题
很多人在 OpenCode 里直接选内置的免费模型,结果报出opencode's free tier can only be used from within opencode。这个错误很明确:内置免费额度不在第三方客户端里开放。
解决办法有两个:
- 配置一个自有模型服务商(如 ACD),用 NanoBanana 或你自己的 API Key。
- 如果是临时试用,去 OpenCode 官方应用里用网页版服务。
这个坑本质上是"渠道隔离"机制,不是网络问题,也不是配置错误。
8.2 MCP Server 启动后找不到工具
注册了 MCP Server 但模型说看不见工具,最常见的原因有四个:
- 路径写错了:
command里的绝对路径不存在,或 Node 环境没在PATH里。 - Server 启动即崩溃:可以先在终端里手动执行
node /绝对路径/index.js,看有没有报错。 - SDK 版本不匹配:MCP SDK 大版本之间不兼容,建议锁定 SDK 版本。
- 没有重启 OpenCode:MCP 配置只在启动时加载,改了配置必须重启。
8.3 工具调用了但图像没变
如果模型说"已完成",但文件没变化,大概率是输出路径写到了别的目录。MCP Server 里建议统一记录输出路径,并在返回结果里明确告知"已生成文件:xxx"。这样 Agent 能确认结果,不会产生幻觉式的成功反馈。
8.4 请求耗时过长
图像任务比文本任务耗时高一个数量级,因为要编码图片、传 token、推理、再解码结果。如果经常超时,我建议:
- 图片在传模型前先压缩,不损失关键细节即可。
- 拆分任务:一次会话只做"看图+决策",另一次会话做"批量执行"。
- 小图用 NanoBanana,超大图先走 MCP 工具做预处理,再让模型看处理后的图。
8.5 常见问题速查表
| 问题现象 | 可能原因 | 处理办法 |
|---|---|---|
| 模型不可用 | 模型名写错或 provider 未加载 | 检查opencode.json中的 provider 和 model 字段 |
| free tier 报错 | 用了内置免费模型 | 换成 ACD 或自己的 API Key 模型 |
| MCP 工具不可见 | Server 未启动或配置路径错误 | 手测 Server 启动命令,确认后重启 OpenCode |
| 中文路径失败 | 编码或路径兼容问题 | 统一改用英文路径 |
| 图片处理慢 | 原图过大 | 先压缩再处理,或拆分为多步任务 |
| 模型断言成功但文件没变 | 输出路径不对 | 在 MCP Server 返回内容里明确输出文件路径 |
9. 个人体验和一些真实心得
整套方案跑通后,我最直观的感受是:终端图像处理的体验从"可以跑"变成了"真好用"。以前用脚本,改参数要回头编辑代码;现在直接在对话框里说"颜色再亮一点""右边留白再宽一些",模型会调整参数重新执行。这种交互方式比写死参数灵活太多。
但也有几个必须老实话说的限制。第一,MCP Server 的能力上限决定了模型的天花板,想要模型会更多操作,得先把 Server 对应的工具接口做好,这个前置投入省不了。第二,视觉模型对复杂构图的理解还不是万无一失,偶尔会出现定位偏差,最好在关键任务上加一道人工校验。第三,当前路径主要适合"批量处理、参数明确、流程固定"的场景,不要拿它去做创意艺术创作。
如果你要踩进这个坑,我的建议是从最简单的场景入手,先让模型调通一个resize_image,再逐步加工具。别想着一步到位搭出完美的 MCP Server,能力边界一步步扩展,出问题也容易定位。
最后分享一个小技巧:把常用的图像处理指令沉淀成 OpenCode 的 Prompt 模板或者 Skill 文件。比如"统一压缩批量图""替换指定区域颜色",下次一键调用,基本告别重复输入。