openrouter-image-mcp-server 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/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +356 -0
- package/dist/index.js.map +1 -0
- package/package.json +40 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* MCP Server for image generation via OpenRouter using the Nanobanana 2
|
|
4
|
+
* (Gemini 3.1 Flash Image Preview) model.
|
|
5
|
+
*
|
|
6
|
+
* Provides tools for generating and editing images through natural language prompts.
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;GAKG"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* MCP Server for image generation via OpenRouter using the Nanobanana 2
|
|
4
|
+
* (Gemini 3.1 Flash Image Preview) model.
|
|
5
|
+
*
|
|
6
|
+
* Provides tools for generating and editing images through natural language prompts.
|
|
7
|
+
*/
|
|
8
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
9
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
10
|
+
import { z } from "zod";
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
// Constants
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
const OPENROUTER_API_URL = "https://openrouter.ai/api/v1/chat/completions";
|
|
15
|
+
const DEFAULT_MODEL = "google/gemini-3.1-flash-image-preview";
|
|
16
|
+
const ASPECT_RATIOS = [
|
|
17
|
+
"1:1", "2:3", "3:2", "3:4", "4:3",
|
|
18
|
+
"4:5", "5:4", "9:16", "16:9", "21:9",
|
|
19
|
+
// Extended ratios (Gemini 3.1 Flash only)
|
|
20
|
+
"1:4", "4:1", "1:8", "8:1",
|
|
21
|
+
];
|
|
22
|
+
const IMAGE_SIZES = ["0.5K", "1K", "2K", "4K"];
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// API Client
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
function getApiKey() {
|
|
27
|
+
const key = process.env.OPENROUTER_API_KEY;
|
|
28
|
+
if (!key) {
|
|
29
|
+
throw new Error("OPENROUTER_API_KEY environment variable is required. " +
|
|
30
|
+
"Get your key at https://openrouter.ai/keys");
|
|
31
|
+
}
|
|
32
|
+
return key;
|
|
33
|
+
}
|
|
34
|
+
async function callOpenRouter(params) {
|
|
35
|
+
const apiKey = getApiKey();
|
|
36
|
+
const messages = [];
|
|
37
|
+
if (params.system_prompt) {
|
|
38
|
+
messages.push({ role: "system", content: params.system_prompt });
|
|
39
|
+
}
|
|
40
|
+
// If an input image is provided, use multipart content
|
|
41
|
+
if (params.input_image_base64) {
|
|
42
|
+
messages.push({
|
|
43
|
+
role: "user",
|
|
44
|
+
content: [
|
|
45
|
+
{
|
|
46
|
+
type: "image_url",
|
|
47
|
+
image_url: { url: params.input_image_base64 },
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
type: "text",
|
|
51
|
+
text: params.prompt,
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
messages.push({ role: "user", content: params.prompt });
|
|
58
|
+
}
|
|
59
|
+
const body = {
|
|
60
|
+
model: params.model ?? DEFAULT_MODEL,
|
|
61
|
+
messages,
|
|
62
|
+
modalities: ["image", "text"],
|
|
63
|
+
};
|
|
64
|
+
// Add image_config if any image options specified
|
|
65
|
+
const imageConfig = {};
|
|
66
|
+
if (params.aspect_ratio)
|
|
67
|
+
imageConfig.aspect_ratio = params.aspect_ratio;
|
|
68
|
+
if (params.image_size)
|
|
69
|
+
imageConfig.image_size = params.image_size;
|
|
70
|
+
if (Object.keys(imageConfig).length > 0) {
|
|
71
|
+
body.image_config = imageConfig;
|
|
72
|
+
}
|
|
73
|
+
const response = await fetch(OPENROUTER_API_URL, {
|
|
74
|
+
method: "POST",
|
|
75
|
+
headers: {
|
|
76
|
+
"Content-Type": "application/json",
|
|
77
|
+
Authorization: `Bearer ${apiKey}`,
|
|
78
|
+
"X-OpenRouter-Title": "openrouter-image-mcp-server",
|
|
79
|
+
},
|
|
80
|
+
body: JSON.stringify(body),
|
|
81
|
+
});
|
|
82
|
+
if (!response.ok) {
|
|
83
|
+
const errorText = await response.text();
|
|
84
|
+
let errorMessage;
|
|
85
|
+
try {
|
|
86
|
+
const errorJson = JSON.parse(errorText);
|
|
87
|
+
errorMessage = errorJson.error?.message ?? errorText;
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
errorMessage = errorText;
|
|
91
|
+
}
|
|
92
|
+
switch (response.status) {
|
|
93
|
+
case 401:
|
|
94
|
+
throw new Error("Authentication failed. Check your OPENROUTER_API_KEY.");
|
|
95
|
+
case 402:
|
|
96
|
+
throw new Error("Insufficient credits. Add credits at https://openrouter.ai/credits");
|
|
97
|
+
case 429:
|
|
98
|
+
throw new Error("Rate limit exceeded. Wait before making more requests.");
|
|
99
|
+
default:
|
|
100
|
+
throw new Error(`OpenRouter API error (${response.status}): ${errorMessage}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return (await response.json());
|
|
104
|
+
}
|
|
105
|
+
// ---------------------------------------------------------------------------
|
|
106
|
+
// Response Helpers
|
|
107
|
+
// ---------------------------------------------------------------------------
|
|
108
|
+
function extractImagesAndText(data) {
|
|
109
|
+
if (data.error) {
|
|
110
|
+
throw new Error(`OpenRouter error: ${data.error.message}`);
|
|
111
|
+
}
|
|
112
|
+
const choice = data.choices?.[0];
|
|
113
|
+
if (!choice) {
|
|
114
|
+
throw new Error("No response from model.");
|
|
115
|
+
}
|
|
116
|
+
const images = (choice.message.images ?? []).map((img) => ({
|
|
117
|
+
base64_data_url: img.image_url.url,
|
|
118
|
+
}));
|
|
119
|
+
return {
|
|
120
|
+
text: choice.message.content,
|
|
121
|
+
images,
|
|
122
|
+
usage: data.usage,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
// ---------------------------------------------------------------------------
|
|
126
|
+
// Zod Schemas
|
|
127
|
+
// ---------------------------------------------------------------------------
|
|
128
|
+
const GenerateImageInputSchema = z.object({
|
|
129
|
+
prompt: z
|
|
130
|
+
.string()
|
|
131
|
+
.min(1, "Prompt is required")
|
|
132
|
+
.max(10000, "Prompt must not exceed 10000 characters")
|
|
133
|
+
.describe("Text description of the image to generate"),
|
|
134
|
+
aspect_ratio: z
|
|
135
|
+
.enum(ASPECT_RATIOS)
|
|
136
|
+
.optional()
|
|
137
|
+
.describe("Aspect ratio for the generated image (default: model decides)"),
|
|
138
|
+
image_size: z
|
|
139
|
+
.enum(IMAGE_SIZES)
|
|
140
|
+
.optional()
|
|
141
|
+
.describe("Output image resolution: 0.5K, 1K (default), 2K, or 4K"),
|
|
142
|
+
system_prompt: z
|
|
143
|
+
.string()
|
|
144
|
+
.max(5000)
|
|
145
|
+
.optional()
|
|
146
|
+
.describe("Optional system prompt to guide the model's style or behavior"),
|
|
147
|
+
}).strict();
|
|
148
|
+
const EditImageInputSchema = z.object({
|
|
149
|
+
prompt: z
|
|
150
|
+
.string()
|
|
151
|
+
.min(1, "Prompt is required")
|
|
152
|
+
.max(10000, "Prompt must not exceed 10000 characters")
|
|
153
|
+
.describe("Instructions describing how to edit the image"),
|
|
154
|
+
input_image_base64: z
|
|
155
|
+
.string()
|
|
156
|
+
.min(1, "Input image is required")
|
|
157
|
+
.describe("Base64-encoded data URL of the input image (e.g. data:image/png;base64,...)"),
|
|
158
|
+
aspect_ratio: z
|
|
159
|
+
.enum(ASPECT_RATIOS)
|
|
160
|
+
.optional()
|
|
161
|
+
.describe("Aspect ratio for the output image"),
|
|
162
|
+
image_size: z
|
|
163
|
+
.enum(IMAGE_SIZES)
|
|
164
|
+
.optional()
|
|
165
|
+
.describe("Output image resolution: 0.5K, 1K (default), 2K, or 4K"),
|
|
166
|
+
system_prompt: z
|
|
167
|
+
.string()
|
|
168
|
+
.max(5000)
|
|
169
|
+
.optional()
|
|
170
|
+
.describe("Optional system prompt to guide editing style"),
|
|
171
|
+
}).strict();
|
|
172
|
+
// ---------------------------------------------------------------------------
|
|
173
|
+
// MCP Server
|
|
174
|
+
// ---------------------------------------------------------------------------
|
|
175
|
+
const server = new McpServer({
|
|
176
|
+
name: "openrouter-image-mcp-server",
|
|
177
|
+
version: "1.0.0",
|
|
178
|
+
});
|
|
179
|
+
// -- generate_image tool --------------------------------------------------
|
|
180
|
+
server.registerTool("generate_image", {
|
|
181
|
+
title: "Generate Image",
|
|
182
|
+
description: `Generate an image from a text prompt using Nanobanana 2 (Gemini 3.1 Flash Image) via OpenRouter.
|
|
183
|
+
|
|
184
|
+
Returns the generated image as a base64 data URL along with any text the model provides.
|
|
185
|
+
|
|
186
|
+
Args:
|
|
187
|
+
- prompt (string): Text description of the image to generate
|
|
188
|
+
- aspect_ratio (string, optional): One of 1:1, 2:3, 3:2, 3:4, 4:3, 4:5, 5:4, 9:16, 16:9, 21:9, 1:4, 4:1, 1:8, 8:1
|
|
189
|
+
- image_size (string, optional): Resolution - 0.5K, 1K (default), 2K, or 4K
|
|
190
|
+
- system_prompt (string, optional): System prompt to guide style/behavior
|
|
191
|
+
|
|
192
|
+
Returns:
|
|
193
|
+
Text content with the model's response, plus image content with the generated image.
|
|
194
|
+
|
|
195
|
+
Examples:
|
|
196
|
+
- "A cat wearing a top hat in watercolor style"
|
|
197
|
+
- "Professional headshot photo, studio lighting, neutral background" with aspect_ratio "3:4"
|
|
198
|
+
- "Wide panoramic landscape of mountains at sunset" with aspect_ratio "21:9" and image_size "4K"`,
|
|
199
|
+
inputSchema: GenerateImageInputSchema,
|
|
200
|
+
annotations: {
|
|
201
|
+
readOnlyHint: true,
|
|
202
|
+
destructiveHint: false,
|
|
203
|
+
idempotentHint: false,
|
|
204
|
+
openWorldHint: true,
|
|
205
|
+
},
|
|
206
|
+
}, async (params) => {
|
|
207
|
+
try {
|
|
208
|
+
const data = await callOpenRouter({
|
|
209
|
+
prompt: params.prompt,
|
|
210
|
+
aspect_ratio: params.aspect_ratio,
|
|
211
|
+
image_size: params.image_size,
|
|
212
|
+
system_prompt: params.system_prompt,
|
|
213
|
+
});
|
|
214
|
+
const result = extractImagesAndText(data);
|
|
215
|
+
const content = [];
|
|
216
|
+
if (result.text) {
|
|
217
|
+
content.push({ type: "text", text: result.text });
|
|
218
|
+
}
|
|
219
|
+
for (const img of result.images) {
|
|
220
|
+
// Extract the raw base64 and mime type from the data URL
|
|
221
|
+
const match = img.base64_data_url.match(/^data:(image\/[^;]+);base64,(.+)$/);
|
|
222
|
+
if (match) {
|
|
223
|
+
content.push({
|
|
224
|
+
type: "image",
|
|
225
|
+
data: match[2],
|
|
226
|
+
mimeType: match[1],
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
content.push({
|
|
231
|
+
type: "text",
|
|
232
|
+
text: `[Image data URL]: ${img.base64_data_url.substring(0, 100)}...`,
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
if (result.usage) {
|
|
237
|
+
content.push({
|
|
238
|
+
type: "text",
|
|
239
|
+
text: `[Tokens used — prompt: ${result.usage.prompt_tokens}, completion: ${result.usage.completion_tokens}]`,
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
if (content.length === 0) {
|
|
243
|
+
content.push({ type: "text", text: "No image was generated. Try rephrasing your prompt." });
|
|
244
|
+
}
|
|
245
|
+
return { content };
|
|
246
|
+
}
|
|
247
|
+
catch (error) {
|
|
248
|
+
return {
|
|
249
|
+
isError: true,
|
|
250
|
+
content: [{
|
|
251
|
+
type: "text",
|
|
252
|
+
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
|
253
|
+
}],
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
// -- edit_image tool ------------------------------------------------------
|
|
258
|
+
server.registerTool("edit_image", {
|
|
259
|
+
title: "Edit Image",
|
|
260
|
+
description: `Edit an existing image using natural language instructions via Nanobanana 2 (Gemini 3.1 Flash Image).
|
|
261
|
+
|
|
262
|
+
Takes an input image (as base64 data URL) and a text prompt describing the desired edits.
|
|
263
|
+
|
|
264
|
+
Args:
|
|
265
|
+
- prompt (string): Instructions describing how to edit the image (e.g. "Remove the background", "Make it look like a painting")
|
|
266
|
+
- input_image_base64 (string): Base64-encoded data URL of the source image (data:image/png;base64,... or data:image/jpeg;base64,...)
|
|
267
|
+
- aspect_ratio (string, optional): Aspect ratio for the output image
|
|
268
|
+
- image_size (string, optional): Resolution - 0.5K, 1K (default), 2K, or 4K
|
|
269
|
+
- system_prompt (string, optional): System prompt to guide editing style
|
|
270
|
+
|
|
271
|
+
Returns:
|
|
272
|
+
Text content with the model's response, plus image content with the edited image.
|
|
273
|
+
|
|
274
|
+
Examples:
|
|
275
|
+
- "Remove the background and replace with a sunset"
|
|
276
|
+
- "Convert this photo to a pencil sketch style"
|
|
277
|
+
- "Add a Santa hat to the person in the image"`,
|
|
278
|
+
inputSchema: EditImageInputSchema,
|
|
279
|
+
annotations: {
|
|
280
|
+
readOnlyHint: true,
|
|
281
|
+
destructiveHint: false,
|
|
282
|
+
idempotentHint: false,
|
|
283
|
+
openWorldHint: true,
|
|
284
|
+
},
|
|
285
|
+
}, async (params) => {
|
|
286
|
+
try {
|
|
287
|
+
const data = await callOpenRouter({
|
|
288
|
+
prompt: params.prompt,
|
|
289
|
+
input_image_base64: params.input_image_base64,
|
|
290
|
+
aspect_ratio: params.aspect_ratio,
|
|
291
|
+
image_size: params.image_size,
|
|
292
|
+
system_prompt: params.system_prompt,
|
|
293
|
+
});
|
|
294
|
+
const result = extractImagesAndText(data);
|
|
295
|
+
const content = [];
|
|
296
|
+
if (result.text) {
|
|
297
|
+
content.push({ type: "text", text: result.text });
|
|
298
|
+
}
|
|
299
|
+
for (const img of result.images) {
|
|
300
|
+
const match = img.base64_data_url.match(/^data:(image\/[^;]+);base64,(.+)$/);
|
|
301
|
+
if (match) {
|
|
302
|
+
content.push({
|
|
303
|
+
type: "image",
|
|
304
|
+
data: match[2],
|
|
305
|
+
mimeType: match[1],
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
content.push({
|
|
310
|
+
type: "text",
|
|
311
|
+
text: `[Image data URL]: ${img.base64_data_url.substring(0, 100)}...`,
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
if (result.usage) {
|
|
316
|
+
content.push({
|
|
317
|
+
type: "text",
|
|
318
|
+
text: `[Tokens used — prompt: ${result.usage.prompt_tokens}, completion: ${result.usage.completion_tokens}]`,
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
if (content.length === 0) {
|
|
322
|
+
content.push({ type: "text", text: "No edited image was returned. Try rephrasing your instructions." });
|
|
323
|
+
}
|
|
324
|
+
return { content };
|
|
325
|
+
}
|
|
326
|
+
catch (error) {
|
|
327
|
+
return {
|
|
328
|
+
isError: true,
|
|
329
|
+
content: [{
|
|
330
|
+
type: "text",
|
|
331
|
+
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
|
332
|
+
}],
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
// ---------------------------------------------------------------------------
|
|
337
|
+
// Main
|
|
338
|
+
// ---------------------------------------------------------------------------
|
|
339
|
+
async function main() {
|
|
340
|
+
// Validate API key on startup
|
|
341
|
+
try {
|
|
342
|
+
getApiKey();
|
|
343
|
+
}
|
|
344
|
+
catch (error) {
|
|
345
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
346
|
+
process.exit(1);
|
|
347
|
+
}
|
|
348
|
+
const transport = new StdioServerTransport();
|
|
349
|
+
await server.connect(transport);
|
|
350
|
+
console.error("openrouter-image-mcp-server running via stdio");
|
|
351
|
+
}
|
|
352
|
+
main().catch((error) => {
|
|
353
|
+
console.error("Fatal error:", error);
|
|
354
|
+
process.exit(1);
|
|
355
|
+
});
|
|
356
|
+
//# 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,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "openrouter-image-mcp-server",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "MCP server for image generation via OpenRouter (Nanobanana 2 / Gemini 3.1 Flash Image)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"openrouter-image-mcp-server": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"keywords": [
|
|
14
|
+
"mcp",
|
|
15
|
+
"mcp-server",
|
|
16
|
+
"openrouter",
|
|
17
|
+
"image-generation",
|
|
18
|
+
"nanobanana",
|
|
19
|
+
"gemini"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"start": "node dist/index.js",
|
|
23
|
+
"dev": "tsx watch src/index.ts",
|
|
24
|
+
"build": "tsc",
|
|
25
|
+
"clean": "rm -rf dist",
|
|
26
|
+
"prepublishOnly": "npm run build"
|
|
27
|
+
},
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=18"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
33
|
+
"zod": "^3.24.4"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@types/node": "^22.10.0",
|
|
37
|
+
"tsx": "^4.19.2",
|
|
38
|
+
"typescript": "^5.7.2"
|
|
39
|
+
}
|
|
40
|
+
}
|