Skip to content

fix: several MCP server and TOML schema bugs - #67

Open
tellang wants to merge 1 commit into
gemini-cli-extensions:mainfrom
tellang:fix/filehandler-mime-seed-schema-bugs
Open

fix: several MCP server and TOML schema bugs#67
tellang wants to merge 1 commit into
gemini-cli-extensions:mainfrom
tellang:fix/filehandler-mime-seed-schema-bugs

Conversation

@tellang

@tellang tellang commented Apr 20, 2026

Copy link
Copy Markdown

Summary

Six small fixes, mostly in fileHandler / imageGenerator plus two TOML command schemas. Public MCP tool schemas (tool names, required args, output shapes) are unchanged.

Fixes

  • fileHandler uses os.homedir() for search pathsprocess.env.HOME || '~' produced literal ~\Downloads / ~\Desktop on Windows (Node doesn't set HOME by default). os.homedir() resolves HOME on Unix and USERPROFILE on Windows.

  • generateFilename matches extension to the actual MIME type — the model regularly returns image/jpeg in inlineData.mimeType, but the extension was derived solely from the caller's format argument (default png). Result: .png files on disk containing JPEG bytes (file reports JPEG image data, JFIF standard 1.01). Added a mimeType?: string argument; picks jpg / png / webp / gif from the MIME type, falling back to format only when the MIME type is missing or unrecognised.

  • seed is forwarded to generateContentseed was advertised in the MCP schema and carried in ImageGenerationRequest, but silently dropped before the SDK call, making the parameter a no-op. Added config: { seed } on the three call sites (generateTextToImage, generateStorySequence, editImage).

  • isValidBase64ImageData checks magic bytes — previously any base64-shaped string longer than 1000 chars was accepted. Now checks PNG (89 50 4E 47 ...), JPEG (FF D8 FF), WebP (RIFF + WEBP), and GIF (GIF87a / GIF89a) magic on the first decoded bytes, so long non-image base64 payloads (logs, JSON) are no longer written to disk.

  • commands/generate.toml exposes --no-previewindex.ts already reads noPreview / no-preview in the generate_image handler, but the TOML parser prompt only listed --preview, so users had no documented way to force preview off. Added --no-preview (flag) to the valid-options list and the error-message fallback.

  • commands/icon.toml strengthens --sizes parsing — the TOML LLM parser was occasionally forwarding --sizes="16,32,64" as a plain string or a single integer instead of [16, 32, 64]. Strengthened the prompt so the parser must produce an integer array before calling generate_icon.

Out of scope

saveImageFromBase64 write race — deliberately left for #60, which already modifies that function. Touching it here would just create a merge conflict.

Test plan

  • npm run build passes cleanly in mcp-server/
  • tools/list via JSON-RPC still returns the same 7 tools with the same schemas
  • Live generate_image call returned mimeType: 'image/jpeg' and was saved as smoke_test_mime_fix_clean_white_.jpg (magic bytes FF D8 FF E0 ... JFIF). Before the fix, the same response would have written a .png file
  • Not verified: seed producing deterministic output across back-to-back calls — the SDK accepts the config.seed field, but I didn't run a reproducibility smoke
  • Tested Windows path resolution indirectly (developed on a Windows box where HOME is unset — old code would have silently failed, new code works). No explicit Downloads/Desktop lookup regression test.

- fileHandler: use os.homedir() instead of `process.env.HOME || '~'`
  for Downloads/Desktop search paths. Node does not set HOME on
  Windows, so the previous expression produced literal `~\Downloads`
  that silently never matched.

- fileHandler: generateFilename now accepts a mimeType argument and
  derives the extension from it (JPEG -> jpg, PNG -> png, WebP -> webp,
  GIF -> gif), falling back to the caller's `format` only when the
  MIME type is missing or unrecognised. Previously the extension was
  always derived from `fileFormat` (default png), so JPEG bytes
  returned by the model were saved under a `.png` filename whenever
  `image/jpeg` came back in inlineData.

- imageGenerator: forward `seed` to generateContent via `config`.
  The MCP generate_image tool has always exposed a seed parameter
  and ImageGenerationRequest carried it, but the value was dropped
  before reaching the Google GenAI SDK, making seeded variations a
  no-op.

- imageGenerator: isValidBase64ImageData now checks PNG/JPEG/WebP/
  GIF magic bytes after the base64 shape check, so long base64-like
  strings that aren't actually images (logs, JSON payloads) are no
  longer accepted.

- commands/generate.toml: expose --no-preview flag. The MCP handler
  in index.ts already reads noPreview / no-preview, but the TOML
  parser prompt listed only --preview, so users had no documented
  way to force preview off.

- commands/icon.toml: strengthen the --sizes instruction to require
  parsing as an integer array (e.g. "16,32,64" -> [16, 32, 64]),
  since the TOML LLM parser was occasionally forwarding it as a
  plain string or a single integer.

The saveImageFromBase64 write race is deliberately left for PR gemini-cli-extensions#60,
which already modifies that function.
@google-cla

google-cla Bot commented Apr 20, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant