mcp-nanobanana 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +284 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +308 -0
- package/dist/index.js.map +1 -0
- package/package.json +49 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Caio Rodrigo Silva
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
# Nano-Banana MCP Server 🍌
|
|
2
|
+
|
|
3
|
+
> **Free & open-source MCP server for AI image generation and editing**, powered by Google Gemini.
|
|
4
|
+
|
|
5
|
+
Generate stunning images, edit existing ones, and iterate on your creations — all through natural language prompts. Works with Claude Code, Cursor, Windsurf, and any MCP-compatible client.
|
|
6
|
+
|
|
7
|
+
## ✨ Features
|
|
8
|
+
|
|
9
|
+
- 🎨 **Generate Images** — Create new images from text descriptions
|
|
10
|
+
- ✏️ **Edit Images** — Modify existing images with natural language instructions
|
|
11
|
+
- 🔄 **Iterative Editing** — Continue refining the last generated/edited image
|
|
12
|
+
- 📐 **Aspect Ratios** — Square, portrait, landscape, widescreen, stories
|
|
13
|
+
- 🖼️ **Resolutions** — From 512px to 4K
|
|
14
|
+
- 🤖 **3 Models** — Fast, balanced, and pro quality tiers
|
|
15
|
+
- 🔧 **Zero Config** — Just add your free Gemini API key and go
|
|
16
|
+
|
|
17
|
+
## 🤖 Available Models
|
|
18
|
+
|
|
19
|
+
| Alias | Gemini Model | Best For |
|
|
20
|
+
|-------|-------------|----------|
|
|
21
|
+
| `nano-banana` | gemini-2.5-flash-image | Fast drafts & previews |
|
|
22
|
+
| `nano-banana-2` | gemini-3.1-flash-image-preview | Balanced quality (default) |
|
|
23
|
+
| `nano-banana-pro` | gemini-3-pro-image-preview | Highest quality results |
|
|
24
|
+
|
|
25
|
+
## 🔑 Setup
|
|
26
|
+
|
|
27
|
+
### 1. Get your Gemini API key (free)
|
|
28
|
+
|
|
29
|
+
- Visit [Google AI Studio](https://aistudio.google.com)
|
|
30
|
+
- Create a new API key
|
|
31
|
+
- Copy it for configuration
|
|
32
|
+
|
|
33
|
+
### 2. Install & configure
|
|
34
|
+
|
|
35
|
+
See configuration examples for your specific client below.
|
|
36
|
+
|
|
37
|
+
## 💻 Usage with Claude Code
|
|
38
|
+
|
|
39
|
+
Add to your Claude Code MCP settings (`~/.claude/settings.json`):
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"mcpServers": {
|
|
44
|
+
"nanobanana": {
|
|
45
|
+
"command": "npx",
|
|
46
|
+
"args": ["-y", "mcp-nanobanana"],
|
|
47
|
+
"env": {
|
|
48
|
+
"GEMINI_API_KEY": "your-gemini-api-key-here"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Usage Examples
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
Generate an image of a sunset over mountains in 4K widescreen
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
Edit this image to add some birds in the sky
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
Continue editing — make it more dramatic
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### 🧩 Companion Skill
|
|
70
|
+
|
|
71
|
+
For the best experience with Claude Code, install the **[nanobanana-skill](https://github.com/caio-rodrigo-silva/nanobanana-skill)** — it teaches Claude how to pick the right tool, enhance prompts, and handle aspect ratios automatically:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
npx skills add caio-rodrigo-silva/nanobanana-skill
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## 🎯 Usage with Cursor
|
|
78
|
+
|
|
79
|
+
Add to your Cursor MCP configuration:
|
|
80
|
+
|
|
81
|
+
```json
|
|
82
|
+
{
|
|
83
|
+
"nanobanana": {
|
|
84
|
+
"command": "npx",
|
|
85
|
+
"args": ["-y", "mcp-nanobanana"],
|
|
86
|
+
"env": {
|
|
87
|
+
"GEMINI_API_KEY": "your-gemini-api-key-here"
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## 🔧 For Other MCP Clients
|
|
94
|
+
|
|
95
|
+
Works with any MCP-compatible client. Use the same configuration pattern:
|
|
96
|
+
|
|
97
|
+
**Option A: Environment variable in MCP config (recommended)**
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"nanobanana": {
|
|
102
|
+
"command": "npx",
|
|
103
|
+
"args": ["-y", "mcp-nanobanana"],
|
|
104
|
+
"env": {
|
|
105
|
+
"GEMINI_API_KEY": "your-gemini-api-key-here"
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**Option B: System environment variable**
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
export GEMINI_API_KEY="your-gemini-api-key-here"
|
|
115
|
+
npx mcp-nanobanana
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## 🛠️ Available Tools
|
|
119
|
+
|
|
120
|
+
### `generate_image`
|
|
121
|
+
|
|
122
|
+
Create a new image from a text prompt.
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
generate_image({
|
|
126
|
+
prompt: "A futuristic city at night with neon lights",
|
|
127
|
+
model: "nano-banana-pro", // optional
|
|
128
|
+
aspectRatio: "16:9", // optional
|
|
129
|
+
imageSize: "4K" // optional
|
|
130
|
+
})
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### `edit_image`
|
|
134
|
+
|
|
135
|
+
Edit an existing image with text instructions.
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
edit_image({
|
|
139
|
+
imagePath: "/path/to/image.png",
|
|
140
|
+
prompt: "Add a rainbow in the sky",
|
|
141
|
+
model: "nano-banana-2", // optional
|
|
142
|
+
aspectRatio: "4:3", // optional
|
|
143
|
+
imageSize: "2K" // optional
|
|
144
|
+
})
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### `continue_editing`
|
|
148
|
+
|
|
149
|
+
Continue editing the last generated/edited image — no need to specify a file path.
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
continue_editing({
|
|
153
|
+
prompt: "Make it more colorful",
|
|
154
|
+
aspectRatio: "1:1", // optional
|
|
155
|
+
imageSize: "2K" // optional
|
|
156
|
+
})
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### `get_last_image`
|
|
160
|
+
|
|
161
|
+
Get information about the last generated/edited image.
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
get_last_image()
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### `get_status`
|
|
168
|
+
|
|
169
|
+
Check if the API key is configured and list available models.
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
get_status()
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### `configure_api_key`
|
|
176
|
+
|
|
177
|
+
Set the Gemini API key at runtime (alternative to environment variable).
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
configure_api_key({
|
|
181
|
+
apiKey: "your-gemini-api-key"
|
|
182
|
+
})
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## 📐 Image Options
|
|
186
|
+
|
|
187
|
+
### Aspect Ratios
|
|
188
|
+
|
|
189
|
+
| Value | Use Case |
|
|
190
|
+
|-------|----------|
|
|
191
|
+
| `1:1` | Square — social media posts, avatars |
|
|
192
|
+
| `3:4` | Portrait — vertical photos |
|
|
193
|
+
| `4:3` | Landscape — horizontal photos |
|
|
194
|
+
| `9:16` | Stories — Instagram/TikTok reels, phone screens |
|
|
195
|
+
| `16:9` | Widescreen — presentations, cinematic |
|
|
196
|
+
|
|
197
|
+
### Resolutions
|
|
198
|
+
|
|
199
|
+
| Value | Notes |
|
|
200
|
+
|-------|-------|
|
|
201
|
+
| `512` | Fast preview (only on nano-banana-2) |
|
|
202
|
+
| `1K` | Standard quality (default) |
|
|
203
|
+
| `2K` | High quality |
|
|
204
|
+
| `4K` | Maximum quality |
|
|
205
|
+
|
|
206
|
+
## 📁 Output
|
|
207
|
+
|
|
208
|
+
Images are saved to `./nanobanana-images/` relative to your working directory.
|
|
209
|
+
|
|
210
|
+
You can customize the output directory with the `NANOBANANA_OUTPUT_DIR` environment variable.
|
|
211
|
+
|
|
212
|
+
## 🎨 Example Workflows
|
|
213
|
+
|
|
214
|
+
### Quick Image Generation
|
|
215
|
+
|
|
216
|
+
1. `generate_image` — Create your base image
|
|
217
|
+
2. `continue_editing` — Refine and improve
|
|
218
|
+
3. `continue_editing` — Add final touches
|
|
219
|
+
|
|
220
|
+
### Editing an Existing Photo
|
|
221
|
+
|
|
222
|
+
1. `edit_image` — Apply changes to your image
|
|
223
|
+
2. `continue_editing` — Fine-tune the result
|
|
224
|
+
3. `get_last_image` — Check the output path
|
|
225
|
+
|
|
226
|
+
### Iterative Design
|
|
227
|
+
|
|
228
|
+
1. `generate_image` — Start with a concept
|
|
229
|
+
2. `continue_editing` — Make adjustments
|
|
230
|
+
3. Repeat until satisfied
|
|
231
|
+
|
|
232
|
+
## 🔧 Development
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
# Clone the repository
|
|
236
|
+
git clone https://github.com/caio-rodrigo-silva/mcp-nanobanana.git
|
|
237
|
+
cd mcp-nanobanana
|
|
238
|
+
|
|
239
|
+
# Install dependencies
|
|
240
|
+
npm install
|
|
241
|
+
|
|
242
|
+
# Build
|
|
243
|
+
npm run build
|
|
244
|
+
|
|
245
|
+
# Development with auto-rebuild
|
|
246
|
+
npm run dev
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### Tech Stack
|
|
250
|
+
|
|
251
|
+
- **TypeScript** — Type-safe development
|
|
252
|
+
- **Node.js** — Runtime environment
|
|
253
|
+
- **Zod** — Schema validation
|
|
254
|
+
- **@google/genai** — Google Gemini API
|
|
255
|
+
- **@modelcontextprotocol/sdk** — MCP protocol
|
|
256
|
+
|
|
257
|
+
## 📋 Requirements
|
|
258
|
+
|
|
259
|
+
- Node.js 18+
|
|
260
|
+
- Gemini API key from [Google AI Studio](https://aistudio.google.com) (free)
|
|
261
|
+
- Any MCP-compatible client
|
|
262
|
+
|
|
263
|
+
## 🤝 Contributing
|
|
264
|
+
|
|
265
|
+
Contributions are welcome! Feel free to:
|
|
266
|
+
|
|
267
|
+
- Report bugs
|
|
268
|
+
- Suggest new features
|
|
269
|
+
- Submit pull requests
|
|
270
|
+
- Improve documentation
|
|
271
|
+
|
|
272
|
+
## 📄 License
|
|
273
|
+
|
|
274
|
+
MIT License — see [LICENSE](LICENSE) file for details.
|
|
275
|
+
|
|
276
|
+
## 🔗 Links
|
|
277
|
+
|
|
278
|
+
- 🐛 **Issues**: [GitHub Issues](https://github.com/caio-rodrigo-silva/mcp-nanobanana/issues)
|
|
279
|
+
- 🧩 **Companion Skill**: [nanobanana-skill](https://github.com/caio-rodrigo-silva/nanobanana-skill)
|
|
280
|
+
- 📖 **Gemini API**: [Google AI Studio](https://aistudio.google.com)
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
_Made with 🍌 by [Caio Rodrigo](https://github.com/caio-rodrigo-silva)_
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { GoogleGenAI } from "@google/genai";
|
|
6
|
+
import * as fs from "fs";
|
|
7
|
+
import * as path from "path";
|
|
8
|
+
// --- Constants ---
|
|
9
|
+
const MODELS = {
|
|
10
|
+
"nano-banana": "gemini-2.5-flash-image",
|
|
11
|
+
"nano-banana-2": "gemini-3.1-flash-image-preview",
|
|
12
|
+
"nano-banana-pro": "gemini-3-pro-image-preview",
|
|
13
|
+
};
|
|
14
|
+
const DEFAULT_MODEL = "nano-banana-2";
|
|
15
|
+
const OUTPUT_DIR = path.resolve(process.env.NANOBANANA_OUTPUT_DIR || "nanobanana-images");
|
|
16
|
+
// --- State ---
|
|
17
|
+
let apiKey = process.env.GEMINI_API_KEY || "";
|
|
18
|
+
let ai = null;
|
|
19
|
+
let lastImagePath = "";
|
|
20
|
+
let lastImageBase64 = "";
|
|
21
|
+
let lastImageMimeType = "";
|
|
22
|
+
// Chat sessions for multi-step editing (keyed by session name)
|
|
23
|
+
const chatSessions = new Map();
|
|
24
|
+
// --- Helpers ---
|
|
25
|
+
function getClient() {
|
|
26
|
+
if (!apiKey) {
|
|
27
|
+
throw new Error("Gemini API key not configured. Use the configure_api_key tool to set it, or pass GEMINI_API_KEY as an environment variable.");
|
|
28
|
+
}
|
|
29
|
+
if (!ai) {
|
|
30
|
+
ai = new GoogleGenAI({ apiKey });
|
|
31
|
+
}
|
|
32
|
+
return ai;
|
|
33
|
+
}
|
|
34
|
+
function ensureOutputDir() {
|
|
35
|
+
if (!fs.existsSync(OUTPUT_DIR)) {
|
|
36
|
+
fs.mkdirSync(OUTPUT_DIR, { recursive: true });
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function resolveModel(model) {
|
|
40
|
+
if (!model)
|
|
41
|
+
return MODELS[DEFAULT_MODEL];
|
|
42
|
+
if (model in MODELS)
|
|
43
|
+
return MODELS[model];
|
|
44
|
+
// Allow passing the full model ID directly
|
|
45
|
+
return model;
|
|
46
|
+
}
|
|
47
|
+
function saveImage(base64Data, mimeType, prefix) {
|
|
48
|
+
ensureOutputDir();
|
|
49
|
+
const ext = mimeType.includes("png") ? "png" : "jpg";
|
|
50
|
+
const timestamp = Date.now();
|
|
51
|
+
const filename = `${prefix}_${timestamp}.${ext}`;
|
|
52
|
+
const filePath = path.join(OUTPUT_DIR, filename);
|
|
53
|
+
const buffer = Buffer.from(base64Data, "base64");
|
|
54
|
+
fs.writeFileSync(filePath, buffer);
|
|
55
|
+
lastImagePath = filePath;
|
|
56
|
+
lastImageBase64 = base64Data;
|
|
57
|
+
lastImageMimeType = mimeType;
|
|
58
|
+
return filePath;
|
|
59
|
+
}
|
|
60
|
+
function readImageAsBase64(imagePath) {
|
|
61
|
+
const resolved = path.resolve(imagePath);
|
|
62
|
+
if (!fs.existsSync(resolved)) {
|
|
63
|
+
throw new Error(`Image not found: ${resolved}`);
|
|
64
|
+
}
|
|
65
|
+
const buffer = fs.readFileSync(resolved);
|
|
66
|
+
const ext = path.extname(resolved).toLowerCase();
|
|
67
|
+
const mimeMap = {
|
|
68
|
+
".png": "image/png",
|
|
69
|
+
".jpg": "image/jpeg",
|
|
70
|
+
".jpeg": "image/jpeg",
|
|
71
|
+
".webp": "image/webp",
|
|
72
|
+
".gif": "image/gif",
|
|
73
|
+
};
|
|
74
|
+
const mimeType = mimeMap[ext] || "image/png";
|
|
75
|
+
return { data: buffer.toString("base64"), mimeType };
|
|
76
|
+
}
|
|
77
|
+
function extractImageAndText(response) {
|
|
78
|
+
let text = "";
|
|
79
|
+
let imagePath = null;
|
|
80
|
+
const parts = response.candidates?.[0]?.content?.parts || [];
|
|
81
|
+
for (const part of parts) {
|
|
82
|
+
if (part.text) {
|
|
83
|
+
text += part.text;
|
|
84
|
+
}
|
|
85
|
+
else if (part.inlineData) {
|
|
86
|
+
imagePath = saveImage(part.inlineData.data, part.inlineData.mimeType, "generated");
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return { text, imagePath };
|
|
90
|
+
}
|
|
91
|
+
// --- MCP Server ---
|
|
92
|
+
const server = new McpServer({
|
|
93
|
+
name: "mcp-nanobanana",
|
|
94
|
+
version: "1.0.0",
|
|
95
|
+
});
|
|
96
|
+
// Tool: configure_api_key
|
|
97
|
+
server.tool("configure_api_key", "Set the Gemini API key for image generation. Get yours at aistudio.google.com", { apiKey: z.string().min(1).describe("Your Gemini API key") }, async ({ apiKey: key }) => {
|
|
98
|
+
apiKey = key;
|
|
99
|
+
ai = null; // Reset client to pick up new key
|
|
100
|
+
return {
|
|
101
|
+
content: [{ type: "text", text: "API key configured successfully." }],
|
|
102
|
+
};
|
|
103
|
+
});
|
|
104
|
+
// Tool: get_status
|
|
105
|
+
server.tool("get_status", "Check if the Gemini API key is configured and list available models", {}, async () => {
|
|
106
|
+
const configured = !!apiKey;
|
|
107
|
+
const modelList = Object.entries(MODELS)
|
|
108
|
+
.map(([alias, id]) => ` - ${alias}: ${id}${alias === DEFAULT_MODEL ? " (default)" : ""}`)
|
|
109
|
+
.join("\n");
|
|
110
|
+
return {
|
|
111
|
+
content: [
|
|
112
|
+
{
|
|
113
|
+
type: "text",
|
|
114
|
+
text: [
|
|
115
|
+
`API Key: ${configured ? "Configured" : "Not configured — use configure_api_key or set GEMINI_API_KEY env var"}`,
|
|
116
|
+
`Output directory: ${OUTPUT_DIR}`,
|
|
117
|
+
`Last image: ${lastImagePath || "None"}`,
|
|
118
|
+
`\nAvailable models:\n${modelList}`,
|
|
119
|
+
].join("\n"),
|
|
120
|
+
},
|
|
121
|
+
],
|
|
122
|
+
};
|
|
123
|
+
});
|
|
124
|
+
// Tool: generate_image
|
|
125
|
+
server.tool("generate_image", "Generate a new image from a text description. Returns the file path of the saved image. Use detailed, descriptive prompts for best results.", {
|
|
126
|
+
prompt: z.string().min(1).describe("Detailed text description of the image to generate"),
|
|
127
|
+
model: z
|
|
128
|
+
.enum(["nano-banana", "nano-banana-2", "nano-banana-pro"])
|
|
129
|
+
.optional()
|
|
130
|
+
.describe("Model to use. nano-banana (fast), nano-banana-2 (balanced, default), nano-banana-pro (highest quality)"),
|
|
131
|
+
aspectRatio: z
|
|
132
|
+
.enum(["1:1", "3:4", "4:3", "9:16", "16:9"])
|
|
133
|
+
.optional()
|
|
134
|
+
.describe("Aspect ratio of the generated image"),
|
|
135
|
+
imageSize: z
|
|
136
|
+
.enum(["512", "1K", "2K", "4K"])
|
|
137
|
+
.optional()
|
|
138
|
+
.describe("Image resolution. 512 only supported on nano-banana-2. Default is 1K"),
|
|
139
|
+
}, async ({ prompt, model, aspectRatio, imageSize }) => {
|
|
140
|
+
const client = getClient();
|
|
141
|
+
const modelId = resolveModel(model);
|
|
142
|
+
const imageConfig = {};
|
|
143
|
+
if (aspectRatio)
|
|
144
|
+
imageConfig.aspectRatio = aspectRatio;
|
|
145
|
+
if (imageSize)
|
|
146
|
+
imageConfig.imageSize = imageSize;
|
|
147
|
+
const response = await client.models.generateContent({
|
|
148
|
+
model: modelId,
|
|
149
|
+
contents: prompt,
|
|
150
|
+
config: {
|
|
151
|
+
responseModalities: ["TEXT", "IMAGE"],
|
|
152
|
+
...(Object.keys(imageConfig).length > 0 && { imageConfig }),
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
const { text, imagePath } = extractImageAndText(response);
|
|
156
|
+
if (!imagePath) {
|
|
157
|
+
return {
|
|
158
|
+
content: [{ type: "text", text: text || "No image was generated. Try a more descriptive prompt." }],
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
return {
|
|
162
|
+
content: [
|
|
163
|
+
{ type: "text", text: `Image saved to: ${imagePath}${text ? `\n\n${text}` : ""}` },
|
|
164
|
+
],
|
|
165
|
+
};
|
|
166
|
+
});
|
|
167
|
+
// Tool: edit_image
|
|
168
|
+
server.tool("edit_image", "Edit an existing image using text instructions. Provide the image path and describe what changes to make.", {
|
|
169
|
+
imagePath: z.string().min(1).describe("Absolute path to the image file to edit"),
|
|
170
|
+
prompt: z.string().min(1).describe("Instructions for how to edit the image"),
|
|
171
|
+
model: z
|
|
172
|
+
.enum(["nano-banana", "nano-banana-2", "nano-banana-pro"])
|
|
173
|
+
.optional()
|
|
174
|
+
.describe("Model to use. nano-banana (fast), nano-banana-2 (balanced, default), nano-banana-pro (highest quality)"),
|
|
175
|
+
aspectRatio: z
|
|
176
|
+
.enum(["1:1", "3:4", "4:3", "9:16", "16:9"])
|
|
177
|
+
.optional()
|
|
178
|
+
.describe("Aspect ratio of the output image"),
|
|
179
|
+
imageSize: z
|
|
180
|
+
.enum(["512", "1K", "2K", "4K"])
|
|
181
|
+
.optional()
|
|
182
|
+
.describe("Image resolution. 512 only supported on nano-banana-2. Default is 1K"),
|
|
183
|
+
}, async ({ imagePath: imgPath, prompt, model, aspectRatio, imageSize }) => {
|
|
184
|
+
const client = getClient();
|
|
185
|
+
const modelId = resolveModel(model);
|
|
186
|
+
const { data, mimeType } = readImageAsBase64(imgPath);
|
|
187
|
+
const imageConfig = {};
|
|
188
|
+
if (aspectRatio)
|
|
189
|
+
imageConfig.aspectRatio = aspectRatio;
|
|
190
|
+
if (imageSize)
|
|
191
|
+
imageConfig.imageSize = imageSize;
|
|
192
|
+
const response = await client.models.generateContent({
|
|
193
|
+
model: modelId,
|
|
194
|
+
contents: [
|
|
195
|
+
{
|
|
196
|
+
role: "user",
|
|
197
|
+
parts: [
|
|
198
|
+
{ text: prompt },
|
|
199
|
+
{ inlineData: { mimeType, data } },
|
|
200
|
+
],
|
|
201
|
+
},
|
|
202
|
+
],
|
|
203
|
+
config: {
|
|
204
|
+
responseModalities: ["TEXT", "IMAGE"],
|
|
205
|
+
...(Object.keys(imageConfig).length > 0 && { imageConfig }),
|
|
206
|
+
},
|
|
207
|
+
});
|
|
208
|
+
const { text, imagePath: savedPath } = extractImageAndText(response);
|
|
209
|
+
if (!savedPath) {
|
|
210
|
+
return {
|
|
211
|
+
content: [{ type: "text", text: text || "No edited image was returned. Try different instructions." }],
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
return {
|
|
215
|
+
content: [
|
|
216
|
+
{ type: "text", text: `Edited image saved to: ${savedPath}${text ? `\n\n${text}` : ""}` },
|
|
217
|
+
],
|
|
218
|
+
};
|
|
219
|
+
});
|
|
220
|
+
// Tool: continue_editing
|
|
221
|
+
server.tool("continue_editing", "Continue editing the last generated or edited image. No need to specify a file path — works on the most recent image.", {
|
|
222
|
+
prompt: z.string().min(1).describe("Instructions for further editing the last image"),
|
|
223
|
+
model: z
|
|
224
|
+
.enum(["nano-banana", "nano-banana-2", "nano-banana-pro"])
|
|
225
|
+
.optional()
|
|
226
|
+
.describe("Model to use. nano-banana (fast), nano-banana-2 (balanced, default), nano-banana-pro (highest quality)"),
|
|
227
|
+
aspectRatio: z
|
|
228
|
+
.enum(["1:1", "3:4", "4:3", "9:16", "16:9"])
|
|
229
|
+
.optional()
|
|
230
|
+
.describe("Aspect ratio of the output image"),
|
|
231
|
+
imageSize: z
|
|
232
|
+
.enum(["512", "1K", "2K", "4K"])
|
|
233
|
+
.optional()
|
|
234
|
+
.describe("Image resolution. 512 only supported on nano-banana-2. Default is 1K"),
|
|
235
|
+
}, async ({ prompt, model, aspectRatio, imageSize }) => {
|
|
236
|
+
if (!lastImageBase64) {
|
|
237
|
+
return {
|
|
238
|
+
content: [{ type: "text", text: "No previous image to edit. Use generate_image or edit_image first." }],
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
const client = getClient();
|
|
242
|
+
const modelId = resolveModel(model);
|
|
243
|
+
const imageConfig = {};
|
|
244
|
+
if (aspectRatio)
|
|
245
|
+
imageConfig.aspectRatio = aspectRatio;
|
|
246
|
+
if (imageSize)
|
|
247
|
+
imageConfig.imageSize = imageSize;
|
|
248
|
+
const response = await client.models.generateContent({
|
|
249
|
+
model: modelId,
|
|
250
|
+
contents: [
|
|
251
|
+
{
|
|
252
|
+
role: "user",
|
|
253
|
+
parts: [
|
|
254
|
+
{ text: prompt },
|
|
255
|
+
{ inlineData: { mimeType: lastImageMimeType, data: lastImageBase64 } },
|
|
256
|
+
],
|
|
257
|
+
},
|
|
258
|
+
],
|
|
259
|
+
config: {
|
|
260
|
+
responseModalities: ["TEXT", "IMAGE"],
|
|
261
|
+
...(Object.keys(imageConfig).length > 0 && { imageConfig }),
|
|
262
|
+
},
|
|
263
|
+
});
|
|
264
|
+
const { text, imagePath } = extractImageAndText(response);
|
|
265
|
+
if (!imagePath) {
|
|
266
|
+
return {
|
|
267
|
+
content: [{ type: "text", text: text || "No edited image was returned. Try different instructions." }],
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
return {
|
|
271
|
+
content: [
|
|
272
|
+
{ type: "text", text: `Edited image saved to: ${imagePath}${text ? `\n\n${text}` : ""}` },
|
|
273
|
+
],
|
|
274
|
+
};
|
|
275
|
+
});
|
|
276
|
+
// Tool: get_last_image
|
|
277
|
+
server.tool("get_last_image", "Get information about the last generated or edited image, including its file path.", {}, async () => {
|
|
278
|
+
if (!lastImagePath) {
|
|
279
|
+
return {
|
|
280
|
+
content: [{ type: "text", text: "No image has been generated yet in this session." }],
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
const exists = fs.existsSync(lastImagePath);
|
|
284
|
+
const stats = exists ? fs.statSync(lastImagePath) : null;
|
|
285
|
+
return {
|
|
286
|
+
content: [
|
|
287
|
+
{
|
|
288
|
+
type: "text",
|
|
289
|
+
text: [
|
|
290
|
+
`Path: ${lastImagePath}`,
|
|
291
|
+
`Exists: ${exists}`,
|
|
292
|
+
`Size: ${stats ? `${(stats.size / 1024).toFixed(1)} KB` : "N/A"}`,
|
|
293
|
+
`Type: ${lastImageMimeType}`,
|
|
294
|
+
].join("\n"),
|
|
295
|
+
},
|
|
296
|
+
],
|
|
297
|
+
};
|
|
298
|
+
});
|
|
299
|
+
// --- Start Server ---
|
|
300
|
+
async function main() {
|
|
301
|
+
const transport = new StdioServerTransport();
|
|
302
|
+
await server.connect(transport);
|
|
303
|
+
}
|
|
304
|
+
main().catch((error) => {
|
|
305
|
+
console.error("Server failed to start:", error);
|
|
306
|
+
process.exit(1);
|
|
307
|
+
});
|
|
308
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mcp-nanobanana",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "MCP server for AI image generation and editing powered by Google Gemini",
|
|
5
|
+
"author": "Caio Rodrigo Silva",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/caio-rodrigo-silva/mcp-nanobanana.git"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/caio-rodrigo-silva/mcp-nanobanana#readme",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/caio-rodrigo-silva/mcp-nanobanana/issues"
|
|
13
|
+
},
|
|
14
|
+
"main": "dist/index.js",
|
|
15
|
+
"bin": {
|
|
16
|
+
"mcp-nanobanana": "dist/index.js"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"LICENSE",
|
|
21
|
+
"README.md"
|
|
22
|
+
],
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "tsc",
|
|
25
|
+
"dev": "tsc --watch",
|
|
26
|
+
"prepublishOnly": "npm run build"
|
|
27
|
+
},
|
|
28
|
+
"keywords": [
|
|
29
|
+
"mcp",
|
|
30
|
+
"mcp-server",
|
|
31
|
+
"nanobanana",
|
|
32
|
+
"gemini",
|
|
33
|
+
"image-generation",
|
|
34
|
+
"image-editing",
|
|
35
|
+
"ai",
|
|
36
|
+
"google-gemini"
|
|
37
|
+
],
|
|
38
|
+
"type": "module",
|
|
39
|
+
"license": "MIT",
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@google/genai": "^1.16.0",
|
|
42
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
43
|
+
"zod": "^3.22.4"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"typescript": "^5.4.0",
|
|
47
|
+
"@types/node": "^20.0.0"
|
|
48
|
+
}
|
|
49
|
+
}
|