@chrischall/gemini-mcp 2.0.0 → 2.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.
@@ -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.0.0"
10
+ "version": "2.1.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": "2.0.0",
18
+ "version": "2.1.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": "2.0.0",
4
+ "version": "2.1.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/dist/bundle.js CHANGED
@@ -26527,6 +26527,25 @@ function isSpecRequestMethod(method) {
26527
26527
  function isSpecNotificationMethod(method) {
26528
26528
  return ALL_CODECS.some((codec2) => codec2.hasNotificationMethod(method));
26529
26529
  }
26530
+ function isPlainObject$3(value) {
26531
+ return value !== null && typeof value === "object" && !Array.isArray(value);
26532
+ }
26533
+ function requestMetaOf(params) {
26534
+ if (!isPlainObject$3(params)) return void 0;
26535
+ const meta3 = params["_meta"];
26536
+ return isPlainObject$3(meta3) ? meta3 : void 0;
26537
+ }
26538
+ function hasEnvelopeClaim(params) {
26539
+ const meta3 = requestMetaOf(params);
26540
+ return meta3 !== void 0 && PROTOCOL_VERSION_META_KEY in meta3;
26541
+ }
26542
+ function envelopeClaimVersion(params) {
26543
+ const value = requestMetaOf(params)?.[PROTOCOL_VERSION_META_KEY];
26544
+ return typeof value === "string" ? value : void 0;
26545
+ }
26546
+ function validateEnvelopeMeta(meta3) {
26547
+ return codecForVersion(MODERN_WIRE_REVISION).validateEnvelopeMeta(meta3);
26548
+ }
26530
26549
  function assertCompleteRequestPrompt(request) {
26531
26550
  if (request.params.ref.type !== "ref/prompt") throw new TypeError(`Expected CompleteRequestPrompt, but got ${request.params.ref.type}`);
26532
26551
  }
@@ -26583,6 +26602,45 @@ function scanXMcpHeaderDeclarations(inputSchema) {
26583
26602
  function pathName(path) {
26584
26603
  return path.length === 0 ? "<root>" : path.join(".");
26585
26604
  }
26605
+ function rejection(rung, cell, httpStatus, error62, settled) {
26606
+ return {
26607
+ kind: "reject",
26608
+ rung,
26609
+ cell,
26610
+ httpStatus,
26611
+ code: error62.code,
26612
+ message: error62.message,
26613
+ ...error62.data !== void 0 && { data: error62.data },
26614
+ settled
26615
+ };
26616
+ }
26617
+ function carriesValidModernEnvelopeClaim(params) {
26618
+ if (!hasEnvelopeClaim(params)) return false;
26619
+ const claimedVersion = envelopeClaimVersion(params);
26620
+ if (claimedVersion === void 0 || !isModernProtocolVersion(claimedVersion)) return false;
26621
+ const meta3 = requestMetaOf(params);
26622
+ return meta3 !== void 0 && validateEnvelopeMeta(meta3).length === 0;
26623
+ }
26624
+ function modernOnlyStrictRejection(route, supportedVersions) {
26625
+ switch (route.reason) {
26626
+ case "http-method":
26627
+ return rejection("http-method", "modern-only-method-not-allowed", 405, new ProtocolError(-32e3, "Method not allowed."), true);
26628
+ case "batch":
26629
+ return rejection("jsonrpc-shape", "modern-only-batch-not-supported", 400, new ProtocolError(ProtocolErrorCode.InvalidRequest, "Bad Request: JSON-RPC batches are not supported by this endpoint"), true);
26630
+ case "response":
26631
+ return rejection("jsonrpc-shape", "modern-only-response-post", 400, new ProtocolError(ProtocolErrorCode.InvalidRequest, "Bad Request: JSON-RPC responses cannot be posted to this endpoint"), true);
26632
+ case "notification":
26633
+ return;
26634
+ case "initialize":
26635
+ case "no-claim": {
26636
+ const requested = route.requestedVersion;
26637
+ return rejection("era-classification", "modern-only-missing-envelope", 400, requested === void 0 ? new ProtocolError(ProtocolErrorCode.UnsupportedProtocolVersion, "Unsupported protocol version: the request did not name a protocol version", { supported: [...supportedVersions] }) : new UnsupportedProtocolVersionError({
26638
+ supported: [...supportedVersions],
26639
+ requested
26640
+ }), true);
26641
+ }
26642
+ }
26643
+ }
26586
26644
  function parseSchema(schema, data) {
26587
26645
  return z2.safeParse(schema, data);
26588
26646
  }
@@ -26894,6 +26952,9 @@ function withRequestStateValue(ctx, value) {
26894
26952
  }
26895
26953
  };
26896
26954
  }
26955
+ function setNegotiatedProtocolVersion(instance, version2) {
26956
+ writeNegotiatedProtocolVersion(instance, version2);
26957
+ }
26897
26958
  function isPlainObject$1(value) {
26898
26959
  return value !== null && typeof value === "object" && !Array.isArray(value);
26899
26960
  }
@@ -27007,7 +27068,7 @@ function normalizeRawShapeSchema(schema) {
27007
27068
  if (!isStandardSchema(schema)) throw new TypeError("inputSchema/outputSchema/argsSchema must be a Standard Schema (e.g. z.object({...})) or a raw Zod shape ({ field: z.string() }).");
27008
27069
  return schema;
27009
27070
  }
27010
- var z2, BRANDS, OAuthError, SdkErrorCode, SdkError, SdkHttpError, FIRST_MODERN_PROTOCOL_VERSION, 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;
27071
+ 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;
27011
27072
  var init_src_CX2iR2pK = __esm({
27012
27073
  "node_modules/@modelcontextprotocol/server/dist/src-CX2iR2pK.mjs"() {
27013
27074
  init_chunk_Br0eD_fh();
@@ -27126,6 +27187,7 @@ var init_src_CX2iR2pK = __esm({
27126
27187
  }
27127
27188
  };
27128
27189
  FIRST_MODERN_PROTOCOL_VERSION = "2026-07-28";
27190
+ SUPPORTED_MODERN_PROTOCOL_VERSIONS = [FIRST_MODERN_PROTOCOL_VERSION];
27129
27191
  TOOL_RESULT_FOREIGN_FAMILY_KEYS = [
27130
27192
  "task",
27131
27193
  "inputRequests",
@@ -35930,6 +35992,58 @@ function isCompletable(schema) {
35930
35992
  function getCompleter(schema) {
35931
35993
  return schema[COMPLETABLE_SYMBOL]?.complete;
35932
35994
  }
35995
+ function listenFilterAccepts(filter, event) {
35996
+ switch (event.kind) {
35997
+ case "tools_list_changed":
35998
+ return filter.toolsListChanged === true;
35999
+ case "prompts_list_changed":
36000
+ return filter.promptsListChanged === true;
36001
+ case "resources_list_changed":
36002
+ return filter.resourcesListChanged === true;
36003
+ case "resource_updated":
36004
+ return filter.resourceSubscriptions !== void 0 && filter.resourceSubscriptions.includes(event.uri);
36005
+ }
36006
+ }
36007
+ function honoredSubset(requested, capabilities) {
36008
+ const honored = {};
36009
+ const allow = (bit) => capabilities === void 0 || bit === true;
36010
+ if (requested.toolsListChanged === true && allow(capabilities?.tools?.listChanged)) honored.toolsListChanged = true;
36011
+ if (requested.promptsListChanged === true && allow(capabilities?.prompts?.listChanged)) honored.promptsListChanged = true;
36012
+ if (requested.resourcesListChanged === true && allow(capabilities?.resources?.listChanged)) honored.resourcesListChanged = true;
36013
+ if (requested.resourceSubscriptions !== void 0 && requested.resourceSubscriptions.length > 0 && allow(capabilities?.resources?.subscribe)) honored.resourceSubscriptions = [...requested.resourceSubscriptions];
36014
+ return honored;
36015
+ }
36016
+ function stampSubscriptionId(notification, subscriptionId) {
36017
+ return {
36018
+ method: notification.method,
36019
+ params: {
36020
+ ...notification.params,
36021
+ _meta: {
36022
+ ...notification.params?._meta,
36023
+ [SUBSCRIPTION_ID_META_KEY]: subscriptionId
36024
+ }
36025
+ }
36026
+ };
36027
+ }
36028
+ function parseListenFilter(message) {
36029
+ const outcome = codecForVersion(MODERN_WIRE_REVISION).validateRequest("subscriptions/listen", message);
36030
+ return outcome.ok ? outcome.value.params?.notifications : void 0;
36031
+ }
36032
+ function notificationToServerEvent(method, uri) {
36033
+ switch (method) {
36034
+ case "notifications/tools/list_changed":
36035
+ return { kind: "tools_list_changed" };
36036
+ case "notifications/prompts/list_changed":
36037
+ return { kind: "prompts_list_changed" };
36038
+ case "notifications/resources/list_changed":
36039
+ return { kind: "resources_list_changed" };
36040
+ default:
36041
+ return {
36042
+ kind: "resource_updated",
36043
+ uri: uri ?? ""
36044
+ };
36045
+ }
36046
+ }
35933
36047
  function resolveLegacyShimOptions(options) {
35934
36048
  if (options?.maxRounds !== void 0 && (!Number.isInteger(options.maxRounds) || options.maxRounds < 1)) throw new RangeError(`inputRequired.maxRounds must be a positive integer (got ${options.maxRounds})`);
35935
36049
  if (options?.roundTimeoutMs !== void 0 && (!Number.isFinite(options.roundTimeoutMs) || options.roundTimeoutMs <= 0)) throw new RangeError(`inputRequired.roundTimeoutMs must be a positive number (got ${options.roundTimeoutMs})`);
@@ -35969,6 +36083,12 @@ function legacyShimFailure(method, message) {
35969
36083
  };
35970
36084
  throw new ProtocolError(ProtocolErrorCode.InternalError, message);
35971
36085
  }
36086
+ function installModernOnlyHandlers(server, servedModernVersions) {
36087
+ installDiscoverHandler(server, servedModernVersions);
36088
+ }
36089
+ function serverIdentityOf(server) {
36090
+ return readServerIdentity(server);
36091
+ }
35972
36092
  function discoverAdvertisedCapabilities(capabilities) {
35973
36093
  return { ...capabilities };
35974
36094
  }
@@ -36021,13 +36141,145 @@ function unwrapOptionalSchema(schema) {
36021
36141
  if (!isOptionalSchema(schema)) return schema;
36022
36142
  return schema.def?.innerType ?? schema;
36023
36143
  }
36024
- var COMPLETABLE_SYMBOL, MAX_TIMER_DELAY_MS, 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;
36144
+ 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;
36025
36145
  var init_mcp_DXXb3Vv3 = __esm({
36026
36146
  "node_modules/@modelcontextprotocol/server/dist/mcp-DXXb3Vv3.mjs"() {
36027
36147
  init_src_CX2iR2pK();
36028
36148
  init_shimsNode();
36029
36149
  COMPLETABLE_SYMBOL = /* @__PURE__ */ Symbol.for("mcp.completable");
36030
36150
  MAX_TIMER_DELAY_MS = 2 ** 31 - 1;
36151
+ DEFAULT_MAX_SUBSCRIPTIONS = 1024;
36152
+ CHANGE_NOTIFICATION_METHODS = /* @__PURE__ */ new Set([
36153
+ "notifications/tools/list_changed",
36154
+ "notifications/prompts/list_changed",
36155
+ "notifications/resources/list_changed",
36156
+ "notifications/resources/updated"
36157
+ ]);
36158
+ StdioListenRouter = class {
36159
+ /** Active subscriptions, keyed by the listen request's JSON-RPC id verbatim. */
36160
+ _subs = /* @__PURE__ */ new Map();
36161
+ /**
36162
+ * The serving instance's declared capabilities. Filled in by the entry
36163
+ * once the modern instance is constructed (the router is created before
36164
+ * the instance exists), so the acknowledged filter is narrowed against
36165
+ * what the server can actually deliver.
36166
+ */
36167
+ _serverCapabilities;
36168
+ /**
36169
+ * The serving instance's identity, stamped onto the graceful-close
36170
+ * results' `_meta` (the spec's `SubscriptionsListenResultMeta` extends
36171
+ * `ResultMetaObject`). Handed over together with the capabilities.
36172
+ */
36173
+ _serverInfo;
36174
+ constructor(_maxSubscriptions = DEFAULT_MAX_SUBSCRIPTIONS, serverCapabilities, serverInfo) {
36175
+ this._maxSubscriptions = _maxSubscriptions;
36176
+ this._serverCapabilities = serverCapabilities;
36177
+ this._serverInfo = serverInfo;
36178
+ }
36179
+ /**
36180
+ * Record the serving instance's declared capabilities and identity once
36181
+ * it has been constructed. Called by `serveStdio`'s connect path;
36182
+ * subsequent `serve()` calls narrow the honored filter against the
36183
+ * capabilities, and `teardownAll()` stamps the identity.
36184
+ */
36185
+ setServerCapabilities(capabilities, serverInfo) {
36186
+ this._serverCapabilities = capabilities;
36187
+ if (serverInfo !== void 0) this._serverInfo = serverInfo;
36188
+ }
36189
+ /** Whether `id` is an active listen subscription on this connection. */
36190
+ has(id) {
36191
+ return this._subs.has(id);
36192
+ }
36193
+ /**
36194
+ * Serve one inbound `subscriptions/listen` request: registers the
36195
+ * subscription and returns the stamped acknowledged notification (or, on
36196
+ * capacity / params rejection, the in-band JSON-RPC error response).
36197
+ *
36198
+ * @throws when called before {@linkcode setServerCapabilities} (or the
36199
+ * constructor) has supplied the serving instance's capabilities. Honoring a
36200
+ * filter without knowing the server's advertised capabilities would fail
36201
+ * open (deliver unadvertised types); the entry guarantees capabilities are
36202
+ * set before any listen request is routed here.
36203
+ */
36204
+ serve(message) {
36205
+ if (this._serverCapabilities === void 0) throw new Error("StdioListenRouter.serve() called before setServerCapabilities(); refusing to honor a filter without capabilities");
36206
+ if (this._subs.size >= this._maxSubscriptions) return {
36207
+ jsonrpc: "2.0",
36208
+ id: message.id,
36209
+ error: {
36210
+ code: -32603,
36211
+ message: "Subscription limit reached"
36212
+ }
36213
+ };
36214
+ const filter = parseListenFilter(message);
36215
+ if (filter === void 0) return {
36216
+ jsonrpc: "2.0",
36217
+ id: message.id,
36218
+ error: {
36219
+ code: -32602,
36220
+ message: "Invalid params: 'notifications' is required and must be a valid SubscriptionFilter"
36221
+ }
36222
+ };
36223
+ const honored = honoredSubset(filter, this._serverCapabilities);
36224
+ this._subs.set(message.id, honored);
36225
+ return stampSubscriptionId({
36226
+ method: "notifications/subscriptions/acknowledged",
36227
+ params: { notifications: honored }
36228
+ }, message.id);
36229
+ }
36230
+ /**
36231
+ * Tear down one subscription (inbound `notifications/cancelled`). Returns
36232
+ * `true` when a subscription was removed. After this call NOTHING further
36233
+ * is delivered for that subscription id (the post-cancel hardening).
36234
+ */
36235
+ cancel(id) {
36236
+ return this._subs.delete(id);
36237
+ }
36238
+ /**
36239
+ * Route an outbound notification through the active subscriptions.
36240
+ *
36241
+ * - For a subscription-gated change notification, returns one stamped copy
36242
+ * per subscription that opted in to it (an empty array means it is
36243
+ * dropped — the modern era never delivers an un-requested change type).
36244
+ * - For any other outbound message, returns `'passthrough'` (the entry
36245
+ * forwards it as-is).
36246
+ */
36247
+ routeOutbound(message) {
36248
+ if (!CHANGE_NOTIFICATION_METHODS.has(message.method)) return "passthrough";
36249
+ const uriParam = message.params?.["uri"];
36250
+ const uri = typeof uriParam === "string" ? uriParam : void 0;
36251
+ const event = notificationToServerEvent(message.method, uri);
36252
+ const out = [];
36253
+ for (const [subscriptionId, filter] of this._subs) if (listenFilterAccepts(filter, event)) out.push(stampSubscriptionId({
36254
+ method: message.method,
36255
+ params: message.params ?? {}
36256
+ }, subscriptionId));
36257
+ return out;
36258
+ }
36259
+ /**
36260
+ * Server-side graceful teardown of every active subscription: returns the
36261
+ * empty `subscriptions/listen` JSON-RPC result for each subscription id —
36262
+ * the spec's graceful-close signal, `_meta` carrying the subscription id
36263
+ * and the serving instance's identity — for the entry to emit before
36264
+ * closing the wire. Clears the set so nothing further is delivered.
36265
+ */
36266
+ teardownAll() {
36267
+ const out = [];
36268
+ for (const id of this._subs.keys()) out.push({
36269
+ jsonrpc: "2.0",
36270
+ id,
36271
+ result: {
36272
+ resultType: "complete",
36273
+ _meta: {
36274
+ [SUBSCRIPTION_ID_META_KEY]: id,
36275
+ ...this._serverInfo !== void 0 && { [SERVER_INFO_META_KEY]: this._serverInfo }
36276
+ }
36277
+ }
36278
+ });
36279
+ this._subs.clear();
36280
+ return out;
36281
+ }
36282
+ };
36031
36283
  DEFAULT_LEGACY_SHIM_MAX_ROUNDS = 8;
36032
36284
  DEFAULT_LEGACY_SHIM_ROUND_TIMEOUT_MS = 6e5;
36033
36285
  LegacyInputRequiredShim = class {
@@ -37259,7 +37511,319 @@ var init_mcp_DXXb3Vv3 = __esm({
37259
37511
  });
37260
37512
 
37261
37513
  // node_modules/@modelcontextprotocol/server/dist/stdio.mjs
37262
- var StdioServerTransport;
37514
+ function classifyOpeningMessage(message) {
37515
+ const params = message.params;
37516
+ if (message.method === "initialize" && !carriesValidModernEnvelopeClaim(params)) {
37517
+ const requestedVersion = params !== null && typeof params === "object" && typeof params.protocolVersion === "string" ? params.protocolVersion : void 0;
37518
+ return {
37519
+ kind: "legacy",
37520
+ reason: "initialize",
37521
+ ...requestedVersion !== void 0 && { requestedVersion }
37522
+ };
37523
+ }
37524
+ if (!hasEnvelopeClaim(params)) return {
37525
+ kind: "legacy",
37526
+ reason: "no-claim"
37527
+ };
37528
+ const meta3 = requestMetaOf(params);
37529
+ const firstIssue = (meta3 === void 0 ? [] : validateEnvelopeMeta(meta3))[0];
37530
+ if (firstIssue !== void 0) return {
37531
+ kind: "invalid-envelope",
37532
+ issue: firstIssue
37533
+ };
37534
+ const claimedVersion = envelopeClaimVersion(params);
37535
+ if (claimedVersion === void 0 || !SUPPORTED_MODERN_PROTOCOL_VERSIONS.includes(claimedVersion)) return {
37536
+ kind: "unsupported-revision",
37537
+ requested: claimedVersion ?? "unknown"
37538
+ };
37539
+ return {
37540
+ kind: "modern",
37541
+ revision: claimedVersion,
37542
+ classification: {
37543
+ era: "modern",
37544
+ revision: claimedVersion
37545
+ }
37546
+ };
37547
+ }
37548
+ function serveStdio(factory, options = {}) {
37549
+ const legacyMode = options.legacy ?? "serve";
37550
+ const wire = options.transport ?? new StdioServerTransport();
37551
+ let state = { phase: "opening" };
37552
+ let discarding;
37553
+ let closing = false;
37554
+ const isTornDown = () => closing || state.phase === "closed";
37555
+ const reportError = (error62) => {
37556
+ try {
37557
+ options.onerror?.(error62);
37558
+ } catch {
37559
+ }
37560
+ };
37561
+ const writeErrorResponse = (id, code, message, data) => wire.send({
37562
+ jsonrpc: "2.0",
37563
+ id,
37564
+ error: {
37565
+ code,
37566
+ message,
37567
+ ...data !== void 0 && { data }
37568
+ }
37569
+ }).catch((error62) => reportError(toError(error62)));
37570
+ const listenRouter = new StdioListenRouter(options.maxSubscriptions ?? DEFAULT_MAX_SUBSCRIPTIONS);
37571
+ const modernOutboundIntercept = (message) => {
37572
+ if (!isJSONRPCNotification(message)) return void 0;
37573
+ const routed = listenRouter.routeOutbound(message);
37574
+ if (routed === "passthrough") return void 0;
37575
+ for (const stamped of routed) wire.send({
37576
+ jsonrpc: "2.0",
37577
+ ...stamped
37578
+ }).catch((error62) => reportError(toError(error62)));
37579
+ return "handled";
37580
+ };
37581
+ const tryServeListen = async (message) => {
37582
+ if (isJSONRPCRequest(message) && message.method === "subscriptions/listen") {
37583
+ const meta3 = requestMetaOf(message.params);
37584
+ const issue2 = hasEnvelopeClaim(message.params) ? (meta3 === void 0 ? [] : validateEnvelopeMeta(meta3))[0] : {
37585
+ key: "_meta",
37586
+ problem: "the per-request envelope is required on protocol revision 2026-07-28"
37587
+ };
37588
+ const claimedVersion = envelopeClaimVersion(message.params);
37589
+ let reply;
37590
+ if (issue2 !== void 0) reply = {
37591
+ jsonrpc: "2.0",
37592
+ id: message.id,
37593
+ error: {
37594
+ code: -32602,
37595
+ message: `Invalid _meta envelope: ${issue2.key}: ${issue2.problem}`
37596
+ }
37597
+ };
37598
+ else if (claimedVersion === void 0 || !SUPPORTED_MODERN_PROTOCOL_VERSIONS.includes(claimedVersion)) {
37599
+ const error62 = new UnsupportedProtocolVersionError({
37600
+ supported: [...SUPPORTED_MODERN_PROTOCOL_VERSIONS],
37601
+ requested: claimedVersion ?? "unknown"
37602
+ });
37603
+ reply = {
37604
+ jsonrpc: "2.0",
37605
+ id: message.id,
37606
+ error: {
37607
+ code: error62.code,
37608
+ message: error62.message,
37609
+ data: error62.data
37610
+ }
37611
+ };
37612
+ } else reply = listenRouter.serve(message);
37613
+ await wire.send("error" in reply ? reply : {
37614
+ jsonrpc: "2.0",
37615
+ method: reply.method,
37616
+ params: reply.params
37617
+ }).catch((error62) => reportError(toError(error62)));
37618
+ return true;
37619
+ }
37620
+ if (isJSONRPCNotification(message) && message.method === "notifications/cancelled") {
37621
+ const cancelledId = message.params?.requestId;
37622
+ if (cancelledId !== void 0 && listenRouter.cancel(cancelledId)) return true;
37623
+ }
37624
+ return false;
37625
+ };
37626
+ const answerLegacyRejection = (request, reason, requestedVersion) => {
37627
+ const rejection2 = modernOnlyStrictRejection({
37628
+ kind: "legacy",
37629
+ reason,
37630
+ ...requestedVersion !== void 0 && { requestedVersion }
37631
+ }, SUPPORTED_MODERN_PROTOCOL_VERSIONS);
37632
+ if (rejection2 === void 0) return Promise.resolve();
37633
+ reportError(/* @__PURE__ */ new Error(`Rejected 2025-era request on a modern-only stdio connection (${rejection2.cell}): ${rejection2.message}`));
37634
+ return writeErrorResponse(request.id, rejection2.code, rejection2.message, rejection2.data);
37635
+ };
37636
+ const onInstanceClosed = (channel) => {
37637
+ if (closing || channel === discarding) return;
37638
+ closeAll();
37639
+ };
37640
+ const connectInstance = async (era, revision) => {
37641
+ const product = await factory({ era });
37642
+ const server = product instanceof McpServer ? product.server : product;
37643
+ if (era === "modern") {
37644
+ setNegotiatedProtocolVersion(server, revision);
37645
+ installModernOnlyHandlers(server, SUPPORTED_MODERN_PROTOCOL_VERSIONS);
37646
+ listenRouter.setServerCapabilities(server.getCapabilities(), serverIdentityOf(server));
37647
+ }
37648
+ const channel = new StdioConnectionChannel(wire, () => onInstanceClosed(channel), era === "modern" ? modernOutboundIntercept : void 0);
37649
+ await product.connect(channel);
37650
+ return {
37651
+ product,
37652
+ channel
37653
+ };
37654
+ };
37655
+ const disposeLateInstance = (instance) => instance.product.close().catch((error62) => reportError(toError(error62)));
37656
+ const discardProbeInstance = async (instance) => {
37657
+ discarding = instance.channel;
37658
+ try {
37659
+ if (!await instance.channel.whenRequestsAnswered(DISCARD_ANSWER_TIMEOUT_MS)) reportError(/* @__PURE__ */ new Error(`Discarded the probe instance with requests still unanswered after ${DISCARD_ANSWER_TIMEOUT_MS}ms; continuing with the fallback`));
37660
+ await instance.product.close();
37661
+ } catch (error62) {
37662
+ reportError(toError(error62));
37663
+ } finally {
37664
+ discarding = void 0;
37665
+ }
37666
+ };
37667
+ const processMessage = async (message) => {
37668
+ if (state.phase === "closed") return;
37669
+ if (state.phase === "pinned") {
37670
+ if (state.era === "modern" && isJSONRPCRequest(message) && message.method === "initialize" && !carriesValidModernEnvelopeClaim(message.params)) {
37671
+ await answerLegacyRejection(message, "initialize", message.params !== null && typeof message.params === "object" && typeof message.params.protocolVersion === "string" ? message.params.protocolVersion : void 0);
37672
+ return;
37673
+ }
37674
+ if (state.era === "modern" && await tryServeListen(message)) return;
37675
+ state.instance.channel.deliver(message);
37676
+ return;
37677
+ }
37678
+ if (!isJSONRPCRequest(message) && !isJSONRPCNotification(message)) {
37679
+ reportError(/* @__PURE__ */ new Error("Discarded a JSON-RPC response received before the connection negotiated an era"));
37680
+ return;
37681
+ }
37682
+ const opening = classifyOpeningMessage(message);
37683
+ switch (opening.kind) {
37684
+ case "invalid-envelope": {
37685
+ const detail = `Invalid _meta envelope for protocol revision 2026-07-28: ${opening.issue.key}: ${opening.issue.problem}`;
37686
+ if (isJSONRPCRequest(message)) await writeErrorResponse(message.id, ProtocolErrorCode.InvalidParams, detail, { envelope: opening.issue });
37687
+ else reportError(/* @__PURE__ */ new Error(`Discarded a notification with a malformed envelope: ${detail}`));
37688
+ return;
37689
+ }
37690
+ case "unsupported-revision":
37691
+ if (isJSONRPCRequest(message)) {
37692
+ const error62 = new UnsupportedProtocolVersionError({
37693
+ supported: [...SUPPORTED_MODERN_PROTOCOL_VERSIONS],
37694
+ requested: opening.requested
37695
+ });
37696
+ reportError(error62);
37697
+ await writeErrorResponse(message.id, error62.code, error62.message, error62.data);
37698
+ } else reportError(/* @__PURE__ */ new Error(`Discarded a notification claiming unsupported protocol revision ${opening.requested}`));
37699
+ return;
37700
+ case "modern":
37701
+ if (isJSONRPCRequest(message) && message.method === "server/discover") {
37702
+ if (state.phase === "probe") {
37703
+ state.instance.channel.deliver(message, { classification: opening.classification });
37704
+ return;
37705
+ }
37706
+ const instance = await connectInstance("modern", opening.revision);
37707
+ if (isTornDown()) {
37708
+ await disposeLateInstance(instance);
37709
+ return;
37710
+ }
37711
+ state = {
37712
+ phase: "probe",
37713
+ instance
37714
+ };
37715
+ instance.channel.deliver(message, { classification: opening.classification });
37716
+ return;
37717
+ }
37718
+ if (state.phase === "probe") {
37719
+ if (isJSONRPCNotification(message)) {
37720
+ state.instance.channel.deliver(message, { classification: opening.classification });
37721
+ return;
37722
+ }
37723
+ state = {
37724
+ phase: "pinned",
37725
+ era: "modern",
37726
+ instance: state.instance
37727
+ };
37728
+ } else {
37729
+ const instance = await connectInstance("modern", opening.revision);
37730
+ if (isTornDown()) {
37731
+ await disposeLateInstance(instance);
37732
+ return;
37733
+ }
37734
+ state = {
37735
+ phase: "pinned",
37736
+ era: "modern",
37737
+ instance
37738
+ };
37739
+ }
37740
+ if (await tryServeListen(message)) return;
37741
+ state.instance.channel.deliver(message, { classification: opening.classification });
37742
+ return;
37743
+ case "legacy": {
37744
+ if (legacyMode === "reject") {
37745
+ if (isJSONRPCRequest(message)) await answerLegacyRejection(message, opening.reason, opening.requestedVersion);
37746
+ return;
37747
+ }
37748
+ if (state.phase === "probe") {
37749
+ await discardProbeInstance(state.instance);
37750
+ if (isTornDown()) return;
37751
+ state = { phase: "opening" };
37752
+ }
37753
+ const instance = await connectInstance("legacy");
37754
+ if (isTornDown()) {
37755
+ await disposeLateInstance(instance);
37756
+ return;
37757
+ }
37758
+ state = {
37759
+ phase: "pinned",
37760
+ era: "legacy",
37761
+ instance
37762
+ };
37763
+ state.instance.channel.deliver(message);
37764
+ return;
37765
+ }
37766
+ }
37767
+ };
37768
+ const queue = [];
37769
+ let pumping = false;
37770
+ const pump = async () => {
37771
+ if (pumping) return;
37772
+ pumping = true;
37773
+ try {
37774
+ while (queue.length > 0) {
37775
+ const message = queue.shift();
37776
+ try {
37777
+ await processMessage(message);
37778
+ } catch (error62) {
37779
+ if (isJSONRPCRequest(message)) await writeErrorResponse(message.id, ProtocolErrorCode.InternalError, "Internal server error");
37780
+ reportError(toError(error62));
37781
+ }
37782
+ }
37783
+ } finally {
37784
+ pumping = false;
37785
+ }
37786
+ };
37787
+ const closeAll = async () => {
37788
+ if (closing || state.phase === "closed") return;
37789
+ closing = true;
37790
+ const current = state;
37791
+ state = { phase: "closed" };
37792
+ for (const result of listenRouter.teardownAll()) await wire.send(result).catch((error62) => reportError(toError(error62)));
37793
+ if (current.phase === "probe" || current.phase === "pinned") await current.instance.product.close().catch((error62) => reportError(toError(error62)));
37794
+ await wire.close().catch((error62) => reportError(toError(error62)));
37795
+ };
37796
+ wire.onmessage = (message) => {
37797
+ queue.push(message);
37798
+ pump();
37799
+ };
37800
+ wire.onerror = (error62) => {
37801
+ reportError(error62);
37802
+ if (state.phase === "probe" || state.phase === "pinned") state.instance.channel.onerror?.(error62);
37803
+ };
37804
+ wire.onclose = () => {
37805
+ if (closing || state.phase === "closed") return;
37806
+ closing = true;
37807
+ const current = state;
37808
+ state = { phase: "closed" };
37809
+ if (current.phase === "probe" || current.phase === "pinned") current.instance.product.close().catch((error62) => reportError(toError(error62)));
37810
+ };
37811
+ const started = wire.start().catch((error62) => {
37812
+ reportError(toError(error62));
37813
+ throw error62;
37814
+ });
37815
+ started.catch(() => {
37816
+ });
37817
+ return { close: async () => {
37818
+ await started.catch(() => {
37819
+ });
37820
+ await closeAll();
37821
+ } };
37822
+ }
37823
+ function toError(value) {
37824
+ return value instanceof Error ? value : new Error(String(value));
37825
+ }
37826
+ var StdioServerTransport, DISCARD_ANSWER_TIMEOUT_MS, StdioConnectionChannel;
37263
37827
  var init_stdio = __esm({
37264
37828
  "node_modules/@modelcontextprotocol/server/dist/stdio.mjs"() {
37265
37829
  init_mcp_DXXb3Vv3();
@@ -37353,6 +37917,88 @@ var init_stdio = __esm({
37353
37917
  });
37354
37918
  }
37355
37919
  };
37920
+ DISCARD_ANSWER_TIMEOUT_MS = 3e3;
37921
+ StdioConnectionChannel = class {
37922
+ onclose;
37923
+ onerror;
37924
+ onmessage;
37925
+ _closed = false;
37926
+ /** Request ids the entry delivered to the instance that the instance has not yet answered. */
37927
+ _pendingRequests = /* @__PURE__ */ new Set();
37928
+ _drainWaiters = [];
37929
+ constructor(_wire, _onInstanceClose, _outboundIntercept) {
37930
+ this._wire = _wire;
37931
+ this._onInstanceClose = _onInstanceClose;
37932
+ this._outboundIntercept = _outboundIntercept;
37933
+ }
37934
+ async start() {
37935
+ }
37936
+ async send(message, options) {
37937
+ if (isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message)) {
37938
+ const { id } = message;
37939
+ if (id !== void 0) this._settle(id);
37940
+ }
37941
+ if (this._closed) return;
37942
+ if (this._outboundIntercept?.(message) === "handled") return;
37943
+ return this._wire.send(message, options);
37944
+ }
37945
+ setProtocolVersion = (version2) => {
37946
+ this._wire.setProtocolVersion?.(version2);
37947
+ };
37948
+ /** Forwards one inbound message to the connected instance. */
37949
+ deliver(message, extra) {
37950
+ if (this._closed) return;
37951
+ if (isJSONRPCRequest(message)) this._pendingRequests.add(message.id);
37952
+ else if (isJSONRPCNotification(message) && message.method === "notifications/cancelled") {
37953
+ const cancelledId = message.params?.requestId;
37954
+ if (cancelledId !== void 0) this._settle(cancelledId);
37955
+ }
37956
+ this.onmessage?.(message, extra);
37957
+ }
37958
+ /**
37959
+ * Resolves once every request delivered to the instance has been answered
37960
+ * through {@linkcode send}, settled by a delivered cancellation, or the
37961
+ * channel has been closed and nothing further can be answered. The wait is
37962
+ * bounded by `timeoutMs` as a backstop so no edge can hold the caller
37963
+ * indefinitely; resolves `false` only when the bound elapsed with requests
37964
+ * still unanswered. Used by the probe-discard path so a probe request the
37965
+ * entry accepted is never silently dropped.
37966
+ */
37967
+ async whenRequestsAnswered(timeoutMs) {
37968
+ if (this._closed || this._pendingRequests.size === 0) return true;
37969
+ return await new Promise((resolve2) => {
37970
+ const waiter = () => {
37971
+ clearTimeout(timer);
37972
+ resolve2(true);
37973
+ };
37974
+ const timer = setTimeout(() => {
37975
+ this._drainWaiters = this._drainWaiters.filter((pending) => pending !== waiter);
37976
+ resolve2(false);
37977
+ }, timeoutMs);
37978
+ this._drainWaiters.push(waiter);
37979
+ });
37980
+ }
37981
+ async close() {
37982
+ if (this._closed) return;
37983
+ this._closed = true;
37984
+ this._pendingRequests.clear();
37985
+ this._releaseDrainWaiters();
37986
+ try {
37987
+ this._onInstanceClose();
37988
+ } finally {
37989
+ this.onclose?.();
37990
+ }
37991
+ }
37992
+ _settle(id) {
37993
+ this._pendingRequests.delete(id);
37994
+ if (this._pendingRequests.size === 0) this._releaseDrainWaiters();
37995
+ }
37996
+ _releaseDrainWaiters() {
37997
+ const waiters = this._drainWaiters;
37998
+ this._drainWaiters = [];
37999
+ for (const waiter of waiters) waiter();
38000
+ }
38001
+ };
37356
38002
  }
37357
38003
  });
37358
38004
 
@@ -57858,7 +58504,7 @@ async function createMcpServer(opts) {
57858
58504
  }
57859
58505
  return server;
57860
58506
  }
57861
- function withGracefulShutdown(server, opts = {}) {
58507
+ function withGracefulShutdown(target, opts = {}) {
57862
58508
  const shouldExit = opts.exit ?? true;
57863
58509
  let shuttingDown = false;
57864
58510
  const handler = (signal) => {
@@ -57869,7 +58515,7 @@ function withGracefulShutdown(server, opts = {}) {
57869
58515
  try {
57870
58516
  if (opts.onSignal)
57871
58517
  await opts.onSignal(signal);
57872
- await server.close();
58518
+ await target.close();
57873
58519
  } catch (err) {
57874
58520
  console.error(`[mcp-utils] error during graceful shutdown on ${signal}: ${err instanceof Error ? err.message : String(err)}`);
57875
58521
  } finally {
@@ -57881,16 +58527,26 @@ function withGracefulShutdown(server, opts = {}) {
57881
58527
  process.on("SIGINT", () => handler("SIGINT"));
57882
58528
  process.on("SIGTERM", () => handler("SIGTERM"));
57883
58529
  }
57884
- async function runMcp(opts) {
57885
- const server = await createMcpServer(opts);
58530
+ function runMcp(opts) {
58531
+ if (opts.banner !== void 0) {
58532
+ console.error(opts.banner);
58533
+ }
58534
+ const spec = opts.transport ?? "stdio";
58535
+ const handle = serveStdio(() => createMcpServer({ ...opts, banner: void 0 }), {
58536
+ legacy: opts.legacy ?? "serve",
58537
+ onerror: opts.onerror ?? ((error62) => {
58538
+ console.error(`[mcp-utils] stdio server error: ${redactSecrets(error62.message)}`);
58539
+ }),
58540
+ // `'stdio'` means "let the entry make its own StdioServerTransport over
58541
+ // this process"; anything else is the caller's transport, which the entry
58542
+ // then owns (it starts it, pumps it, and closes it with the handle).
58543
+ ...spec === "stdio" ? {} : { transport: spec }
58544
+ });
57886
58545
  const shutdown = opts.shutdown ?? true;
57887
58546
  if (shutdown !== false) {
57888
- withGracefulShutdown(server, shutdown === true ? {} : shutdown);
58547
+ withGracefulShutdown(handle, shutdown === true ? {} : shutdown);
57889
58548
  }
57890
- const spec = opts.transport ?? "stdio";
57891
- const transport = spec === "stdio" ? new StdioServerTransport() : spec;
57892
- await server.connect(transport);
57893
- return server;
58549
+ return handle;
57894
58550
  }
57895
58551
  var SERVER_PROTOCOL_VERSIONS;
57896
58552
  var init_server = __esm({
@@ -58536,7 +59192,7 @@ async function loadStdioDotenv() {
58536
59192
  }
58537
59193
 
58538
59194
  // src/version.ts
58539
- var VERSION = "2.0.0";
59195
+ var VERSION = "2.1.0";
58540
59196
 
58541
59197
  // src/errors.ts
58542
59198
  init_dist2();
@@ -59757,7 +60413,7 @@ async function withProgressHeartbeat(extra, message, fn) {
59757
60413
  if (active) {
59758
60414
  console.error(`[gemini-mcp] heartbeat active: progressToken present, interval=${intervalMs}ms \u2014 ${message}`);
59759
60415
  } else {
59760
- const reason = progressToken === void 0 ? "no progressToken from host (host cannot extend its tools/call timeout; long calls will hit it)" : !send ? "host provided no sendNotification channel" : "heartbeat disabled (GEMINI_HEARTBEAT_MS=0)";
60416
+ const reason = progressToken === void 0 ? "no progressToken from host (host cannot extend its tools/call timeout; long calls will hit it)" : !send ? "no mcpReq.notify on the request extra (SDK v2 renamed v1's sendNotification; without it there is no channel to send progress on)" : "heartbeat disabled (GEMINI_HEARTBEAT_MS=0)";
59761
60417
  console.error(`[gemini-mcp] heartbeat inactive: ${reason} \u2014 ${message}`);
59762
60418
  }
59763
60419
  }
@@ -376,7 +376,7 @@ export async function withProgressHeartbeat(extra, message, fn) {
376
376
  const reason = progressToken === undefined
377
377
  ? 'no progressToken from host (host cannot extend its tools/call timeout; long calls will hit it)'
378
378
  : !send
379
- ? 'host provided no sendNotification channel'
379
+ ? 'no mcpReq.notify on the request extra (SDK v2 renamed v1\'s sendNotification; without it there is no channel to send progress on)'
380
380
  : 'heartbeat disabled (GEMINI_HEARTBEAT_MS=0)';
381
381
  console.error(`[gemini-mcp] heartbeat inactive: ${reason} — ${message}`);
382
382
  }
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.0.0'; // x-release-please-version
2
+ export const VERSION = '2.1.0'; // x-release-please-version
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chrischall/gemini-mcp",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
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": "^0.28.0",
49
+ "@chrischall/mcp-utils": "^1.0.0",
50
50
  "@modelcontextprotocol/server": "^2.0.0",
51
51
  "dotenv": "^17.4.0",
52
52
  "zod": "^4.6.2"
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.0.0",
9
+ "version": "2.1.0",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "identifier": "@chrischall/gemini-mcp",
14
- "version": "2.0.0",
14
+ "version": "2.1.0",
15
15
  "transport": {
16
16
  "type": "stdio"
17
17
  },