@chrischall/gemini-mcp 0.8.0 → 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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +17 -6
- package/SKILL.md +44 -16
- package/dist/bundle.js +630 -160
- package/dist/client.js +92 -35
- package/dist/images.js +35 -6
- package/dist/index.js +4 -1
- package/dist/jobs.js +0 -0
- package/dist/models.js +5 -0
- package/dist/tools/generate.js +95 -71
- package/dist/tools/interact.js +65 -50
- package/dist/tools/jobs.js +17 -0
- package/dist/tools/music.js +90 -0
- package/dist/tools/set.js +55 -41
- package/dist/tools/shared.js +99 -20
- package/dist/tools/video.js +92 -0
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/server.json +2 -2
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
},
|
|
8
8
|
"metadata": {
|
|
9
9
|
"description": "MCP server for Google Gemini image generation and editing — generate and edit images via the Gemini API",
|
|
10
|
-
"version": "0.
|
|
10
|
+
"version": "1.0.0"
|
|
11
11
|
},
|
|
12
12
|
"plugins": [
|
|
13
13
|
{
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"displayName": "Gemini Images",
|
|
16
16
|
"source": "./",
|
|
17
17
|
"description": "Generate and edit images with Google Gemini image models (Nano Banana / Nano Banana Pro) via natural language prompts",
|
|
18
|
-
"version": "0.
|
|
18
|
+
"version": "1.0.0",
|
|
19
19
|
"author": {
|
|
20
20
|
"name": "Chris Hall"
|
|
21
21
|
},
|
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
[](https://www.npmjs.com/package/@chrischall/gemini-mcp)
|
|
5
5
|
[](LICENSE)
|
|
6
6
|
|
|
7
|
-
MCP server for Google Gemini
|
|
7
|
+
MCP server for Google Gemini media generation. Exposes eight tools to Claude over stdio: list available models, generate/edit/compose images, generate a consistent set of images from a master prompt, multi-turn image refinement (Interactions API), **video** generation (omni), **music** generation (Lyria), and an async result poll for long generations. Output is written to disk by default (path returned) or returned inline as base64. Built on the Gemini v1beta API (`generativelanguage.googleapis.com`) using the Nano Banana / Nano Banana Pro (images), omni (video), and Lyria (music) model families.
|
|
8
8
|
|
|
9
9
|
Developed and maintained by AI (Claude Code).
|
|
10
10
|
|
|
@@ -26,18 +26,29 @@ The server sends `notifications/progress` heartbeats so hosts that reset their t
|
|
|
26
26
|
progress wait it out. If the host still gives up, the server-side generation usually completes
|
|
27
27
|
anyway: the image is written to the output dir, `gemini_interact` also writes an
|
|
28
28
|
`<image>.json` sidecar recording the `interaction_id`, and `continue_last: true` resumes the
|
|
29
|
-
interaction the lost response belonged to
|
|
30
|
-
|
|
29
|
+
interaction the lost response belonged to.
|
|
30
|
+
|
|
31
|
+
For hosts whose timeout can't be tamed (e.g. Claude Desktop, a fixed ~30s cap that ignores
|
|
32
|
+
progress), two guards make re-issuing safe and unnecessary:
|
|
33
|
+
|
|
34
|
+
- **`async: true`** returns a `job_id` immediately instead of the image, so the call can't
|
|
35
|
+
time out at all; poll `gemini_get_result` with the `job_id` until it's `done`.
|
|
36
|
+
- **`idempotency_key`** makes a repeat call idempotent — a retry with the same key returns the
|
|
37
|
+
recorded result (`reused: true`) instead of billing a second generation. (Even without a key,
|
|
38
|
+
two identical in-flight calls are deduplicated automatically.)
|
|
31
39
|
|
|
32
40
|
## Tools
|
|
33
41
|
|
|
34
42
|
| Tool | Description |
|
|
35
43
|
|------|-------------|
|
|
36
44
|
| `gemini_list_models` | List available Gemini image models and the current default |
|
|
37
|
-
| `
|
|
38
|
-
| `
|
|
39
|
-
| `
|
|
45
|
+
| `gemini_image_generate` | Generate image(s) from a text prompt |
|
|
46
|
+
| `gemini_image_edit` | One-off edits or multi-image composition with a text instruction (for a series of edits, use `gemini_interact`) |
|
|
47
|
+
| `gemini_image_set` | Generate a master image plus N consistent images referencing it |
|
|
40
48
|
| `gemini_interact` | Preferred tool for iterative refinement: multi-turn generation/editing via the Interactions API — chain the returned `interaction_id` via `previous_interaction_id` (or `continue_last: true`) |
|
|
49
|
+
| `gemini_video_generate` | Generate a short video (text→video, image→video, or `edit`) via the Gemini omni model (preview); written to disk as MP4 |
|
|
50
|
+
| `gemini_music_generate` | Generate music from a text prompt via a Lyria model — `lyria-3-clip-preview` (~30s, default) or `lyria-3-pro-preview` (longer, WAV-capable); written to disk as MP3/WAV (preview) |
|
|
51
|
+
| `gemini_get_result` | Fetch an async generation started with `async: true` by its `job_id` (status `running` → `done` result). Lets a long generation outlive a host's `tools/call` timeout |
|
|
41
52
|
|
|
42
53
|
## Quick Start
|
|
43
54
|
|
package/SKILL.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: gemini-mcp
|
|
3
|
-
description: Generate and edit images with Google Gemini
|
|
3
|
+
description: Generate and edit images, video, and music with Google Gemini models via MCP. Use when the user asks to generate, create, or edit images (Gemini / Nano Banana), produce a consistent set of images, compose/blend multiple images, generate a short video (text→video or image→video, via the omni model), or generate music/audio clips (via Lyria). Triggers on phrases like "generate an image of", "edit this image with Gemini", "create a set of consistent images", "make a video of", "generate a video", "generate music", "make a song/audio clip", "use Nano Banana to make", or any request to produce images, video, or music via the Gemini API. Requires the @chrischall/gemini-mcp package installed and the gemini server registered (see Setup below).
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# gemini-mcp
|
|
7
7
|
|
|
8
|
-
MCP server for Google Gemini
|
|
8
|
+
MCP server for Google Gemini media generation — natural-language **image**, **video**, and **music** creation via the Gemini API (Nano Banana / Nano Banana Pro images, omni video, Lyria music).
|
|
9
9
|
|
|
10
10
|
- **npm:** [npmjs.com/package/@chrischall/gemini-mcp](https://www.npmjs.com/package/@chrischall/gemini-mcp)
|
|
11
11
|
- **Source:** [github.com/chrischall/gemini-mcp](https://github.com/chrischall/gemini-mcp)
|
|
@@ -91,38 +91,49 @@ Note: Image generation requires a billing-enabled Google Cloud project.
|
|
|
91
91
|
### Image Generation
|
|
92
92
|
| Tool | Description |
|
|
93
93
|
|------|-------------|
|
|
94
|
-
| `
|
|
95
|
-
| `
|
|
96
|
-
| `
|
|
94
|
+
| `gemini_image_generate(prompt, count?, images?, images_base64?, video_url?, video_path?, google_search?, seed?, filename?, model?, aspect_ratio?, image_size?, thinking_level?, output_dir?, inline?)` | Generate image(s) from a text prompt (optionally image-conditioned via `images`/`images_base64`, or video-conditioned via `video_url`/`video_path`) |
|
|
95
|
+
| `gemini_image_edit(prompt, images?, images_base64?, google_search?, seed?, filename?, model?, aspect_ratio?, image_size?, thinking_level?, output_dir?, inline?)` | Edit or compose input image(s) — by **path** (`images`) or **value** (`images_base64`: data URI or raw base64) — with a text instruction. Requires ≥1 input |
|
|
96
|
+
| `gemini_image_set(master_prompt, scenes? \| count?, reference_mode?, master_images?, master_images_base64?, google_search?, seed?, basename?, model?, thinking_level?, ...)` | Master image (optionally seeded from a reference photo) plus N consistent images referencing it |
|
|
97
97
|
|
|
98
98
|
### Multi-turn (Interactions API)
|
|
99
99
|
| Tool | Description |
|
|
100
100
|
|------|-------------|
|
|
101
101
|
| `gemini_interact(input, previous_interaction_id?, continue_last?, images?, images_base64?, video_url?, video_path?, google_search?, search_types?, model?, aspect_ratio?, image_size?, thinking_level?, filename?, output_dir?, inline?)` | **Preferred tool for iterative refinement.** Generate/edit via Gemini's **Interactions API**. Returns an `interaction_id`; pass it back as `previous_interaction_id` (or set `continue_last: true` to reuse the session's most recent one) to **iteratively refine the same image** conversationally — do NOT start a new interaction or re-upload the image per tweak. Output is **JPEG**. |
|
|
102
102
|
|
|
103
|
+
### Video & Music (preview — funded account)
|
|
104
|
+
| Tool | Description |
|
|
105
|
+
|------|-------------|
|
|
106
|
+
| `gemini_video_generate(prompt, aspect_ratio?, task?, images?, images_base64?, from_clipboard?, previous_interaction_id?, continue_last?, model?, filename?, output_dir?, timeout_ms?, idempotency_key?, async?)` | Generate a short video via the Gemini omni model: `text_to_video` (default), `image_to_video` / `reference_to_video` (supply reference image[s]), or `edit` (with `previous_interaction_id` / `continue_last`). `aspect_ratio` is `16:9` or `9:16`. Written to disk as **MP4**. Runs long — use `async: true` + `gemini_get_result`, or raise `timeout_ms`. |
|
|
107
|
+
| `gemini_music_generate(prompt, model?, audio_format?, images?, images_base64?, from_clipboard?, previous_interaction_id?, continue_last?, filename?, output_dir?, inline?, timeout_ms?, idempotency_key?, async?)` | Generate music from a prompt (mood/genre/instruments/structure/lyrics) via a Lyria model: `lyria-3-clip-preview` (~30s, default) or `lyria-3-pro-preview` (longer, WAV-capable). `audio_format` `mp3` (default) or `wav` (**Pro-only**). Written to disk as MP3/WAV, or returned inline. |
|
|
108
|
+
|
|
109
|
+
### Async / idempotency (any generation tool)
|
|
110
|
+
| Tool | Description |
|
|
111
|
+
|------|-------------|
|
|
112
|
+
| `gemini_get_result(job_id)` | Fetch a generation started with `async: true`. Returns `running` while in flight, then the normal result on completion. Lets a long video/music/image generation outlive a host's `tools/call` timeout. All generation tools also accept `idempotency_key` — a repeat call with the same key returns the recorded result (`reused: true`) instead of billing again. |
|
|
113
|
+
|
|
103
114
|
## Workflows
|
|
104
115
|
|
|
105
116
|
**Generate a single image:**
|
|
106
117
|
```
|
|
107
|
-
|
|
118
|
+
gemini_image_generate(prompt: "a red maple leaf on white background, studio photo")
|
|
108
119
|
→ returns path to saved PNG
|
|
109
120
|
```
|
|
110
121
|
|
|
111
122
|
**Generate multiple variations:**
|
|
112
123
|
```
|
|
113
|
-
|
|
124
|
+
gemini_image_generate(prompt: "a cartoon fox", count: 4, output_dir: "/tmp/foxes")
|
|
114
125
|
→ returns paths to 4 PNG files
|
|
115
126
|
```
|
|
116
127
|
|
|
117
128
|
**Edit an existing image:**
|
|
118
129
|
```
|
|
119
|
-
|
|
130
|
+
gemini_image_edit(prompt: "make the background blue", images: ["/path/to/image.png"])
|
|
120
131
|
→ returns path to edited PNG
|
|
121
132
|
```
|
|
122
133
|
|
|
123
134
|
**Generate a consistent set (master + scenes):**
|
|
124
135
|
```
|
|
125
|
-
|
|
136
|
+
gemini_image_set(
|
|
126
137
|
master_prompt: "a cartoon fox named Rusty, orange fur, blue scarf",
|
|
127
138
|
scenes: ["Rusty waving hello", "Rusty eating an apple", "Rusty sleeping"]
|
|
128
139
|
)
|
|
@@ -131,7 +142,7 @@ gemini_generate_set(
|
|
|
131
142
|
|
|
132
143
|
**Generate variations of a concept:**
|
|
133
144
|
```
|
|
134
|
-
|
|
145
|
+
gemini_image_set(
|
|
135
146
|
master_prompt: "minimalist logo for a coffee shop",
|
|
136
147
|
count: 5
|
|
137
148
|
)
|
|
@@ -140,7 +151,7 @@ gemini_generate_set(
|
|
|
140
151
|
|
|
141
152
|
**Use a reference photo by value (when you have the bytes):**
|
|
142
153
|
```
|
|
143
|
-
|
|
154
|
+
gemini_image_edit(
|
|
144
155
|
prompt: "place this house on a vintage travel-poster background",
|
|
145
156
|
images_base64: ["data:image/jpeg;base64,/9j/4AAQ..."] // or raw base64
|
|
146
157
|
)
|
|
@@ -159,7 +170,24 @@ r2 = gemini_interact(input: "add a sleeping cat on the chair",
|
|
|
159
170
|
r3 = gemini_interact(input: "warmer lighting", continue_last: true)
|
|
160
171
|
→ same chain, without threading the id (uses the session's most recent interaction)
|
|
161
172
|
```
|
|
162
|
-
Prefer this over re-running `
|
|
173
|
+
Prefer this over re-running `gemini_image_edit` when you're making a *series* of incremental edits — the model keeps the prior result in context. Every result echoes `interaction_id` (and `previous_interaction_id` when chaining) plus a `hint` with the exact follow-up call.
|
|
174
|
+
|
|
175
|
+
**Generate a video (preview — runs long, use async):**
|
|
176
|
+
```
|
|
177
|
+
job = gemini_video_generate(prompt: "a paper boat sailing down a rain gutter, cinematic",
|
|
178
|
+
aspect_ratio: "16:9", async: true)
|
|
179
|
+
→ { job_id, status: "running" } (returns immediately — no host timeout)
|
|
180
|
+
gemini_get_result(job_id: job.job_id)
|
|
181
|
+
→ "running" until done, then the MP4 path on disk
|
|
182
|
+
# Animate a still instead: gemini_video_generate(prompt: "…", task: "image_to_video", images: ["/path/still.png"])
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
**Generate music (preview):**
|
|
186
|
+
```
|
|
187
|
+
gemini_music_generate(prompt: "warm lo-fi hip hop, mellow Rhodes, vinyl crackle, 70bpm")
|
|
188
|
+
→ ~30s MP3 on disk (lyria-3-clip-preview)
|
|
189
|
+
# Longer / WAV: gemini_music_generate(prompt: "…", model: "lyria-3-pro-preview", audio_format: "wav")
|
|
190
|
+
```
|
|
163
191
|
**⚠️ Chat-pasted/attached images can't be fed to these tools directly.** A pasted
|
|
164
192
|
image reaches the assistant as a *vision* block — the assistant can SEE it but
|
|
165
193
|
never receives the original bytes, and the host doesn't write it to disk. So
|
|
@@ -176,9 +204,9 @@ extraction:
|
|
|
176
204
|
clipboard itself (osascript), downscales it, and uses it. The user just needs
|
|
177
205
|
to **copy** the image (⌘C — distinct from pasting it inline into chat, which
|
|
178
206
|
doesn't keep it on the clipboard). Works on every image tool:
|
|
179
|
-
`
|
|
207
|
+
`gemini_image_edit(prompt: "…", from_clipboard: true)`.
|
|
180
208
|
- **`GEMINI_INPUT_DIR`** — point it at a folder (e.g. Cowork's `uploads/`); then a
|
|
181
|
-
**bare filename** resolves against it: `
|
|
209
|
+
**bare filename** resolves against it: `gemini_image_edit(prompt: "…", images: ["house.jpg"])`.
|
|
182
210
|
|
|
183
211
|
## Prompting playbook
|
|
184
212
|
|
|
@@ -220,10 +248,10 @@ Condensed from Google's official Nano Banana prompting guide. Core rule:
|
|
|
220
248
|
- **Model text.** When the model returns a caption/explanation (mostly Gemini 3 **Pro**), it's surfaced as `text` in the result metadata.
|
|
221
249
|
- **`google_search: true`** grounds the image in live Google Search (current events, weather, real data — great for infographics). The result metadata includes `grounding` with the `queries` run and the `sources` (`{uri, title}`) used. (`gemini_interact` surfaces `grounding.queries` — the Interactions API returns no clean source list.)
|
|
222
250
|
- **`search_types`** (`gemini_interact` only): `["web_search", "image_search"]` picks the grounding search types (setting it implies `google_search`). **`image_search`** (gemini-3.1-flash-image only) pulls web images via Google Image Search as *visual* references — useful for real-world subjects (a specific butterfly species, a landmark, a product). ⚠️ Two catches: Google ToS require **displaying the returned `grounding.search_suggestions` HTML chips** to the user, and image_search won't depict real people from web images.
|
|
223
|
-
- **`video_url`** (a public YouTube URL, on `
|
|
251
|
+
- **`video_url`** (a public YouTube URL, on `gemini_image_generate` / `gemini_interact`) generates an image from a video reference — **requires a Flash model** (e.g. `model: "gemini-3.1-flash-image"`). For a **local video file**, use **`video_path`** instead: the file is uploaded to the Gemini Files API (streamed from disk, 2 GB max), waited to `ACTIVE`, and referenced by its `files/…` uri. The result metadata echoes `video_file` (`{uri, name, expires}`, ~48h retention) — reuse that uri as `video_url` in later calls to skip re-uploading.
|
|
224
252
|
- **`gemini_interact`** is the multi-turn path: it returns an `interaction_id`; thread it back via `previous_interaction_id` for conversational refinement. Output is **JPEG only**. (The Interactions API is GA as of 2026-07; it uses a different request shape than the `generate`/`edit`/`set` tools.)
|
|
225
253
|
- `output_dir` per-call overrides `$GEMINI_OUTPUT_DIR` overrides cwd. `inline: true` returns bytes (with a metadata text block) instead of writing.
|
|
226
|
-
- `count` and `scenes` are mutually exclusive in `
|
|
254
|
+
- `count` and `scenes` are mutually exclusive in `gemini_image_set`; `reference_mode: "chain"` references the previous image instead of the master.
|
|
227
255
|
- Aspect ratios: `1:1`, `16:9`, `9:16`, `4:3`, `3:4`, `2:3`, `3:2`, … · Image sizes: `512` (0.5K, Flash only), `1K`, `2K`, `4K`. `4K` is the max native output — true 18×24 in @ 300 DPI (5400×7200) needs an external upscale step.
|
|
228
256
|
- All generated images carry a **SynthID** watermark (Google).
|
|
229
257
|
- The model can mis-render text/Roman numerals (e.g. years) — verify any text in the output; it's a model limitation, not a tool setting.
|