@chrischall/gemini-mcp 1.0.4 → 1.2.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.
@@ -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": "1.0.4"
10
+ "version": "1.2.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": "1.0.4",
18
+ "version": "1.2.0",
19
19
  "author": {
20
20
  "name": "Chris Hall"
21
21
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "gemini-mcp",
3
3
  "displayName": "Gemini Images",
4
- "version": "1.0.4",
4
+ "version": "1.2.0",
5
5
  "description": "MCP server for Google Gemini image generation and editing — generate and edit images via the Gemini API",
6
6
  "author": {
7
7
  "name": "Chris Hall",
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  [![npm](https://img.shields.io/npm/v/@chrischall/gemini-mcp)](https://www.npmjs.com/package/@chrischall/gemini-mcp)
5
5
  [![license](https://img.shields.io/npm/l/@chrischall/gemini-mcp)](LICENSE)
6
6
 
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.
7
+ MCP server for Google Gemini media generation. Exposes eleven 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), an async result poll for long generations, and Files API upload/list/delete for reusable image references. 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
 
@@ -83,6 +83,80 @@ progress), two guards make re-issuing safe and unnecessary:
83
83
  | `gemini_video_generate` | Generate a short video (text→video, image→video, or `edit`) via the Gemini omni model (preview); written to disk as MP4 |
84
84
  | `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) |
85
85
  | `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 |
86
+ | `gemini_upload_file` | Upload an image (or video/audio) to the Gemini Files API once — from a `url`, `data_base64`, or a local `path` — and get a reusable `files/<id>` reference |
87
+ | `gemini_list_files` | List the files currently uploaded under this API key, with MIME types and expiry times |
88
+ | `gemini_delete_file` | Delete an uploaded file before its ~48h expiry (confirm-gated) |
89
+
90
+ ## Sending reference images without burning context
91
+
92
+ Every tool that takes a reference image — `gemini_image_generate`, `gemini_image_edit`,
93
+ `gemini_image_set`, `gemini_interact`, plus `gemini_video_generate` (reference stills) and
94
+ `gemini_music_generate` — accepts them four ways. Only one of them costs model context:
95
+
96
+ | Parameter | Where the bytes travel | Context cost |
97
+ |---|---|---|
98
+ | `images_url` (`master_images_url`) | the **server** downloads the https URL | none |
99
+ | `images_file_uris` (`master_images_file_uris`) | a `files/<id>` reference, already uploaded | none |
100
+ | `images` | read off local disk (stdio builds only) | none |
101
+ | `images_base64` | **through the tool-call JSON** | **~14k tokens per JPEG** |
102
+
103
+ `images_base64` is the fallback of last resort. It costs roughly 14k tokens per modest photo,
104
+ and it is silently corrupted whenever the file read that produced it was truncated — the
105
+ payload still looks like base64, so the failure surfaces as a bad generation rather than an
106
+ error. Prefer any of the other three.
107
+
108
+ ### `images_url` — the server fetches it
109
+
110
+ ```jsonc
111
+ { "prompt": "make it look like winter", "images_url": ["https://example.com/photo.jpg"] }
112
+ ```
113
+
114
+ Fetches are restricted to public `https://` URLs — private, loopback and link-local hosts are
115
+ refused (IPv6 literals are parsed, so `[::ffff:7f00:1]` is caught as loopback), every redirect
116
+ hop is revalidated, and each hop is bounded by a timeout. The response must be
117
+ `Content-Type: image/*` and is capped at **15MB**, enforced while streaming rather than trusted
118
+ from `Content-Length`. A failure names the offending URL. Anything over 6MB is uploaded to the
119
+ Files API and referenced by uri instead of inlined, since `generateContent` caps a whole
120
+ request near 20MB.
121
+
122
+ ### `images_file_uris` — upload once, reference many times
123
+
124
+ ```jsonc
125
+ // 1. upload
126
+ { "tool": "gemini_upload_file", "url": "https://example.com/photo.jpg" }
127
+ // → { "file_uri": "files/abc123", "mime_type": "image/jpeg", "expires": "..." }
128
+
129
+ // 2. reference it, as many times as you like
130
+ { "prompt": "make it winter", "images_file_uris": ["files/abc123"] }
131
+ { "prompt": "make it sunrise", "images_file_uris": ["files/abc123"] }
132
+ ```
133
+
134
+ Uploads are retained **~48h**; after that the reference stops resolving (as a generic 404 —
135
+ see the chained-404 section above). `gemini_image_set` fetches or resolves such a reference
136
+ **once** and passes it to the master and every scene call.
137
+
138
+ On stdio builds, a local `images` path that gets referenced **more than once in a session** is
139
+ uploaded to the Files API automatically (keyed on path + mtime + size), so repeated edits of
140
+ the same photo stop re-sending the bytes. Editing the file invalidates the cached upload.
141
+
142
+ ### `POST /upload` — raw bytes, no base64 at all (hosted connector)
143
+
144
+ The hosted connector exposes an HTTP upload endpoint behind the **same OAuth token as
145
+ `/mcp`**. This is the intended path for an agent with a shell: disk file → curl → `file_uri` →
146
+ tool call, with the image never entering the conversation.
147
+
148
+ ```bash
149
+ curl -X POST https://connector.gemini.nullnet.app/upload \
150
+ -H "Authorization: Bearer $ACCESS_TOKEN" \
151
+ -H "Content-Type: image/jpeg" \
152
+ --data-binary @photo.jpg
153
+ # → {"file_uri":"files/abc123","mime_type":"image/jpeg","expires":"...","...":"..."}
154
+ ```
155
+
156
+ Then pass `"images_file_uris": ["files/abc123"]` to any image tool. The body is streamed
157
+ straight to the Files API (nothing is buffered), so `Content-Length` is required — curl sets it
158
+ automatically with `--data-binary @file`. Accepted content types are `image/*`, `video/*` and
159
+ `audio/*`; an optional `?name=` or `X-Filename` header sets the display name.
86
160
 
87
161
  ## Quick Start
88
162