@chrischall/gemini-mcp 2.3.2 → 2.3.3
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 +4 -2
- package/dist/bundle.js +34 -6
- package/dist/version.js +1 -1
- package/package.json +2 -2
- package/server.json +2 -2
- package/skills/gemini-mcp/SKILL.md +1 -1
|
@@ -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": "2.3.
|
|
10
|
+
"version": "2.3.3"
|
|
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": "2.3.
|
|
18
|
+
"version": "2.3.3",
|
|
19
19
|
"author": {
|
|
20
20
|
"name": "Chris Hall"
|
|
21
21
|
},
|
package/README.md
CHANGED
|
@@ -26,7 +26,8 @@ Developed and maintained by AI (Claude Code).
|
|
|
26
26
|
|
|
27
27
|
Sending a **local file** to Google (the `images` / `master_images` / `video_path` inputs, or
|
|
28
28
|
`gemini_upload_file`'s `path`) and every **delete** ask for confirmation first. A client that can
|
|
29
|
-
show a confirmation prompt (Claude Code) gets the real prompt
|
|
29
|
+
show a confirmation prompt (Claude Code) gets the real prompt, unless `MCP_CONFIRM_ELICITATION=off`.
|
|
30
|
+
Elsewhere the first call does
|
|
30
31
|
nothing and returns a preview (the resolved local paths with their MIME types and sizes, or the
|
|
31
32
|
method/path being deleted) plus a `confirmToken`; only a repeat call with the same arguments and
|
|
32
33
|
that token proceeds. The token is single-use, expires, and is bound to the exact arguments — a
|
|
@@ -35,7 +36,8 @@ changed prompt or a swapped file between the two calls is refused. Pure text pro
|
|
|
35
36
|
|
|
36
37
|
| variable | default | |
|
|
37
38
|
|---|---|---|
|
|
38
|
-
| `MCP_CONFIRM_MODE` | `ask-user` | What a write does on a client that cannot show a confirmation prompt (claude.ai, Claude Desktop). `ask-user`: two steps — the first call does nothing and returns a preview plus a token, and the model must get your approval in chat before calling again with it. `auto`: the same two steps, but the model may use the token after reviewing the preview itself. `refuse`: writes are refused on such clients. A client that can show prompts (Claude Code) always gets the real prompt
|
|
39
|
+
| `MCP_CONFIRM_MODE` | `ask-user` | What a write does on a client that cannot show a confirmation prompt (claude.ai, Claude Desktop). `ask-user`: two steps — the first call does nothing and returns a preview plus a token, and the model must get your approval in chat before calling again with it. `auto`: the same two steps, but the model may use the token after reviewing the preview itself. `refuse`: writes are refused on such clients. A client that can show prompts (Claude Code) always gets the real prompt, unless `MCP_CONFIRM_ELICITATION=off`. An unrecognised value is treated as `refuse`. |
|
|
40
|
+
| `MCP_CONFIRM_ELICITATION` | `on` | `off` never shows a confirmation prompt, so every client gets the `MCP_CONFIRM_MODE` path. Set it for a client that claims to support prompts but never shows one (the gated call hangs — opencode 2.0.x). Any other value stays `on`, with a warning on stderr. |
|
|
39
41
|
| `MCP_CONFIRM_TTL_SECONDS` | `600` | How long a token stays valid. |
|
|
40
42
|
| `MCP_CONFIRM_SECRET` | random per process | Signing key; set it only if tokens must survive a server restart. |
|
|
41
43
|
|
package/dist/bundle.js
CHANGED
|
@@ -58852,6 +58852,15 @@ ${JSON.stringify(preview, null, 2)}`,
|
|
|
58852
58852
|
};
|
|
58853
58853
|
const response = inputResponse(ctx.mcpReq.inputResponses, requestKey);
|
|
58854
58854
|
const accepted = acceptedContent(ctx.mcpReq.inputResponses, requestKey, confirmationSchema);
|
|
58855
|
+
if (options.elicitation === false) {
|
|
58856
|
+
return textResult({
|
|
58857
|
+
confirmed: false,
|
|
58858
|
+
dispatched: false,
|
|
58859
|
+
action: options.action,
|
|
58860
|
+
reason: "confirmation-unsupported",
|
|
58861
|
+
note: options.unsupportedNote ? `${DISABLED_NOTE}. ${options.unsupportedNote}` : `${DISABLED_NOTE}.`
|
|
58862
|
+
});
|
|
58863
|
+
}
|
|
58855
58864
|
if (response.kind === "missing") {
|
|
58856
58865
|
if (callerAcceptsFormElicitation(ctx) === false) {
|
|
58857
58866
|
return textResult({
|
|
@@ -58882,7 +58891,7 @@ ${JSON.stringify(preview, null, 2)}`,
|
|
|
58882
58891
|
note: "Nothing was changed because the confirmation was declined, cancelled, or left unchecked."
|
|
58883
58892
|
});
|
|
58884
58893
|
}
|
|
58885
|
-
var DEFAULT_REQUEST_KEY, DEFAULT_CONFIRMATION_LABEL, UNSUPPORTED_NOTE, STATE_PREFIX;
|
|
58894
|
+
var DEFAULT_REQUEST_KEY, DEFAULT_CONFIRMATION_LABEL, UNSUPPORTED_NOTE, DISABLED_NOTE, STATE_PREFIX;
|
|
58886
58895
|
var init_confirmation = __esm({
|
|
58887
58896
|
"node_modules/@chrischall/mcp-utils/dist/server/confirmation.js"() {
|
|
58888
58897
|
init_dist();
|
|
@@ -58893,6 +58902,7 @@ var init_confirmation = __esm({
|
|
|
58893
58902
|
DEFAULT_REQUEST_KEY = "confirmation";
|
|
58894
58903
|
DEFAULT_CONFIRMATION_LABEL = "Confirm this action should proceed.";
|
|
58895
58904
|
UNSUPPORTED_NOTE = "Nothing was done because this client cannot show a confirmation prompt (it declares no MCP elicitation capability), and this action is never taken without one";
|
|
58905
|
+
DISABLED_NOTE = "Nothing was done because confirmation prompts are turned off for this server, and this action is never taken without one";
|
|
58896
58906
|
STATE_PREFIX = "mcpu.confirm.v1.";
|
|
58897
58907
|
}
|
|
58898
58908
|
});
|
|
@@ -59046,7 +59056,7 @@ async function tokenConfirmation(action, fb) {
|
|
|
59046
59056
|
}
|
|
59047
59057
|
async function requireConfirmationWithFallback(ctx, options) {
|
|
59048
59058
|
const { tokenFallback, ...confirmation } = options;
|
|
59049
|
-
if (tokenFallback && callerAcceptsFormElicitation(ctx) === false) {
|
|
59059
|
+
if (tokenFallback && (options.elicitation === false || callerAcceptsFormElicitation(ctx) === false)) {
|
|
59050
59060
|
return tokenConfirmation(options.action, tokenFallback);
|
|
59051
59061
|
}
|
|
59052
59062
|
return requireConfirmation(ctx, confirmation);
|
|
@@ -59223,6 +59233,20 @@ function readConfirmMode(env = process.env) {
|
|
|
59223
59233
|
}
|
|
59224
59234
|
return "refuse";
|
|
59225
59235
|
}
|
|
59236
|
+
function readConfirmElicitation(env = process.env) {
|
|
59237
|
+
const raw = readEnvVar("MCP_CONFIRM_ELICITATION", { env })?.trim().toLowerCase();
|
|
59238
|
+
if (!raw || raw === "on")
|
|
59239
|
+
return "on";
|
|
59240
|
+
if (raw === "off")
|
|
59241
|
+
return "off";
|
|
59242
|
+
const key = `elicitation:${raw}`;
|
|
59243
|
+
if (!warned.has(key)) {
|
|
59244
|
+
warned.add(key);
|
|
59245
|
+
process.stderr.write(`MCP_CONFIRM_ELICITATION="${raw}" is not one of on, off; treating it as on.
|
|
59246
|
+
`);
|
|
59247
|
+
}
|
|
59248
|
+
return "on";
|
|
59249
|
+
}
|
|
59226
59250
|
function readConfirmTtl(env) {
|
|
59227
59251
|
const raw = readEnvVar("MCP_CONFIRM_TTL_SECONDS", { env })?.trim();
|
|
59228
59252
|
if (!raw)
|
|
@@ -59275,10 +59299,13 @@ function confirmationFromEnv(options) {
|
|
|
59275
59299
|
const spent = callerSpent ?? spentTokenStoreFromEnv(env);
|
|
59276
59300
|
const mode = readConfirmMode(env);
|
|
59277
59301
|
const ttlSeconds = readConfirmTtl(env);
|
|
59302
|
+
const elicitationOff = readConfirmElicitation(env) === "off";
|
|
59278
59303
|
const bound = args === void 0 ? void 0 : boundArgs(args);
|
|
59279
|
-
const
|
|
59304
|
+
const bindingAdded = bound === void 0 || rest.binding ? rest : { ...rest, binding: { key: confirmKeyFromEnv(env), args: bound, ttlSeconds: ttlSeconds ?? DEFAULT_TTL_SECONDS2 } };
|
|
59305
|
+
const confirmation = elicitationOff ? { ...bindingAdded, elicitation: false } : bindingAdded;
|
|
59280
59306
|
if (mode === "refuse" || ttlSeconds === void 0) {
|
|
59281
|
-
const
|
|
59307
|
+
const reason = mode === "refuse" ? REFUSE_HINT : BAD_TTL_HINT;
|
|
59308
|
+
const hint = elicitationOff ? `${ELICITATION_OFF_HINT} ${reason}` : reason;
|
|
59282
59309
|
return {
|
|
59283
59310
|
...confirmation,
|
|
59284
59311
|
unsupportedNote: confirmation.unsupportedNote ? `${confirmation.unsupportedNote} ${hint}` : hint
|
|
@@ -59304,7 +59331,7 @@ function confirmationFromEnv(options) {
|
|
|
59304
59331
|
}
|
|
59305
59332
|
};
|
|
59306
59333
|
}
|
|
59307
|
-
var MODES, DEFAULT_TTL_SECONDS2, warned, processKey, fileStores, CONFIRM_TOKEN_AUTO_INSTRUCTION, REFUSE_HINT, BAD_TTL_HINT;
|
|
59334
|
+
var MODES, DEFAULT_TTL_SECONDS2, warned, processKey, fileStores, CONFIRM_TOKEN_AUTO_INSTRUCTION, REFUSE_HINT, ELICITATION_OFF_HINT, BAD_TTL_HINT;
|
|
59308
59335
|
var init_confirm_env = __esm({
|
|
59309
59336
|
"node_modules/@chrischall/mcp-utils/dist/server/confirm-env.js"() {
|
|
59310
59337
|
init_config();
|
|
@@ -59316,6 +59343,7 @@ var init_confirm_env = __esm({
|
|
|
59316
59343
|
fileStores = /* @__PURE__ */ new Map();
|
|
59317
59344
|
CONFIRM_TOKEN_AUTO_INSTRUCTION = "Nothing has been done yet. Review this preview; if it is what was intended, call again with the same arguments plus confirmToken. (This server runs with MCP_CONFIRM_MODE=auto, so the user's approval in chat is not required.)";
|
|
59318
59345
|
REFUSE_HINT = "Set MCP_CONFIRM_MODE=ask-user on the server to allow two-step confirmation instead.";
|
|
59346
|
+
ELICITATION_OFF_HINT = "MCP_CONFIRM_ELICITATION=off on the server turns confirmation prompts off.";
|
|
59319
59347
|
BAD_TTL_HINT = "MCP_CONFIRM_TTL_SECONDS on the server is not a positive whole number of seconds; fix it to allow two-step confirmation.";
|
|
59320
59348
|
}
|
|
59321
59349
|
});
|
|
@@ -60755,7 +60783,7 @@ async function loadStdioDotenv() {
|
|
|
60755
60783
|
}
|
|
60756
60784
|
|
|
60757
60785
|
// src/version.ts
|
|
60758
|
-
var VERSION = "2.3.
|
|
60786
|
+
var VERSION = "2.3.3";
|
|
60759
60787
|
|
|
60760
60788
|
// src/errors.ts
|
|
60761
60789
|
init_dist2();
|
package/dist/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** Single source of the server version. release-please bumps the literal below. */
|
|
2
|
-
export const VERSION = '2.3.
|
|
2
|
+
export const VERSION = '2.3.3'; // x-release-please-version
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chrischall/gemini-mcp",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.3",
|
|
4
4
|
"mcpName": "io.github.chrischall/gemini-mcp",
|
|
5
5
|
"description": "Gemini image-generation MCP server for Claude — developed and maintained by AI (Claude Code)",
|
|
6
6
|
"author": "Claude Code (AI) <https://www.anthropic.com/claude>",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"typecheck": "tsc -p tsconfig.test.json"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@chrischall/mcp-utils": "^2.
|
|
49
|
+
"@chrischall/mcp-utils": "^2.15.0",
|
|
50
50
|
"@modelcontextprotocol/server": "^2.3.0",
|
|
51
51
|
"dotenv": "^18.0.2",
|
|
52
52
|
"zod": "^4.6.5"
|
package/server.json
CHANGED
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
"url": "https://github.com/chrischall/gemini-mcp",
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
|
-
"version": "2.3.
|
|
9
|
+
"version": "2.3.3",
|
|
10
10
|
"packages": [
|
|
11
11
|
{
|
|
12
12
|
"registryType": "npm",
|
|
13
13
|
"identifier": "@chrischall/gemini-mcp",
|
|
14
|
-
"version": "2.3.
|
|
14
|
+
"version": "2.3.3",
|
|
15
15
|
"transport": {
|
|
16
16
|
"type": "stdio"
|
|
17
17
|
},
|
|
@@ -307,7 +307,7 @@ Condensed from Google's official Nano Banana prompting guide. Core rule:
|
|
|
307
307
|
|
|
308
308
|
## Notes
|
|
309
309
|
|
|
310
|
-
- **Confirmations.** Local file inputs (`images`, `master_images`, `video_path`, `gemini_upload_file`'s `path`) and every delete are confirmed before anything is sent: a confirmation prompt where the client supports one; otherwise the first call does nothing and returns `status: "confirmation-required"` with a `preview` (resolved paths, MIME types, sizes — or the method/path being deleted) and a `confirmToken`. Show the preview to the user, and only after they approve call again with the **same arguments** plus `confirmToken`. The token is single-use, expires (default 10 min), and is bound to those exact arguments — change anything and the call is refused (`DRAFT_CHANGED`, with a fresh preview and token). `MCP_CONFIRM_MODE` on the server picks `ask-user` (default), `auto` (the model may approve after reviewing the preview) or `refuse`. Text prompts, URLs, `files/` references and base64 inputs are not gated.
|
|
310
|
+
- **Confirmations.** Local file inputs (`images`, `master_images`, `video_path`, `gemini_upload_file`'s `path`) and every delete are confirmed before anything is sent: a confirmation prompt where the client supports one (unless the server sets `MCP_CONFIRM_ELICITATION=off`); otherwise the first call does nothing and returns `status: "confirmation-required"` with a `preview` (resolved paths, MIME types, sizes — or the method/path being deleted) and a `confirmToken`. Show the preview to the user, and only after they approve call again with the **same arguments** plus `confirmToken`. The token is single-use, expires (default 10 min), and is bound to those exact arguments — change anything and the call is refused (`DRAFT_CHANGED`, with a fresh preview and token). `MCP_CONFIRM_MODE` on the server picks `ask-user` (default), `auto` (the model may approve after reviewing the preview) or `refuse`. Text prompts, URLs, `files/` references and base64 inputs are not gated.
|
|
311
311
|
- **Input images** accept either file **paths** (`images` / `master_images`) or **base64/data-URI values** (`images_base64` / `master_images_base64`).
|
|
312
312
|
- **`seed`** makes a result reproducible; it's echoed in the result metadata (a random one is chosen + echoed when omitted). `count>1` uses `seed, seed+1, …` so the images differ. Determinism isn't fully guaranteed by the model.
|
|
313
313
|
- **`filename`/`basename`** set the output name (extension stripped); names never overwrite (a `-2`, `-3` suffix is added). The result echoes the absolute path(s), `model`, `seed`, and aspect/size.
|