@chrischall/gemini-mcp 2.3.1 → 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 +136 -44
- package/dist/version.js +1 -1
- package/package.json +4 -4
- 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
|
@@ -24393,7 +24393,7 @@ var init_internal = __esm({
|
|
|
24393
24393
|
}
|
|
24394
24394
|
});
|
|
24395
24395
|
|
|
24396
|
-
// node_modules/@modelcontextprotocol/server/dist/src-
|
|
24396
|
+
// node_modules/@modelcontextprotocol/server/dist/src-Cqbh3MYc.mjs
|
|
24397
24397
|
function stampErrorBrands(instance, ctor) {
|
|
24398
24398
|
const brands = /* @__PURE__ */ new Set();
|
|
24399
24399
|
let current = ctor;
|
|
@@ -26373,7 +26373,8 @@ function build() {
|
|
|
26373
26373
|
ListResourceTemplatesResultResponseSchema: wireResultResponse(ListResourceTemplatesResultSchema$1),
|
|
26374
26374
|
ReadResourceResultResponseSchema: wireResultResponse(z2.union([ReadResourceResultSchema$1, InputRequiredResultSchema])),
|
|
26375
26375
|
CompleteResultResponseSchema: wireResultResponse(CompleteResultSchema$1),
|
|
26376
|
-
DiscoverResultResponseSchema: wireResultResponse(DiscoverResultSchema$1)
|
|
26376
|
+
DiscoverResultResponseSchema: wireResultResponse(DiscoverResultSchema$1),
|
|
26377
|
+
SubscriptionsListenResultResponseSchema: wireResultResponse(SubscriptionsListenResultSchema$1)
|
|
26377
26378
|
};
|
|
26378
26379
|
}
|
|
26379
26380
|
function buildSchemas2026() {
|
|
@@ -26592,6 +26593,9 @@ function isSpecRequestMethod(method) {
|
|
|
26592
26593
|
function isSpecNotificationMethod(method) {
|
|
26593
26594
|
return ALL_CODECS.some((codec2) => codec2.hasNotificationMethod(method));
|
|
26594
26595
|
}
|
|
26596
|
+
function isExtensionReusedRequestMethod(method) {
|
|
26597
|
+
return method === "tasks/get" || method === "tasks/cancel";
|
|
26598
|
+
}
|
|
26595
26599
|
function isPlainObject$3(value) {
|
|
26596
26600
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
26597
26601
|
}
|
|
@@ -27166,8 +27170,8 @@ function normalizeRawShapeSchema(schema) {
|
|
|
27166
27170
|
return schema;
|
|
27167
27171
|
}
|
|
27168
27172
|
var z2, BRANDS, OAuthError, SdkErrorCode, SdkError, SdkHttpError, FIRST_MODERN_PROTOCOL_VERSION, SUPPORTED_MODERN_PROTOCOL_VERSIONS, TOOL_RESULT_FOREIGN_FAMILY_KEYS, memo$1, REF_REWRITE_DATA_POSITION_KEYS, REF_REWRITE_NAME_MAP_KEYS, requestMethodKeys$1, notificationMethodKeys$1, resultMethodKeys, maps$1, rev2025RequestMethods, rev2025NotificationMethods, NOT_IN_ERA$1, rev2025Codec, memo, CACHEABLE_RESULT_METHODS, RESULT_CACHE_HINT_FALLBACK, ProtocolErrorCode, ProtocolError, ResourceNotFoundError, UrlElicitationRequiredError, UnsupportedProtocolVersionError, MissingRequiredClientCapabilityError, DEFAULT_CACHE_TTL_MS, DEFAULT_CACHE_SCOPE, EXTENDED_RESULT_TYPE_METHODS, INPUT_REQUEST_METHODS_2026, maps, requestMethodKeys, notificationMethodKeys, rev2026RequestMethods, rev2026NotificationMethods, NOT_IN_ERA, REQUIRED_ENVELOPE_KEYS, rev2026Codec, wireResultSchemasMemo, MODERN_WIRE_REVISION, ALL_CODECS, schemas_exports, isJSONRPCRequest, isJSONRPCNotification, isJSONRPCResultResponse, isJSONRPCErrorResponse, isInputRequiredResult, X_MCP_HEADER_KEY, RFC9110_TOKEN, PERMITTED_X_MCP_HEADER_TYPES, NON_REACHABLE_SUBSCHEMA_KEYWORDS, OBJECT_VALUED_SUBSCHEMA_KEYWORDS, HEADER_MISMATCH_ERROR_CODE, INBOUND_VALIDATION_LADDER, LADDER_ERROR_HTTP_STATUS, warnedZodFallback, JSON_SCHEMA_CONVERSION_TARGET, DATETIME_FRACTION_DIGITS, ANNOTATION_ONLY_JSON_SCHEMA_KEYWORDS, ROOT_KEYS, PROPERTY_KEYS_BY_TYPE, SUPPORTED_STRING_FORMATS, inputRequired, REQUEST_STATE_ONLY_LEG_PACING_MS, SPEC_SCHEMA_KEYS, authSchemas, _specTypeSchemas, _isSpecType, specTypeSchemas, isSpecType, DEFAULT_REQUEST_TIMEOUT_MSEC, RESERVED_ENVELOPE_META_KEYS, RETRY_PARAMS_KEYS, NO_REQUEST_STATE, writeNegotiatedProtocolVersion, Protocol, require_content_type, import_content_type, STDIO_DEFAULT_MAX_BUFFER_SIZE, ReadBuffer, TOOL_NAME_REGEX;
|
|
27169
|
-
var
|
|
27170
|
-
"node_modules/@modelcontextprotocol/server/dist/src-
|
|
27173
|
+
var init_src_Cqbh3MYc = __esm({
|
|
27174
|
+
"node_modules/@modelcontextprotocol/server/dist/src-Cqbh3MYc.mjs"() {
|
|
27171
27175
|
init_chunk_Br0eD_fh();
|
|
27172
27176
|
init_dialects_DoSzNhcb();
|
|
27173
27177
|
init_internal();
|
|
@@ -28267,6 +28271,8 @@ var init_src_BHSMhZ_W = __esm({
|
|
|
28267
28271
|
_transport;
|
|
28268
28272
|
_requestMessageId = 0;
|
|
28269
28273
|
_requestHandlers = /* @__PURE__ */ new Map();
|
|
28274
|
+
/** Methods registered with an explicit schema; the era gate in `_onrequest` reads it for the Tasks extension names. */
|
|
28275
|
+
_customSchemaRequestMethods = /* @__PURE__ */ new Set();
|
|
28270
28276
|
_requestHandlerAbortControllers = /* @__PURE__ */ new Map();
|
|
28271
28277
|
_notificationHandlers = /* @__PURE__ */ new Map();
|
|
28272
28278
|
_responseHandlers = /* @__PURE__ */ new Map();
|
|
@@ -28550,7 +28556,7 @@ var init_src_BHSMhZ_W = __esm({
|
|
|
28550
28556
|
return;
|
|
28551
28557
|
}
|
|
28552
28558
|
}
|
|
28553
|
-
if (isSpecRequestMethod(request.method) && !codec2.hasRequestMethod(request.method)) {
|
|
28559
|
+
if (isSpecRequestMethod(request.method) && !codec2.hasRequestMethod(request.method) && !(isExtensionReusedRequestMethod(request.method) && this._customSchemaRequestMethods.has(request.method))) {
|
|
28554
28560
|
sendErrorResponse(ProtocolErrorCode.MethodNotFound, "Method not found");
|
|
28555
28561
|
return;
|
|
28556
28562
|
}
|
|
@@ -28683,8 +28689,11 @@ var init_src_BHSMhZ_W = __esm({
|
|
|
28683
28689
|
}
|
|
28684
28690
|
request(request, schemaOrOptions, maybeOptions) {
|
|
28685
28691
|
const codec2 = this._resolveOutboundCodec(request.method);
|
|
28692
|
+
if (isStandardSchema(schemaOrOptions)) {
|
|
28693
|
+
if (!isExtensionReusedRequestMethod(request.method)) this._assertOutboundRequestInEra(codec2, request.method);
|
|
28694
|
+
return this._requestWithSchemaViaCodec(codec2, request, schemaOrOptions, maybeOptions);
|
|
28695
|
+
}
|
|
28686
28696
|
this._assertOutboundRequestInEra(codec2, request.method);
|
|
28687
|
-
if (isStandardSchema(schemaOrOptions)) return this._requestWithSchemaViaCodec(codec2, request, schemaOrOptions, maybeOptions);
|
|
28688
28697
|
const validate2 = codecResultValidator(codec2, request.method);
|
|
28689
28698
|
if (validate2 === void 0) throw new TypeError(`'${request.method}' is not a spec method; pass a result schema as the second argument to request().`);
|
|
28690
28699
|
return this._requestWithSchemaViaCodec(codec2, request, validate2, schemaOrOptions);
|
|
@@ -28928,6 +28937,8 @@ var init_src_BHSMhZ_W = __esm({
|
|
|
28928
28937
|
return maybeHandler(parsed.data, ctx);
|
|
28929
28938
|
};
|
|
28930
28939
|
else throw new TypeError("setRequestHandler: handler is required");
|
|
28940
|
+
if (typeof schemasOrHandler === "function") this._customSchemaRequestMethods.delete(method);
|
|
28941
|
+
else this._customSchemaRequestMethods.add(method);
|
|
28931
28942
|
this._requestHandlers.set(method, this._wrapHandler(method, stored));
|
|
28932
28943
|
}
|
|
28933
28944
|
/**
|
|
@@ -28957,6 +28968,7 @@ var init_src_BHSMhZ_W = __esm({
|
|
|
28957
28968
|
*/
|
|
28958
28969
|
removeRequestHandler(method) {
|
|
28959
28970
|
this._requestHandlers.delete(method);
|
|
28971
|
+
this._customSchemaRequestMethods.delete(method);
|
|
28960
28972
|
}
|
|
28961
28973
|
/**
|
|
28962
28974
|
* Asserts that a request handler has not already been set for the given method, in preparation for a new one being automatically installed.
|
|
@@ -36099,7 +36111,7 @@ var init_shimsNode = __esm({
|
|
|
36099
36111
|
}
|
|
36100
36112
|
});
|
|
36101
36113
|
|
|
36102
|
-
// node_modules/@modelcontextprotocol/server/dist/mcp-
|
|
36114
|
+
// node_modules/@modelcontextprotocol/server/dist/mcp-DIH4cS6P.mjs
|
|
36103
36115
|
function isCompletable(schema) {
|
|
36104
36116
|
return !!schema && typeof schema === "object" && COMPLETABLE_SYMBOL in schema;
|
|
36105
36117
|
}
|
|
@@ -36209,6 +36221,30 @@ function serverIdentityOf(server) {
|
|
|
36209
36221
|
function discoverAdvertisedCapabilities(capabilities) {
|
|
36210
36222
|
return { ...capabilities };
|
|
36211
36223
|
}
|
|
36224
|
+
function toolInputElementCount(value, max) {
|
|
36225
|
+
let count = 0;
|
|
36226
|
+
const stack = [value];
|
|
36227
|
+
while (stack.length > 0) {
|
|
36228
|
+
const node2 = stack.pop();
|
|
36229
|
+
if (node2 === null || typeof node2 !== "object") continue;
|
|
36230
|
+
if (Array.isArray(node2)) for (const child of node2) {
|
|
36231
|
+
if (++count > max) return count;
|
|
36232
|
+
if (child !== null && typeof child === "object") stack.push(child);
|
|
36233
|
+
}
|
|
36234
|
+
else for (const key in node2) {
|
|
36235
|
+
if (!Object.prototype.hasOwnProperty.call(node2, key)) continue;
|
|
36236
|
+
if (++count > max) return count;
|
|
36237
|
+
const child = node2[key];
|
|
36238
|
+
if (child !== null && typeof child === "object") stack.push(child);
|
|
36239
|
+
}
|
|
36240
|
+
}
|
|
36241
|
+
return count;
|
|
36242
|
+
}
|
|
36243
|
+
function resolveMaxToolInputElements(value) {
|
|
36244
|
+
if (value === void 0 || value === Infinity) return void 0;
|
|
36245
|
+
if (typeof value !== "number" || Number.isNaN(value) || value < 1) throw new RangeError(`maxToolInputElements must be a number of at least 1, or Infinity, got ${String(value)}`);
|
|
36246
|
+
return value;
|
|
36247
|
+
}
|
|
36212
36248
|
function createToolExecutor(inputSchema, handler) {
|
|
36213
36249
|
if (inputSchema) {
|
|
36214
36250
|
const callback$1 = handler;
|
|
@@ -36217,6 +36253,12 @@ function createToolExecutor(inputSchema, handler) {
|
|
|
36217
36253
|
const callback = handler;
|
|
36218
36254
|
return async (_args, ctx) => callback(ctx);
|
|
36219
36255
|
}
|
|
36256
|
+
function convertListedInputSchema(name, inputSchema) {
|
|
36257
|
+
const json2 = standardSchemaToJsonSchema(inputSchema, "input");
|
|
36258
|
+
const scan = scanXMcpHeaderDeclarations(json2);
|
|
36259
|
+
if (!scan.valid) console.warn(`[mcp-sdk] tool '${name}' carries an invalid x-mcp-header declaration and will be excluded by conforming Streamable HTTP clients: ${scan.reason}`);
|
|
36260
|
+
return json2;
|
|
36261
|
+
}
|
|
36220
36262
|
function convertOutputSchemaJson(outputSchema) {
|
|
36221
36263
|
if (outputSchema === void 0) return void 0;
|
|
36222
36264
|
try {
|
|
@@ -36229,7 +36271,7 @@ function createPromptHandler(name, argsSchema, callback) {
|
|
|
36229
36271
|
if (argsSchema) {
|
|
36230
36272
|
const typedCallback = callback;
|
|
36231
36273
|
return async (args, ctx) => {
|
|
36232
|
-
const parseResult = await validateStandardSchema(argsSchema, args);
|
|
36274
|
+
const parseResult = await validateStandardSchema(argsSchema, args ?? {});
|
|
36233
36275
|
if (!parseResult.success) throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Invalid arguments for prompt ${name}: ${parseResult.error}`);
|
|
36234
36276
|
return typedCallback(parseResult.data, ctx);
|
|
36235
36277
|
};
|
|
@@ -36259,9 +36301,9 @@ function unwrapOptionalSchema(schema) {
|
|
|
36259
36301
|
return schema.def?.innerType ?? schema;
|
|
36260
36302
|
}
|
|
36261
36303
|
var COMPLETABLE_SYMBOL, MAX_TIMER_DELAY_MS, DEFAULT_MAX_SUBSCRIPTIONS, CHANGE_NOTIFICATION_METHODS, StdioListenRouter, DEFAULT_LEGACY_SHIM_MAX_ROUNDS, DEFAULT_LEGACY_SHIM_ROUND_TIMEOUT_MS, LegacyInputRequiredShim, INPUT_REQUIRED_CAPABLE_METHODS, writeClientIdentity, installDiscoverHandler, readServerIdentity, Server, McpServer, EMPTY_OBJECT_JSON_SCHEMA, EMPTY_COMPLETION_RESULT;
|
|
36262
|
-
var
|
|
36263
|
-
"node_modules/@modelcontextprotocol/server/dist/mcp-
|
|
36264
|
-
|
|
36304
|
+
var init_mcp_DIH4cS6P = __esm({
|
|
36305
|
+
"node_modules/@modelcontextprotocol/server/dist/mcp-DIH4cS6P.mjs"() {
|
|
36306
|
+
init_src_Cqbh3MYc();
|
|
36265
36307
|
init_shimsNode();
|
|
36266
36308
|
COMPLETABLE_SYMBOL = /* @__PURE__ */ Symbol.for("mcp.completable");
|
|
36267
36309
|
MAX_TIMER_DELAY_MS = 2 ** 31 - 1;
|
|
@@ -36284,7 +36326,7 @@ var init_mcp_DYuW2ZSs = __esm({
|
|
|
36284
36326
|
_serverCapabilities;
|
|
36285
36327
|
/**
|
|
36286
36328
|
* The serving instance's identity, stamped onto the graceful-close
|
|
36287
|
-
* results' `_meta` (the spec's `
|
|
36329
|
+
* results' `_meta` (the spec's `SubscriptionsListenResultMetaObject` extends
|
|
36288
36330
|
* `ResultMetaObject`). Handed over together with the capabilities.
|
|
36289
36331
|
*/
|
|
36290
36332
|
_serverInfo;
|
|
@@ -36550,6 +36592,11 @@ var init_mcp_DYuW2ZSs = __esm({
|
|
|
36550
36592
|
if (modernProtocolVersions(this._supportedProtocolVersions).length > 0) this.setRequestHandler("server/discover", () => this._ondiscover());
|
|
36551
36593
|
if (this._capabilities.logging) this._registerLoggingHandler();
|
|
36552
36594
|
}
|
|
36595
|
+
/** Attaches to the given transport; rejects while this instance is connected to another one. */
|
|
36596
|
+
async connect(transport) {
|
|
36597
|
+
if (this.transport !== void 0) throw new SdkError(SdkErrorCode.AlreadyConnected, "Use a separate Server instance per connection: this instance is already connected to a transport. To connect it to a new transport, call close() first.");
|
|
36598
|
+
await super.connect(transport);
|
|
36599
|
+
}
|
|
36553
36600
|
/**
|
|
36554
36601
|
* Registers the built-in `logging/setLevel` request handler.
|
|
36555
36602
|
*
|
|
@@ -37105,16 +37152,12 @@ var init_mcp_DYuW2ZSs = __esm({
|
|
|
37105
37152
|
* The underlying {@linkcode Server} instance, useful for advanced operations like sending notifications.
|
|
37106
37153
|
*/
|
|
37107
37154
|
server;
|
|
37155
|
+
_maxToolInputElements;
|
|
37108
37156
|
_registeredResources = {};
|
|
37109
37157
|
_registeredResourceTemplates = {};
|
|
37110
37158
|
_registeredTools = {};
|
|
37111
37159
|
_registeredPrompts = {};
|
|
37112
|
-
/**
|
|
37113
|
-
* Per-tool JSON-converted `inputSchema`, memoized so the SEP-2243
|
|
37114
|
-
* registration-time scan and the pre-dispatch validation step share one
|
|
37115
|
-
* conversion instead of paying it twice per request under the
|
|
37116
|
-
* per-request-factory `createMcpHandler` model.
|
|
37117
|
-
*/
|
|
37160
|
+
/** Per-tool JSON-converted `inputSchema`, filled on first use by `toolInputSchemaJson()`. */
|
|
37118
37161
|
_toolInputSchemaJson = {};
|
|
37119
37162
|
/**
|
|
37120
37163
|
* The JSON-serialized `inputSchema` of a registered tool, or `undefined`
|
|
@@ -37139,6 +37182,7 @@ var init_mcp_DYuW2ZSs = __esm({
|
|
|
37139
37182
|
}
|
|
37140
37183
|
constructor(serverInfo, options) {
|
|
37141
37184
|
this.server = new Server(serverInfo, options);
|
|
37185
|
+
this._maxToolInputElements = resolveMaxToolInputElements(options?.maxToolInputElements);
|
|
37142
37186
|
if (options?.capabilities?.tools) this.setToolRequestHandlers();
|
|
37143
37187
|
if (options?.capabilities?.resources) this.setResourceRequestHandlers();
|
|
37144
37188
|
if (options?.capabilities?.prompts) this.setPromptRequestHandlers();
|
|
@@ -37211,7 +37255,7 @@ var init_mcp_DYuW2ZSs = __esm({
|
|
|
37211
37255
|
name,
|
|
37212
37256
|
title: tool.title,
|
|
37213
37257
|
description: tool.description,
|
|
37214
|
-
inputSchema: tool.inputSchema ?
|
|
37258
|
+
inputSchema: tool.inputSchema ? convertListedInputSchema(name, tool.inputSchema) : EMPTY_OBJECT_JSON_SCHEMA,
|
|
37215
37259
|
annotations: tool.annotations,
|
|
37216
37260
|
icons: tool.icons,
|
|
37217
37261
|
execution: tool.execution,
|
|
@@ -37256,6 +37300,7 @@ var init_mcp_DYuW2ZSs = __esm({
|
|
|
37256
37300
|
* Validates tool input arguments against the tool's input schema.
|
|
37257
37301
|
*/
|
|
37258
37302
|
async validateToolInput(tool, args, toolName) {
|
|
37303
|
+
if (this._maxToolInputElements !== void 0 && toolInputElementCount(args, this._maxToolInputElements) > this._maxToolInputElements) throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Invalid arguments for tool ${toolName}: arguments contain more than the maximum of ${this._maxToolInputElements} elements`);
|
|
37259
37304
|
if (!tool.inputSchema) return;
|
|
37260
37305
|
const parseResult = await validateStandardSchema(tool.inputSchema, args ?? {});
|
|
37261
37306
|
if (!parseResult.success) throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Input validation error: Invalid arguments for tool ${toolName}: ${parseResult.error}`);
|
|
@@ -37530,20 +37575,19 @@ var init_mcp_DYuW2ZSs = __esm({
|
|
|
37530
37575
|
}
|
|
37531
37576
|
_createRegisteredTool(name, title, description, inputSchema, outputSchema, annotations, icons, execution, scopeChallenge, _meta, handler) {
|
|
37532
37577
|
validateAndWarnToolName(name);
|
|
37533
|
-
if (inputSchema !== void 0) try {
|
|
37534
|
-
const json2 = standardSchemaToJsonSchema(inputSchema, "input");
|
|
37535
|
-
this._toolInputSchemaJson[name] = json2;
|
|
37536
|
-
const scan = scanXMcpHeaderDeclarations(json2);
|
|
37537
|
-
if (!scan.valid) console.warn(`[mcp-sdk] tool '${name}' carries an invalid x-mcp-header declaration and will be excluded by conforming Streamable HTTP clients: ${scan.reason}`);
|
|
37538
|
-
} catch {
|
|
37539
|
-
}
|
|
37540
37578
|
let currentHandler = handler;
|
|
37579
|
+
let outputSchemaJson;
|
|
37541
37580
|
const registeredTool = {
|
|
37542
37581
|
title,
|
|
37543
37582
|
description,
|
|
37544
37583
|
inputSchema,
|
|
37545
37584
|
outputSchema,
|
|
37546
|
-
outputSchemaJson
|
|
37585
|
+
get outputSchemaJson() {
|
|
37586
|
+
return outputSchemaJson ??= convertOutputSchemaJson(registeredTool.outputSchema);
|
|
37587
|
+
},
|
|
37588
|
+
set outputSchemaJson(value) {
|
|
37589
|
+
outputSchemaJson = value;
|
|
37590
|
+
},
|
|
37547
37591
|
annotations,
|
|
37548
37592
|
icons,
|
|
37549
37593
|
execution,
|
|
@@ -37987,8 +38031,8 @@ function toError(value) {
|
|
|
37987
38031
|
var swallowsErrorsAfterClose, StdioServerTransport, DISCARD_ANSWER_TIMEOUT_MS, StdioConnectionChannel;
|
|
37988
38032
|
var init_stdio = __esm({
|
|
37989
38033
|
"node_modules/@modelcontextprotocol/server/dist/stdio.mjs"() {
|
|
37990
|
-
|
|
37991
|
-
|
|
38034
|
+
init_mcp_DIH4cS6P();
|
|
38035
|
+
init_src_Cqbh3MYc();
|
|
37992
38036
|
init_shimsNode();
|
|
37993
38037
|
swallowsErrorsAfterClose = /* @__PURE__ */ Symbol("swallowsErrorsAfterClose");
|
|
37994
38038
|
StdioServerTransport = class {
|
|
@@ -38179,8 +38223,8 @@ var init_stdio = __esm({
|
|
|
38179
38223
|
var DEFAULT_MAX_REQUEST_BODY_SIZE;
|
|
38180
38224
|
var init_dist = __esm({
|
|
38181
38225
|
"node_modules/@modelcontextprotocol/server/dist/index.mjs"() {
|
|
38182
|
-
|
|
38183
|
-
|
|
38226
|
+
init_mcp_DIH4cS6P();
|
|
38227
|
+
init_src_Cqbh3MYc();
|
|
38184
38228
|
init_shimsNode();
|
|
38185
38229
|
DEFAULT_MAX_REQUEST_BODY_SIZE = 4 * 1024 * 1024;
|
|
38186
38230
|
}
|
|
@@ -58808,6 +58852,15 @@ ${JSON.stringify(preview, null, 2)}`,
|
|
|
58808
58852
|
};
|
|
58809
58853
|
const response = inputResponse(ctx.mcpReq.inputResponses, requestKey);
|
|
58810
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
|
+
}
|
|
58811
58864
|
if (response.kind === "missing") {
|
|
58812
58865
|
if (callerAcceptsFormElicitation(ctx) === false) {
|
|
58813
58866
|
return textResult({
|
|
@@ -58838,7 +58891,7 @@ ${JSON.stringify(preview, null, 2)}`,
|
|
|
58838
58891
|
note: "Nothing was changed because the confirmation was declined, cancelled, or left unchecked."
|
|
58839
58892
|
});
|
|
58840
58893
|
}
|
|
58841
|
-
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;
|
|
58842
58895
|
var init_confirmation = __esm({
|
|
58843
58896
|
"node_modules/@chrischall/mcp-utils/dist/server/confirmation.js"() {
|
|
58844
58897
|
init_dist();
|
|
@@ -58849,6 +58902,7 @@ var init_confirmation = __esm({
|
|
|
58849
58902
|
DEFAULT_REQUEST_KEY = "confirmation";
|
|
58850
58903
|
DEFAULT_CONFIRMATION_LABEL = "Confirm this action should proceed.";
|
|
58851
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";
|
|
58852
58906
|
STATE_PREFIX = "mcpu.confirm.v1.";
|
|
58853
58907
|
}
|
|
58854
58908
|
});
|
|
@@ -59002,7 +59056,7 @@ async function tokenConfirmation(action, fb) {
|
|
|
59002
59056
|
}
|
|
59003
59057
|
async function requireConfirmationWithFallback(ctx, options) {
|
|
59004
59058
|
const { tokenFallback, ...confirmation } = options;
|
|
59005
|
-
if (tokenFallback && callerAcceptsFormElicitation(ctx) === false) {
|
|
59059
|
+
if (tokenFallback && (options.elicitation === false || callerAcceptsFormElicitation(ctx) === false)) {
|
|
59006
59060
|
return tokenConfirmation(options.action, tokenFallback);
|
|
59007
59061
|
}
|
|
59008
59062
|
return requireConfirmation(ctx, confirmation);
|
|
@@ -59179,6 +59233,20 @@ function readConfirmMode(env = process.env) {
|
|
|
59179
59233
|
}
|
|
59180
59234
|
return "refuse";
|
|
59181
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
|
+
}
|
|
59182
59250
|
function readConfirmTtl(env) {
|
|
59183
59251
|
const raw = readEnvVar("MCP_CONFIRM_TTL_SECONDS", { env })?.trim();
|
|
59184
59252
|
if (!raw)
|
|
@@ -59231,10 +59299,13 @@ function confirmationFromEnv(options) {
|
|
|
59231
59299
|
const spent = callerSpent ?? spentTokenStoreFromEnv(env);
|
|
59232
59300
|
const mode = readConfirmMode(env);
|
|
59233
59301
|
const ttlSeconds = readConfirmTtl(env);
|
|
59302
|
+
const elicitationOff = readConfirmElicitation(env) === "off";
|
|
59234
59303
|
const bound = args === void 0 ? void 0 : boundArgs(args);
|
|
59235
|
-
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;
|
|
59236
59306
|
if (mode === "refuse" || ttlSeconds === void 0) {
|
|
59237
|
-
const
|
|
59307
|
+
const reason = mode === "refuse" ? REFUSE_HINT : BAD_TTL_HINT;
|
|
59308
|
+
const hint = elicitationOff ? `${ELICITATION_OFF_HINT} ${reason}` : reason;
|
|
59238
59309
|
return {
|
|
59239
59310
|
...confirmation,
|
|
59240
59311
|
unsupportedNote: confirmation.unsupportedNote ? `${confirmation.unsupportedNote} ${hint}` : hint
|
|
@@ -59260,7 +59331,7 @@ function confirmationFromEnv(options) {
|
|
|
59260
59331
|
}
|
|
59261
59332
|
};
|
|
59262
59333
|
}
|
|
59263
|
-
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;
|
|
59264
59335
|
var init_confirm_env = __esm({
|
|
59265
59336
|
"node_modules/@chrischall/mcp-utils/dist/server/confirm-env.js"() {
|
|
59266
59337
|
init_config();
|
|
@@ -59272,6 +59343,7 @@ var init_confirm_env = __esm({
|
|
|
59272
59343
|
fileStores = /* @__PURE__ */ new Map();
|
|
59273
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.)";
|
|
59274
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.";
|
|
59275
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.";
|
|
59276
59348
|
}
|
|
59277
59349
|
});
|
|
@@ -59368,7 +59440,10 @@ function surfaceToolHints(server) {
|
|
|
59368
59440
|
));
|
|
59369
59441
|
}
|
|
59370
59442
|
async function createMcpServer(opts) {
|
|
59371
|
-
const server = new McpServer({ name: opts.name, version: opts.version }, {
|
|
59443
|
+
const server = new McpServer({ name: opts.name, version: opts.version }, {
|
|
59444
|
+
supportedProtocolVersions: [...SERVER_PROTOCOL_VERSIONS],
|
|
59445
|
+
...opts.maxToolInputElements !== void 0 ? { maxToolInputElements: opts.maxToolInputElements } : {}
|
|
59446
|
+
});
|
|
59372
59447
|
if (opts.surfaceHints !== false)
|
|
59373
59448
|
surfaceToolHints(server);
|
|
59374
59449
|
if (opts.banner !== void 0) {
|
|
@@ -59770,6 +59845,21 @@ var init_fs = __esm({
|
|
|
59770
59845
|
}
|
|
59771
59846
|
});
|
|
59772
59847
|
|
|
59848
|
+
// node_modules/@chrischall/mcp-utils/dist/internal/headers.js
|
|
59849
|
+
function responseHeader(res, name) {
|
|
59850
|
+
return getHeader(res?.headers, name);
|
|
59851
|
+
}
|
|
59852
|
+
function getHeader(headers, name) {
|
|
59853
|
+
if (!headers || typeof headers.get !== "function")
|
|
59854
|
+
return null;
|
|
59855
|
+
const value = headers.get.call(headers, name);
|
|
59856
|
+
return typeof value === "string" ? value : null;
|
|
59857
|
+
}
|
|
59858
|
+
var init_headers = __esm({
|
|
59859
|
+
"node_modules/@chrischall/mcp-utils/dist/internal/headers.js"() {
|
|
59860
|
+
}
|
|
59861
|
+
});
|
|
59862
|
+
|
|
59773
59863
|
// node_modules/@chrischall/mcp-utils/dist/internal/ascii.js
|
|
59774
59864
|
var init_ascii = __esm({
|
|
59775
59865
|
"node_modules/@chrischall/mcp-utils/dist/internal/ascii.js"() {
|
|
@@ -60020,7 +60110,7 @@ function createApiClient(opts) {
|
|
|
60020
60110
|
if (retryStatuses.includes(res.status) && attempt < retry.count) {
|
|
60021
60111
|
discard(current);
|
|
60022
60112
|
attempt += 1;
|
|
60023
|
-
const delay = retry.honorRetryAfter ? parseRetryAfterMs(res
|
|
60113
|
+
const delay = retry.honorRetryAfter ? parseRetryAfterMs(responseHeader(res, "retry-after"), {
|
|
60024
60114
|
defaultMs: retry.delayMs,
|
|
60025
60115
|
capMs: retry.maxRetryAfterMs ?? 3e4
|
|
60026
60116
|
}) : retry.delayMs;
|
|
@@ -60033,7 +60123,7 @@ function createApiClient(opts) {
|
|
|
60033
60123
|
async function unauthorizedOrEdge(attempt, method, path) {
|
|
60034
60124
|
const res = attempt.res;
|
|
60035
60125
|
let text = "";
|
|
60036
|
-
if (/json/i.test(res
|
|
60126
|
+
if (/json/i.test(responseHeader(res, "content-type") ?? "")) {
|
|
60037
60127
|
discard(attempt);
|
|
60038
60128
|
} else {
|
|
60039
60129
|
text = await readBody(attempt, (r) => r.text()).catch(() => "");
|
|
@@ -60045,14 +60135,14 @@ function createApiClient(opts) {
|
|
|
60045
60135
|
}
|
|
60046
60136
|
async function rateLimitedError(attempt, method, path) {
|
|
60047
60137
|
const res = attempt.res;
|
|
60048
|
-
const retryAfter = res
|
|
60138
|
+
const retryAfter = responseHeader(res, "retry-after");
|
|
60049
60139
|
const retryAfterMs = retryAfterToMs(retryAfter);
|
|
60050
60140
|
if (!opts.onRateLimited) {
|
|
60051
60141
|
discard(attempt);
|
|
60052
60142
|
return new RateLimitedError(service, retryAfterMs);
|
|
60053
60143
|
}
|
|
60054
60144
|
let text = "";
|
|
60055
|
-
if (/json/i.test(res
|
|
60145
|
+
if (/json/i.test(responseHeader(res, "content-type") ?? "")) {
|
|
60056
60146
|
discard(attempt);
|
|
60057
60147
|
} else {
|
|
60058
60148
|
text = await readBody(attempt, (r) => r.text()).catch(() => "");
|
|
@@ -60112,7 +60202,7 @@ function createApiClient(opts) {
|
|
|
60112
60202
|
const bytes = new Uint8Array(await readBody(attempt, (r) => r.arrayBuffer()));
|
|
60113
60203
|
return {
|
|
60114
60204
|
status: res.status,
|
|
60115
|
-
contentType: res
|
|
60205
|
+
contentType: responseHeader(res, "content-type"),
|
|
60116
60206
|
headers: res.headers,
|
|
60117
60207
|
bytes
|
|
60118
60208
|
};
|
|
@@ -60145,6 +60235,7 @@ function formatApiError(status, method, path, errorText, opts = {}) {
|
|
|
60145
60235
|
var DEFAULT_RETRY, defaultSleep, UnauthorizedError, RateLimitedError, RequestTimeoutError, ApiError, EdgeBlockedError, EDGE_BLOCK_SCAN_MAX, EDGE_BLOCK_MARKERS;
|
|
60146
60236
|
var init_http = __esm({
|
|
60147
60237
|
"node_modules/@chrischall/mcp-utils/dist/http/index.js"() {
|
|
60238
|
+
init_headers();
|
|
60148
60239
|
init_cancel();
|
|
60149
60240
|
init_errors();
|
|
60150
60241
|
init_scrape();
|
|
@@ -60320,6 +60411,7 @@ var init_es256 = __esm({
|
|
|
60320
60411
|
// node_modules/@chrischall/mcp-utils/dist/auth/index.js
|
|
60321
60412
|
var init_auth = __esm({
|
|
60322
60413
|
"node_modules/@chrischall/mcp-utils/dist/auth/index.js"() {
|
|
60414
|
+
init_headers();
|
|
60323
60415
|
init_config();
|
|
60324
60416
|
init_errors();
|
|
60325
60417
|
init_http();
|
|
@@ -60691,7 +60783,7 @@ async function loadStdioDotenv() {
|
|
|
60691
60783
|
}
|
|
60692
60784
|
|
|
60693
60785
|
// src/version.ts
|
|
60694
|
-
var VERSION = "2.3.
|
|
60786
|
+
var VERSION = "2.3.3";
|
|
60695
60787
|
|
|
60696
60788
|
// src/errors.ts
|
|
60697
60789
|
init_dist2();
|
|
@@ -65725,7 +65817,7 @@ await runMcp({
|
|
|
65725
65817
|
});
|
|
65726
65818
|
/*! Bundled license information:
|
|
65727
65819
|
|
|
65728
|
-
@modelcontextprotocol/server/dist/src-
|
|
65820
|
+
@modelcontextprotocol/server/dist/src-Cqbh3MYc.mjs:
|
|
65729
65821
|
(*!
|
|
65730
65822
|
* content-type
|
|
65731
65823
|
* Copyright(c) 2015 Douglas Christopher Wilson
|
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,13 +46,13 @@
|
|
|
46
46
|
"typecheck": "tsc -p tsconfig.test.json"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@chrischall/mcp-utils": "^2.
|
|
50
|
-
"@modelcontextprotocol/server": "^2.
|
|
49
|
+
"@chrischall/mcp-utils": "^2.15.0",
|
|
50
|
+
"@modelcontextprotocol/server": "^2.3.0",
|
|
51
51
|
"dotenv": "^18.0.2",
|
|
52
52
|
"zod": "^4.6.5"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"@modelcontextprotocol/client": "^2.
|
|
55
|
+
"@modelcontextprotocol/client": "^2.3.0",
|
|
56
56
|
"@types/node": "^26.0.0",
|
|
57
57
|
"@vitest/coverage-v8": "^5.0.0",
|
|
58
58
|
"esbuild": "^0.28.0",
|
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.
|