@chrischall/gemini-mcp 0.2.0 → 0.4.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.
@@ -3,8 +3,8 @@ import { textResult } from '@chrischall/mcp-utils';
3
3
  import { writeImage, resolveOutputDir } from '../images.js';
4
4
  /** Supported output aspect ratios (Gemini image API). */
5
5
  export const ASPECT_RATIOS = ['1:1', '2:3', '3:2', '3:4', '4:3', '4:5', '5:4', '9:16', '16:9', '21:9', '1:4', '4:1', '1:8', '8:1'];
6
- /** Supported output resolutions. */
7
- export const IMAGE_SIZES = ['1K', '2K', '4K'];
6
+ /** Supported output resolutions. `512` is Flash-only (0.5K); `1K`/`2K`/`4K` work on all image models. */
7
+ export const IMAGE_SIZES = ['512', '1K', '2K', '4K'];
8
8
  /**
9
9
  * The model/aspect/size/output fields every generation tool shares. Defined once
10
10
  * here so descriptions can't drift between `generate.ts` and `set.ts`. Spread
@@ -13,23 +13,49 @@ export const IMAGE_SIZES = ['1K', '2K', '4K'];
13
13
  export const sharedImageSchema = {
14
14
  model: z.string().optional().describe('Model id override (default: server default; see gemini_list_models)'),
15
15
  aspect_ratio: z.enum(ASPECT_RATIOS).optional().describe('Output aspect ratio'),
16
- image_size: z.enum(IMAGE_SIZES).optional().describe('Output resolution'),
16
+ image_size: z.enum(IMAGE_SIZES).optional().describe('Output resolution (512 = 0.5K, Flash-only)'),
17
17
  output_dir: z.string().optional().describe('Directory to write images to (default: $GEMINI_OUTPUT_DIR or cwd)'),
18
18
  inline: z.boolean().optional().describe('Return base64 images inline instead of writing to disk'),
19
+ seed: z.number().int().optional().describe('Seed for reproducible generation; random if omitted'),
20
+ thinking_level: z.enum(['minimal', 'high']).optional().describe('Reasoning depth (Gemini 3 models); higher can help complex/structural edits'),
21
+ google_search: z.boolean().optional().describe('Ground the image in live Google Search results (current events, weather, data)'),
22
+ from_clipboard: z.boolean().optional().describe('Use the image currently on the macOS system clipboard as an input (downscaled to JPEG)'),
19
23
  };
24
+ /**
25
+ * Return the provided seed, or pick a random one. Capped well below INT32_MAX
26
+ * so derived per-image seeds (`seed + i`) can't overflow a 32-bit int.
27
+ */
28
+ export function pickSeed(seed) {
29
+ return seed ?? Math.floor(Math.random() * 2_147_483_000);
30
+ }
31
+ /** Build the result metadata echoed to the caller (omitting unset optionals). */
32
+ export function buildMeta(model, seed, opts) {
33
+ const meta = { model, seed };
34
+ if (opts.aspect_ratio)
35
+ meta.aspect_ratio = opts.aspect_ratio;
36
+ if (opts.image_size)
37
+ meta.image_size = opts.image_size;
38
+ return meta;
39
+ }
20
40
  /**
21
41
  * Either return images inline (base64 content blocks) or write them to disk and
22
42
  * return their paths as a text result. `inline` wins when true.
43
+ * Optional `meta` is merged into the disk-path JSON result, or prepended as a
44
+ * text block in inline mode (only if meta has keys).
23
45
  */
24
- export async function emit(named, opts) {
46
+ export async function emit(named, opts, meta) {
25
47
  if (opts.inline) {
26
- return {
27
- content: named.map((n) => ({ type: 'image', data: n.image.base64, mimeType: n.image.mimeType })),
28
- };
48
+ const imageBlocks = named.map((n) => ({ type: 'image', data: n.image.base64, mimeType: n.image.mimeType }));
49
+ if (meta && Object.keys(meta).length > 0) {
50
+ return {
51
+ content: [{ type: 'text', text: JSON.stringify(meta, null, 2) }, ...imageBlocks],
52
+ };
53
+ }
54
+ return { content: imageBlocks };
29
55
  }
30
56
  const dir = resolveOutputDir(opts.output_dir);
31
57
  const images = [];
32
58
  for (const n of named)
33
59
  images.push(await writeImage(dir, n.base, n.image.base64, n.image.mimeType));
34
- return textResult({ images });
60
+ return textResult({ images, ...meta });
35
61
  }
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 = '0.2.0'; // x-release-please-version
2
+ export const VERSION = '0.4.0'; // x-release-please-version
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chrischall/gemini-mcp",
3
- "version": "0.2.0",
3
+ "version": "0.4.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>",
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": "0.2.0",
9
+ "version": "0.4.0",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "identifier": "@chrischall/gemini-mcp",
14
- "version": "0.2.0",
14
+ "version": "0.4.0",
15
15
  "transport": {
16
16
  "type": "stdio"
17
17
  },
@@ -36,6 +36,13 @@
36
36
  "isRequired": false,
37
37
  "format": "string",
38
38
  "isSecret": false
39
+ },
40
+ {
41
+ "name": "GEMINI_INPUT_DIR",
42
+ "description": "Directory to resolve bare input-image filenames against",
43
+ "isRequired": false,
44
+ "format": "string",
45
+ "isSecret": false
39
46
  }
40
47
  ]
41
48
  }