@agentrix/gemini-image-mcp 1.1.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/QUICKSTART.md +156 -0
- package/README.md +194 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +220 -0
- package/dist/index.js.map +1 -0
- package/example/image_1768469622926_1.png +0 -0
- package/package.json +41 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Agentrix
|
|
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/QUICKSTART.md
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# Quick Start Guide
|
|
2
|
+
|
|
3
|
+
## Installation & Publishing
|
|
4
|
+
|
|
5
|
+
### 1. Install Dependencies
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
cd gemini-image-mcp
|
|
9
|
+
npm install
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
### 2. Build the Project
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm run build
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
This will compile TypeScript files to the `dist/` directory.
|
|
19
|
+
|
|
20
|
+
### 3. Test Locally
|
|
21
|
+
|
|
22
|
+
Before publishing, test the MCP server locally:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# Set environment variables
|
|
26
|
+
export GEMINI_API_KEY="your-api-key"
|
|
27
|
+
export GEMINI_BASE_URL="https://generativelanguage.googleapis.com/v1beta"
|
|
28
|
+
export GEMINI_MODEL="gemini-2.5-flash-image"
|
|
29
|
+
|
|
30
|
+
# Run the server
|
|
31
|
+
npm start
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 4. Test with Claude Desktop (Local)
|
|
35
|
+
|
|
36
|
+
Edit your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json`):
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"mcpServers": {
|
|
41
|
+
"gemini-image": {
|
|
42
|
+
"command": "node",
|
|
43
|
+
"args": ["/absolute/path/to/gemini-image-mcp/dist/index.js"],
|
|
44
|
+
"env": {
|
|
45
|
+
"GEMINI_API_KEY": "your-api-key-here"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Restart Claude Desktop and test the `generate_image` tool.
|
|
53
|
+
|
|
54
|
+
### 5. Publish to npm
|
|
55
|
+
|
|
56
|
+
When ready to publish:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
# Login to npm (first time only)
|
|
60
|
+
npm login
|
|
61
|
+
|
|
62
|
+
# Publish the package
|
|
63
|
+
npm publish --access public
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 6. Use Published Package
|
|
67
|
+
|
|
68
|
+
After publishing, users can install with:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
npm install -g @agentrix/gemini-image-mcp
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
And configure Claude Desktop:
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"mcpServers": {
|
|
79
|
+
"gemini-image": {
|
|
80
|
+
"command": "gemini-image-mcp",
|
|
81
|
+
"env": {
|
|
82
|
+
"GEMINI_API_KEY": "your-api-key-here"
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Or use with npx (no installation needed):
|
|
90
|
+
|
|
91
|
+
```json
|
|
92
|
+
{
|
|
93
|
+
"mcpServers": {
|
|
94
|
+
"gemini-image": {
|
|
95
|
+
"command": "npx",
|
|
96
|
+
"args": ["-y", "@agentrix/gemini-image-mcp"],
|
|
97
|
+
"env": {
|
|
98
|
+
"GEMINI_API_KEY": "your-api-key-here"
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Example Usage
|
|
106
|
+
|
|
107
|
+
Once configured in Claude Desktop, you can ask Claude to generate images:
|
|
108
|
+
|
|
109
|
+
**Return base64 images:**
|
|
110
|
+
- "Generate an image of a sunset over mountains"
|
|
111
|
+
- "Create a 16:9 landscape image of a futuristic city"
|
|
112
|
+
- "Generate an image of a cat, but avoid any dogs or other animals"
|
|
113
|
+
|
|
114
|
+
The tool will return base64 encoded images that Claude can display.
|
|
115
|
+
|
|
116
|
+
**Save images to disk:**
|
|
117
|
+
- "Generate an image of a sunset and save it to /Users/myname/pictures"
|
|
118
|
+
- "Create an image of a cat and save it to ~/Downloads"
|
|
119
|
+
|
|
120
|
+
When saving to disk, the tool will:
|
|
121
|
+
- Create the directory if it doesn't exist
|
|
122
|
+
- Save all generated images with timestamped filenames (e.g., `image_1737023456789_1.png`)
|
|
123
|
+
- Return the full paths of saved files
|
|
124
|
+
|
|
125
|
+
## Troubleshooting
|
|
126
|
+
|
|
127
|
+
### Permission Issues During npm install
|
|
128
|
+
|
|
129
|
+
If you encounter EPERM errors, try:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
# Use a different cache directory
|
|
133
|
+
npm install --cache /tmp/npm-cache-$USER
|
|
134
|
+
|
|
135
|
+
# Or clean npm cache
|
|
136
|
+
npm cache clean --force
|
|
137
|
+
npm install
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### API Key Issues
|
|
141
|
+
|
|
142
|
+
Make sure your GEMINI_API_KEY is valid and has access to image generation features.
|
|
143
|
+
|
|
144
|
+
### Model Selection
|
|
145
|
+
|
|
146
|
+
Different Gemini models may have different capabilities. The default `gemini-2.5-flash-image` is optimized for image generation. Check Google's documentation for available models.
|
|
147
|
+
|
|
148
|
+
## Development
|
|
149
|
+
|
|
150
|
+
For development with auto-rebuild on changes:
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
npm run dev
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
This runs TypeScript in watch mode.
|
package/README.md
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
# Gemini Image MCP Server
|
|
2
|
+
|
|
3
|
+
A Model Context Protocol (MCP) server that provides image generation capabilities using Google's Gemini Banana API.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Generate images from text prompts using Gemini API
|
|
8
|
+
- Support for different aspect ratios (1:1, 16:9, 9:16, 4:3, 3:4)
|
|
9
|
+
- Negative prompts to avoid unwanted elements
|
|
10
|
+
- Returns base64 encoded images compatible with MCP clients
|
|
11
|
+
- Configurable API endpoint, key, and model
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
### From npm (when published)
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install -g @agentrix/gemini-image-mcp
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### From source
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
git clone <repository-url>
|
|
25
|
+
cd gemini-image-mcp
|
|
26
|
+
npm install
|
|
27
|
+
npm run build
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Configuration
|
|
31
|
+
|
|
32
|
+
The server requires environment variables for configuration:
|
|
33
|
+
|
|
34
|
+
| Variable | Required | Default | Description |
|
|
35
|
+
|----------|----------|---------|-------------|
|
|
36
|
+
| `GEMINI_API_KEY` | Yes | - | Your Gemini API key |
|
|
37
|
+
| `GEMINI_BASE_URL` | No | `https://generativelanguage.googleapis.com/v1beta` | Gemini API base URL |
|
|
38
|
+
| `GEMINI_MODEL` | No | `gemini-2.5-flash-image` | Model to use for image generation |
|
|
39
|
+
|
|
40
|
+
## Usage
|
|
41
|
+
|
|
42
|
+
### With Claude Desktop
|
|
43
|
+
|
|
44
|
+
Add to your Claude Desktop configuration (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"mcpServers": {
|
|
49
|
+
"gemini-image": {
|
|
50
|
+
"command": "npx",
|
|
51
|
+
"args": ["-y", "@agentrix/gemini-image-mcp"],
|
|
52
|
+
"env": {
|
|
53
|
+
"GEMINI_API_KEY": "your-api-key-here",
|
|
54
|
+
"GEMINI_BASE_URL": "https://generativelanguage.googleapis.com/v1beta",
|
|
55
|
+
"GEMINI_MODEL": "gemini-2.5-flash-image"
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Or if installed globally:
|
|
63
|
+
|
|
64
|
+
```json
|
|
65
|
+
{
|
|
66
|
+
"mcpServers": {
|
|
67
|
+
"gemini-image": {
|
|
68
|
+
"command": "gemini-image-mcp",
|
|
69
|
+
"env": {
|
|
70
|
+
"GEMINI_API_KEY": "your-api-key-here"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Standalone
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
export GEMINI_API_KEY="your-api-key-here"
|
|
81
|
+
export GEMINI_BASE_URL="https://generativelanguage.googleapis.com/v1beta"
|
|
82
|
+
export GEMINI_MODEL="gemini-2.5-flash-image"
|
|
83
|
+
|
|
84
|
+
gemini-image-mcp
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Available Tools
|
|
88
|
+
|
|
89
|
+
### generate_image
|
|
90
|
+
|
|
91
|
+
Generate an image from a text prompt. Can return base64 encoded images or save them to disk.
|
|
92
|
+
|
|
93
|
+
**Parameters:**
|
|
94
|
+
|
|
95
|
+
- `prompt` (string, required): The text description of the image to generate
|
|
96
|
+
- `aspectRatio` (string, optional): The aspect ratio of the image. Options: "1:1", "16:9", "9:16", "4:3", "3:4". Default: "1:1"
|
|
97
|
+
- `negativePrompt` (string, optional): Description of elements to avoid in the image
|
|
98
|
+
- `path` (string, optional): Directory path to save generated images. If provided, all images will be saved as PNG files instead of returning base64 data
|
|
99
|
+
|
|
100
|
+
**Returns:**
|
|
101
|
+
|
|
102
|
+
When `path` is NOT provided:
|
|
103
|
+
- Text confirmation message
|
|
104
|
+
- Base64 encoded image data with MIME type (for all generated images)
|
|
105
|
+
|
|
106
|
+
When `path` is provided:
|
|
107
|
+
- Text message with list of saved file paths
|
|
108
|
+
|
|
109
|
+
**Note:** The API may generate multiple images per request. All images will be either returned as base64 data or saved to the specified directory.
|
|
110
|
+
|
|
111
|
+
**Example 1: Return base64 data**
|
|
112
|
+
|
|
113
|
+
```javascript
|
|
114
|
+
{
|
|
115
|
+
"name": "generate_image",
|
|
116
|
+
"arguments": {
|
|
117
|
+
"prompt": "A serene mountain landscape at sunset with a lake reflection",
|
|
118
|
+
"aspectRatio": "16:9",
|
|
119
|
+
"negativePrompt": "people, buildings, text"
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**Example 2: Save to disk**
|
|
125
|
+
|
|
126
|
+
```javascript
|
|
127
|
+
{
|
|
128
|
+
"name": "generate_image",
|
|
129
|
+
"arguments": {
|
|
130
|
+
"prompt": "A cute cat sitting on a sofa",
|
|
131
|
+
"path": "/Users/username/images"
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Response:
|
|
137
|
+
```
|
|
138
|
+
Successfully generated 2 images for prompt: "A cute cat sitting on a sofa"
|
|
139
|
+
|
|
140
|
+
Images saved to:
|
|
141
|
+
- /Users/username/images/image_1737023456789_1.png
|
|
142
|
+
- /Users/username/images/image_1737023456789_2.png
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Development
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
# Install dependencies
|
|
149
|
+
npm install
|
|
150
|
+
|
|
151
|
+
# Build
|
|
152
|
+
npm run build
|
|
153
|
+
|
|
154
|
+
# Watch mode for development
|
|
155
|
+
npm run dev
|
|
156
|
+
|
|
157
|
+
# Run locally
|
|
158
|
+
npm start
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Publishing
|
|
162
|
+
|
|
163
|
+
To publish to npm:
|
|
164
|
+
|
|
165
|
+
1. Update version in `package.json`
|
|
166
|
+
2. Build the project: `npm run build`
|
|
167
|
+
3. Login to npm: `npm login`
|
|
168
|
+
4. Publish: `npm publish --access public`
|
|
169
|
+
|
|
170
|
+
## Requirements
|
|
171
|
+
|
|
172
|
+
- Node.js >= 18.0.0
|
|
173
|
+
- Valid Gemini API key with image generation access
|
|
174
|
+
|
|
175
|
+
## Error Handling
|
|
176
|
+
|
|
177
|
+
The server provides detailed error messages for common issues:
|
|
178
|
+
|
|
179
|
+
- Missing API key
|
|
180
|
+
- API request failures
|
|
181
|
+
- Invalid responses
|
|
182
|
+
- Network timeouts (60 second timeout per request)
|
|
183
|
+
|
|
184
|
+
## License
|
|
185
|
+
|
|
186
|
+
MIT
|
|
187
|
+
|
|
188
|
+
## Contributing
|
|
189
|
+
|
|
190
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
191
|
+
|
|
192
|
+
## Support
|
|
193
|
+
|
|
194
|
+
For issues and questions, please open an issue on the GitHub repository.
|
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,220 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
5
|
+
import axios from "axios";
|
|
6
|
+
import { writeFileSync, mkdirSync, existsSync } from "fs";
|
|
7
|
+
import { join, resolve } from "path";
|
|
8
|
+
// Configuration from environment variables
|
|
9
|
+
const GEMINI_BASE_URL = process.env.GEMINI_BASE_URL || "https://generativelanguage.googleapis.com/v1beta";
|
|
10
|
+
const GEMINI_API_KEY = process.env.GEMINI_API_KEY;
|
|
11
|
+
const GEMINI_MODEL = process.env.GEMINI_MODEL || "gemini-2.5-flash-image";
|
|
12
|
+
// Validate required configuration
|
|
13
|
+
if (!GEMINI_API_KEY) {
|
|
14
|
+
console.error("Error: GEMINI_API_KEY environment variable is required");
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
class GeminiImageMCPServer {
|
|
18
|
+
server;
|
|
19
|
+
constructor() {
|
|
20
|
+
this.server = new Server({
|
|
21
|
+
name: "gemini-image-mcp",
|
|
22
|
+
version: "1.0.0",
|
|
23
|
+
}, {
|
|
24
|
+
capabilities: {
|
|
25
|
+
tools: {},
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
this.setupHandlers();
|
|
29
|
+
}
|
|
30
|
+
setupHandlers() {
|
|
31
|
+
// List available tools
|
|
32
|
+
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
33
|
+
const tools = [
|
|
34
|
+
{
|
|
35
|
+
name: "generate_image",
|
|
36
|
+
description: "Generate an image using Gemini Banana API based on a text prompt. Can save images to a specified directory or return base64 encoded data.",
|
|
37
|
+
inputSchema: {
|
|
38
|
+
type: "object",
|
|
39
|
+
properties: {
|
|
40
|
+
prompt: {
|
|
41
|
+
type: "string",
|
|
42
|
+
description: "The text prompt describing the image to generate",
|
|
43
|
+
},
|
|
44
|
+
aspectRatio: {
|
|
45
|
+
type: "string",
|
|
46
|
+
enum: ["1:1", "16:9", "9:16", "4:3", "3:4"],
|
|
47
|
+
description: "The aspect ratio of the generated image (default: 1:1)",
|
|
48
|
+
default: "1:1",
|
|
49
|
+
},
|
|
50
|
+
negativePrompt: {
|
|
51
|
+
type: "string",
|
|
52
|
+
description: "Optional negative prompt describing what to avoid in the image",
|
|
53
|
+
},
|
|
54
|
+
path: {
|
|
55
|
+
type: "string",
|
|
56
|
+
description: "Optional directory path to save generated images. If provided, images will be saved as PNG files instead of returning base64 data.",
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
required: ["prompt"],
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
];
|
|
63
|
+
return { tools };
|
|
64
|
+
});
|
|
65
|
+
// Handle tool calls
|
|
66
|
+
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
67
|
+
if (request.params.name === "generate_image") {
|
|
68
|
+
return await this.handleImageGeneration(request.params.arguments);
|
|
69
|
+
}
|
|
70
|
+
throw new Error(`Unknown tool: ${request.params.name}`);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
async handleImageGeneration(params) {
|
|
74
|
+
try {
|
|
75
|
+
const { prompt, negativePrompt, path } = params;
|
|
76
|
+
// Construct the full prompt with negative prompt
|
|
77
|
+
let fullPrompt = prompt;
|
|
78
|
+
if (negativePrompt) {
|
|
79
|
+
fullPrompt += `\n\nAvoid: ${negativePrompt}`;
|
|
80
|
+
}
|
|
81
|
+
// Prepare the request payload for Gemini API
|
|
82
|
+
const requestBody = {
|
|
83
|
+
contents: [
|
|
84
|
+
{
|
|
85
|
+
role: "user",
|
|
86
|
+
parts: [
|
|
87
|
+
{
|
|
88
|
+
text: fullPrompt,
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
generationConfig: {
|
|
94
|
+
temperature: 1.0,
|
|
95
|
+
topP: 0.95,
|
|
96
|
+
topK: 40
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
// Make API request
|
|
100
|
+
const url = `${GEMINI_BASE_URL}/v1beta/models/${GEMINI_MODEL}:generateContent`;
|
|
101
|
+
const response = await axios.post(url, requestBody, {
|
|
102
|
+
headers: {
|
|
103
|
+
"Content-Type": "application/json",
|
|
104
|
+
"x-goog-api-key": `${GEMINI_API_KEY}`
|
|
105
|
+
},
|
|
106
|
+
timeout: 60000, // 60 second timeout
|
|
107
|
+
});
|
|
108
|
+
// Check for API errors
|
|
109
|
+
if (response.data.error) {
|
|
110
|
+
throw new Error(`Gemini API error: ${response.data.error.message}`);
|
|
111
|
+
}
|
|
112
|
+
// Check if we have any candidates
|
|
113
|
+
if (!response.data.candidates || response.data.candidates.length === 0) {
|
|
114
|
+
throw new Error("No image data returned from Gemini API");
|
|
115
|
+
}
|
|
116
|
+
// Collect all images from all candidates and parts
|
|
117
|
+
const allImages = [];
|
|
118
|
+
for (const candidate of response.data.candidates) {
|
|
119
|
+
if (candidate.content?.parts) {
|
|
120
|
+
for (const part of candidate.content.parts) {
|
|
121
|
+
if (part.inlineData?.data) {
|
|
122
|
+
allImages.push({
|
|
123
|
+
data: part.inlineData.data,
|
|
124
|
+
mimeType: part.inlineData.mimeType || "image/png",
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (allImages.length === 0) {
|
|
131
|
+
throw new Error("No image data found in API response");
|
|
132
|
+
}
|
|
133
|
+
// If path is provided, save images to disk
|
|
134
|
+
if (path) {
|
|
135
|
+
const savePath = resolve(path);
|
|
136
|
+
// Create directory if it doesn't exist
|
|
137
|
+
if (!existsSync(savePath)) {
|
|
138
|
+
mkdirSync(savePath, { recursive: true });
|
|
139
|
+
}
|
|
140
|
+
const savedFiles = [];
|
|
141
|
+
const timestamp = Date.now();
|
|
142
|
+
// Save all images
|
|
143
|
+
for (let i = 0; i < allImages.length; i++) {
|
|
144
|
+
const image = allImages[i];
|
|
145
|
+
const extension = image.mimeType.split("/")[1] || "png";
|
|
146
|
+
const filename = `image_${timestamp}_${i + 1}.${extension}`;
|
|
147
|
+
const filepath = join(savePath, filename);
|
|
148
|
+
// Decode base64 and save to file
|
|
149
|
+
const buffer = Buffer.from(image.data, "base64");
|
|
150
|
+
writeFileSync(filepath, buffer);
|
|
151
|
+
savedFiles.push(filepath);
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
content: [
|
|
155
|
+
{
|
|
156
|
+
type: "text",
|
|
157
|
+
text: `Successfully generated ${allImages.length} image${allImages.length > 1 ? 's' : ''} for prompt: "${prompt}"\n\nImages saved to:\n${savedFiles.map(f => `- ${f}`).join('\n')}`,
|
|
158
|
+
},
|
|
159
|
+
],
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
// Return base64 encoded images
|
|
164
|
+
const content = [
|
|
165
|
+
{
|
|
166
|
+
type: "text",
|
|
167
|
+
text: `Successfully generated ${allImages.length} image${allImages.length > 1 ? 's' : ''} for prompt: "${prompt}"`,
|
|
168
|
+
},
|
|
169
|
+
];
|
|
170
|
+
// Add all images to content
|
|
171
|
+
for (const image of allImages) {
|
|
172
|
+
content.push({
|
|
173
|
+
type: "image",
|
|
174
|
+
data: image.data,
|
|
175
|
+
mimeType: image.mimeType,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
return { content };
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
if (axios.isAxiosError(error)) {
|
|
183
|
+
const axiosError = error;
|
|
184
|
+
const errorMessage = axiosError.response?.data
|
|
185
|
+
? JSON.stringify(axiosError.response.data)
|
|
186
|
+
: axiosError.message;
|
|
187
|
+
return {
|
|
188
|
+
content: [
|
|
189
|
+
{
|
|
190
|
+
type: "text",
|
|
191
|
+
text: `Error generating image: ${errorMessage}`,
|
|
192
|
+
},
|
|
193
|
+
],
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
return {
|
|
197
|
+
content: [
|
|
198
|
+
{
|
|
199
|
+
type: "text",
|
|
200
|
+
text: `Error generating image: ${error instanceof Error ? error.message : String(error)}`,
|
|
201
|
+
},
|
|
202
|
+
],
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
async run() {
|
|
207
|
+
const transport = new StdioServerTransport();
|
|
208
|
+
await this.server.connect(transport);
|
|
209
|
+
console.error("Gemini Image MCP Server running on stdio");
|
|
210
|
+
console.error(`Using base URL: ${GEMINI_BASE_URL}`);
|
|
211
|
+
console.error(`Using model: ${GEMINI_MODEL}`);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
// Start the server
|
|
215
|
+
const server = new GeminiImageMCPServer();
|
|
216
|
+
server.run().catch((error) => {
|
|
217
|
+
console.error("Fatal error:", error);
|
|
218
|
+
process.exit(1);
|
|
219
|
+
});
|
|
220
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EACL,qBAAqB,EACrB,sBAAsB,GAEvB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,KAAqB,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAC1D,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAErC,2CAA2C;AAC3C,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,kDAAkD,CAAC;AAC1G,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;AAClD,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,wBAAwB,CAAC;AAE1E,kCAAkC;AAClC,IAAI,CAAC,cAAc,EAAE,CAAC;IACpB,OAAO,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAC;IACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AA8BD,MAAM,oBAAoB;IAChB,MAAM,CAAS;IAEvB;QACE,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CACtB;YACE,IAAI,EAAE,kBAAkB;YACxB,OAAO,EAAE,OAAO;SACjB,EACD;YACE,YAAY,EAAE;gBACZ,KAAK,EAAE,EAAE;aACV;SACF,CACF,CAAC;QAEF,IAAI,CAAC,aAAa,EAAE,CAAC;IACvB,CAAC;IAEO,aAAa;QACnB,uBAAuB;QACvB,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE;YAC/D,MAAM,KAAK,GAAW;gBACpB;oBACE,IAAI,EAAE,gBAAgB;oBACtB,WAAW,EAAE,2IAA2I;oBACxJ,WAAW,EAAE;wBACX,IAAI,EAAE,QAAQ;wBACd,UAAU,EAAE;4BACV,MAAM,EAAE;gCACN,IAAI,EAAE,QAAQ;gCACd,WAAW,EAAE,kDAAkD;6BAChE;4BACD,WAAW,EAAE;gCACX,IAAI,EAAE,QAAQ;gCACd,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC;gCAC3C,WAAW,EAAE,wDAAwD;gCACrE,OAAO,EAAE,KAAK;6BACf;4BACD,cAAc,EAAE;gCACd,IAAI,EAAE,QAAQ;gCACd,WAAW,EAAE,gEAAgE;6BAC9E;4BACD,IAAI,EAAE;gCACJ,IAAI,EAAE,QAAQ;gCACd,WAAW,EAAE,oIAAoI;6BAClJ;yBACF;wBACD,QAAQ,EAAE,CAAC,QAAQ,CAAC;qBACrB;iBACF;aACF,CAAC;YAEF,OAAO,EAAE,KAAK,EAAE,CAAC;QACnB,CAAC,CAAC,CAAC;QAEH,oBAAoB;QACpB,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;YACrE,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;gBAC7C,OAAO,MAAM,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,MAAM,CAAC,SAA6C,CAAC,CAAC;YACxG,CAAC;YAED,MAAM,IAAI,KAAK,CAAC,iBAAiB,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,qBAAqB,CAAC,MAA6B;QAG/D,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC;YAEhD,iDAAiD;YACjD,IAAI,UAAU,GAAG,MAAM,CAAC;YAExB,IAAI,cAAc,EAAE,CAAC;gBACnB,UAAU,IAAI,cAAc,cAAc,EAAE,CAAC;YAC/C,CAAC;YAED,6CAA6C;YAC7C,MAAM,WAAW,GAAG;gBAClB,QAAQ,EAAE;oBACR;wBACE,IAAI,EAAE,MAAM;wBACZ,KAAK,EAAE;4BACL;gCACE,IAAI,EAAE,UAAU;6BACjB;yBACF;qBACF;iBACF;gBACD,gBAAgB,EAAE;oBAChB,WAAW,EAAE,GAAG;oBAChB,IAAI,EAAE,IAAI;oBACV,IAAI,EAAE,EAAE;iBACT;aACF,CAAC;YAEF,mBAAmB;YACnB,MAAM,GAAG,GAAG,GAAG,eAAe,kBAAkB,YAAY,kBAAkB,CAAC;YAE/E,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAsB,GAAG,EAAE,WAAW,EAAE;gBACvE,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,gBAAgB,EAAE,GAAG,cAAc,EAAE;iBACtC;gBACD,OAAO,EAAE,KAAK,EAAE,oBAAoB;aACrC,CAAC,CAAC;YAEH,uBAAuB;YACvB,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;gBACxB,MAAM,IAAI,KAAK,CAAC,qBAAqB,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YACtE,CAAC;YAED,kCAAkC;YAClC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,IAAI,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACvE,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;YAC5D,CAAC;YAED,mDAAmD;YACnD,MAAM,SAAS,GAA8C,EAAE,CAAC;YAEhE,KAAK,MAAM,SAAS,IAAI,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;gBACjD,IAAI,SAAS,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC;oBAC7B,KAAK,MAAM,IAAI,IAAI,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;wBAC3C,IAAI,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC;4BAC1B,SAAS,CAAC,IAAI,CAAC;gCACb,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI;gCAC1B,QAAQ,EAAE,IAAI,CAAC,UAAU,CAAC,QAAQ,IAAI,WAAW;6BAClD,CAAC,CAAC;wBACL,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;YAED,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC3B,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;YACzD,CAAC;YAED,2CAA2C;YAC3C,IAAI,IAAI,EAAE,CAAC;gBACT,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;gBAE/B,uCAAuC;gBACvC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAC1B,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC3C,CAAC;gBAED,MAAM,UAAU,GAAa,EAAE,CAAC;gBAChC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBAE7B,kBAAkB;gBAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBAC1C,MAAM,KAAK,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;oBAC3B,MAAM,SAAS,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC;oBACxD,MAAM,QAAQ,GAAG,SAAS,SAAS,IAAI,CAAC,GAAG,CAAC,IAAI,SAAS,EAAE,CAAC;oBAC5D,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;oBAE1C,iCAAiC;oBACjC,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;oBACjD,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;oBAEhC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAC5B,CAAC;gBAED,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,0BAA0B,SAAS,CAAC,MAAM,SAAS,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,iBAAiB,MAAM,0BAA0B,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;yBACpL;qBACF;iBACF,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,+BAA+B;gBAC/B,MAAM,OAAO,GAA6E;oBACxF;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,0BAA0B,SAAS,CAAC,MAAM,SAAS,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,iBAAiB,MAAM,GAAG;qBACnH;iBACF,CAAC;gBAEF,4BAA4B;gBAC5B,KAAK,MAAM,KAAK,IAAI,SAAS,EAAE,CAAC;oBAC9B,OAAO,CAAC,IAAI,CAAC;wBACX,IAAI,EAAE,OAAO;wBACb,IAAI,EAAE,KAAK,CAAC,IAAI;wBAChB,QAAQ,EAAE,KAAK,CAAC,QAAQ;qBACzB,CAAC,CAAC;gBACL,CAAC;gBAED,OAAO,EAAE,OAAO,EAAE,CAAC;YACrB,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC9B,MAAM,UAAU,GAAG,KAAmB,CAAC;gBACvC,MAAM,YAAY,GAAG,UAAU,CAAC,QAAQ,EAAE,IAAI;oBAC5C,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC;oBAC1C,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC;gBAEvB,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,2BAA2B,YAAY,EAAE;yBAChD;qBACF;iBACF,CAAC;YACJ,CAAC;YAED,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,2BAA2B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;qBAC1F;iBACF;aACF,CAAC;QACJ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,GAAG;QACP,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC7C,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAErC,OAAO,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAC1D,OAAO,CAAC,KAAK,CAAC,mBAAmB,eAAe,EAAE,CAAC,CAAC;QACpD,OAAO,CAAC,KAAK,CAAC,gBAAgB,YAAY,EAAE,CAAC,CAAC;IAChD,CAAC;CACF;AAED,mBAAmB;AACnB,MAAM,MAAM,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC1C,MAAM,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IAC3B,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
Binary file
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agentrix/gemini-image-mcp",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "MCP server for generating images using Gemini Banana API",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"gemini-image-mcp": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"prepare": "npm run build",
|
|
13
|
+
"start": "node dist/index.js",
|
|
14
|
+
"dev": "tsc --watch"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"mcp",
|
|
18
|
+
"gemini",
|
|
19
|
+
"image-generation",
|
|
20
|
+
"ai",
|
|
21
|
+
"banana"
|
|
22
|
+
],
|
|
23
|
+
"author": "",
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "https://github.com/xmz-ai/agentrix-mcp-tools.git",
|
|
28
|
+
"directory": "gemini-image-mcp"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@modelcontextprotocol/sdk": "^0.6.0",
|
|
32
|
+
"axios": "^1.7.9"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/node": "^22.10.5",
|
|
36
|
+
"typescript": "^5.7.2"
|
|
37
|
+
},
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=18.0.0"
|
|
40
|
+
}
|
|
41
|
+
}
|