OpenCode + MCP 接入 NanoBanana:终端里一句话完成 AI 图像编辑
2026/9/19 4:52:05 网站建设 项目流程

最近折腾了一段时间的 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 整体架构:一句话说清楚链路

整个链路不算复杂,我画个思路给大家拆开看:

OpenCode(MCP Host) ↓ 通过 MCP 协议(stdio / HTTP) MCP Server(NanoBanana 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 Calling,Anthropic 有 Tools,开源项目再各自包装一套 JSON-RPC 通信,开发者每接一个助手就要写一遍适配逻辑。MCP 把这件事标准化了,只要 MCP Server 实现了协议,任何支持 MCP 的客户端都能直接用。

MCP 协议里最常见的三个原语是toolsresourcesprompts。图像编辑这种能力对应的是 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 NanoBanana:Ace 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="你的Key"

3.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(f"Content-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": f"Bearer {NANOBANANA_API_KEY}"} resp = requests.post(EDIT_ENDPOINT, headers=headers, files=files, data=data) 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.png

OpenCode 会把这句话解析成工具调用,自动给edit_image传参。执行过程中你能在终端里看到工具调用的详细记录,包括模型选择了什么指令、传了什么参数。大概几秒钟后,模型回复"图片编辑完成,结果已保存到 new_this.png"。

我实测这个流程跑通的那一刻,有点小激动——以前要打开网页上传图片、写提示词、下载的流程,现在一句话就在终端里完成了,而且是直接嵌在我写代码的语境里。而且因为图片路径是本地路径,后续我可以在同一个会话里继续让模型做二次编辑、生成 HTML 页面展示、甚至写一段 Python 脚本处理同一目录下的其他图片,整个工作流是非常连贯的。

4. 实战:把图像编辑指令玩出花

4.1 常见指令与提示词模板

工具跑通了,接下来就是怎么用得顺手。我在实际使用中总结了一些高频率的指令模板,可以直接复制进 OpenCode 对话里。注意控制好指令的颗粒度:太模糊的指令模型会自由发挥,太死板的指令又限制了模型的理解空间。给一个参考:

  • 背景替换:把 {图片路径} 的背景替换为 {场景描述},保持前景主体不变
  • 抠图:把 {图片路径} 中的 {物体} 抠出来,背景改为透明
  • 调色:让 {图片路径} 的画面更通透明亮,色调偏暖一点
  • 物体移除:把 {图片路径} 中 {位置/描述} 的物体移除,用周围环境自然填充
  • 风格迁移:把 {图片路径} 转成日系动漫风格
  • 图片扩写:扩大 {图片路径} 的画布,把周围环境合理地补全

实际效果相当稳定。有一次我拿一张产品图,要求"把产品放在一个木质桌面上,带柔和自然光",模型处理得比我想象中自然,阴影和反光都处理得比较合理。还有一次是团队活动合照,我想把背景从室内换到草地,人脸边缘基本没出现明显的抠图痕迹。

4.2 批量处理与脚本化工作流

单张图片处理只是开胃菜。接进终端最大的好处是能跟脚本和命令组合使用。配合 OpenCode 的 Agent 能力,我可以让它一口气处理整个目录下的图片:

遍历当前目录的 ./raw_images 文件夹,把所有 jpg 图片统一调亮一档,调整成 1024x1024 方形,保存到 ./processed_images

OpenCode 会自己写一段循环脚本,逐个调用图像编辑工具,或者直接生成 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里的commandargs是否指向正确的脚本路径;重启 OpenCode;用/mcp命令查看当前 MCP 状态
调用工具时报认证错误API Key 没传对,或者环境变量没生效在终端执行echo $NANOBANANA_API_KEY确认有值;如果使用env字段配置,注意 JSON 转义
返回图片保存失败输出路径不存在,或 API 返回的图片字段格式不是预期格式确保输出目录已创建;先打印 API 响应结构,确认image字段的实际格式(二进制还是 Base64)
图片编辑效果不理想提示词不够清晰,或图片本身分辨率过低把指令写得更具体,比如增加位置、色彩、材质描述;原图尽量用高分辨率图片
工具调用参数被模型猜错工具描述和参数 Schema 写得不够清晰优化description,把常见用法写进描述;给参数增加enumdefault值约束
批量处理时频繁超时单张图片处理时间过长,网络不稳定在 MCP Server 侧增加超时重试逻辑;用异步方式并行处理多张图片

5.2 我踩过的几个坑

第一个坑是 MCP stdio 协议的手写解析。一开始我没用官方 SDK,自己解析Content-Length前缀,结果在 Windows 下换行符不同,导致消息解析错位,OpenCode 一直说连接失败。折腾半天后发现是\r\n\n混用的问题。所以如果只是正常使用,建议直接用官方 MCP SDK,别重复造轮子。

第二个坑是工具描述写得太简短。最开始我把edit_image的描述写成"编辑图片",模型经常不知道该传几个参数,有时漏传instruction,有时把image_pathinstruction搞混。后来我参考 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 跑通流程,再回来研究定制化实现。先把链路走通,再逐步优化,这是所有工具集成交接项目里最稳妥的路线。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询