Skip to main content
Glama

gemini-mcp

CI npm license

MCP server for Google Gemini media generation. Exposes thirteen tools to Claude over stdio: list available models, generate/edit/compose images, generate a consistent set of images from a master prompt, multi-turn image refinement (Interactions API), video generation (omni), music generation (Lyria), an async result poll for long generations, and Files API upload/list/delete for reusable image references. Output is written to disk by default (path returned) or returned inline as base64. Built on the Gemini v1beta API (generativelanguage.googleapis.com) using the Nano Banana / Nano Banana Pro (images), omni (video), and Lyria (music) model families.

Developed and maintained by AI (Claude Code).

Environment Variables

Variable

Required

Description

GEMINI_API_KEY

Yes

Your Google Gemini API key (aistudio.google.com/apikey)

GEMINI_IMAGE_MODEL

No

Override the default image model (default: gemini-nano-banana-2.1)

GEMINI_OUTPUT_DIR

No

Default directory for generated images (default: ~/Downloads/gemini-mcp). When set, a per-call output_dir must be inside it.

GEMINI_INPUT_DIR

No

Directory to resolve bare input-image filenames against (so images: ["foo.jpg"] works)

GEMINI_UPLOAD_DIR

No

Restrict local files streamed to the Gemini Files API (gemini_upload_file path, video_path) to these directories — one or more, separated by : (; on Windows); ~ allowed. A path outside is refused before any upload. Unset: no restriction

GEMINI_REFERENCE_DIR

No

Restrict local reference images (the images / master_images paths read and sent to Gemini — inline, or as a Files API upload once reused) to these directories — :-separated (; on Windows), ~ allowed; GEMINI_OUTPUT_DIR is always allowed too, so generated images can be fed back in. A path outside (symlinks followed) is refused before it is read. Unset: GEMINI_UPLOAD_DIR applies instead. If both are unset, reference images are unrestricted on a local install (any file the server can read can be sent), and confined to $MCP_DATA_DIR/uploads when MCP_DATA_DIR is set (hosted)

GEMINI_TIMEOUT_MS

No

Upstream request timeout in ms (default: 60000, or 120000 for image_size: "4K"); each generation tool also takes a per-call timeout_ms

GEMINI_HEARTBEAT_MS

No

Progress-notification cadence in ms while a generation runs (default: 10000; 0 disables) — keeps MCP hosts that reset their timeout on progress from timing out long generations

GEMINI_CHAIN_RETRY_MS

No

How long to wait out interactions-store lag when a chained call 404s (default: 120000; 0 disables retrying)

Confirmations

Sending a local file to Google (the images / master_images / video_path inputs, or gemini_upload_file's path) and every delete ask for confirmation first. A client that can show a confirmation prompt (Claude Code) gets the real prompt, unless MCP_CONFIRM_ELICITATION=off. Elsewhere the first call does nothing and returns a preview (the resolved local paths with their MIME types and sizes, or the method/path being deleted) plus a confirmToken; only a repeat call with the same arguments and that token proceeds. The token is single-use, expires, and is bound to the exact arguments — a changed prompt or a swapped file between the two calls is refused. Pure text prompts, URLs, files/ references and base64 inputs are not gated.

variable

default

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.

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.

MCP_CONFIRM_TTL_SECONDS

600

How long a token stays valid.

MCP_CONFIRM_SECRET

random per process

Signing key; set it only if tokens must survive a server restart.

Long generations and client timeouts

4K / Pro-model generations can outrun an MCP host's own tools/call timeout (error -32001). The server sends notifications/progress heartbeats so hosts that reset their timeout on progress wait it out. If the host still gives up, the server-side generation usually completes anyway: the image is written to the output dir, gemini_interact also writes an <image>.json sidecar recording the interaction_id, and continue_last: true resumes the interaction the lost response belonged to.

When a chained call 404s

A 404 on a request carrying previous_interaction_id is not proof the chain expired. The only 404 body observed live is generic — "Requested entity was not found." — and never names which entity. An unknown or renamed model id, and an expired Files API files/… uri (~48h TTL), return exactly the same thing. So the server no longer asserts a cause it can't establish: the upstream text is surfaced verbatim, and gemini_interact runs an experiment to find out which it was.

Most often the id isn't missing at all — it just isn't visible yet. The interactions store is eventually consistent, and a freshly created id can 404 while the same id resolves fine minutes later; heavy turns (4K, Pro, thinking_level: high) are the likeliest to hit it, which is exactly the turn you most want to chain from. So a chained 404 is retried with exponential backoff for up to 120s (GEMINI_CHAIN_RETRY_MS) before anything is declared broken. The 404 generates nothing and isn't billed, so the wait costs only time.

After that budget is spent, the tool looks up that id's sidecar, re-attaches the image it produced, and re-issues the request without the chain:

  • The re-issue succeeds → the chain really was the problem, and you get your image anyway, reported as chain_recovered: { expired_interaction_id, reanchored_on }. The 404'd attempt generates nothing, so this costs the one generation you'd have paid for re-anchoring manually.

  • The re-issue 404s too → the interaction id was never the cause. You get told exactly that, with the upstream text, and pointed at the model id and any files/… uri instead of being sent to chase an interaction that was fine all along.

  • No sidecar matches the dead id → the original error, rather than a guess. Re-anchoring on the wrong picture would silently corrupt the edit.

Separately, continue_last no longer dies with the server process: with no in-memory id it resumes from the newest <image>.json sidecar in the output dir and reports continued_from_sidecar: true. That case was never an expired chain at all — the interaction was alive upstream the whole time; only our memory of its id was gone.

For hosts whose timeout can't be tamed (e.g. Claude Desktop, a fixed ~30s cap that ignores progress), two guards make re-issuing safe and unnecessary:

  • async: true returns a job_id immediately instead of the image, so the call can't time out at all; poll gemini_get_result with the job_id until it's done.

  • idempotency_key makes a repeat call idempotent — a retry with the same key returns the recorded result (reused: true) instead of billing a second generation. (Even without a key, two identical in-flight calls are deduplicated automatically.)

Related MCP server: mmxomni

Tools

Tool

Description

gemini_list_models

List available Gemini image models and the current default

gemini_image_generate

Generate image(s) from a text prompt

gemini_image_edit

One-off edits or multi-image composition with a text instruction (for a series of edits, use gemini_interact)

gemini_image_set

Generate a master image plus N consistent images referencing it

gemini_interact

Preferred tool for iterative refinement: multi-turn generation/editing via the Interactions API — chain the returned interaction_id via previous_interaction_id (or continue_last: true)

gemini_video_generate

Generate a short video (text→video, image→video, two-still interpolation, edit or extend) via the Gemini omni model; resolution 360p/720p/1080p/4k is the cost lever; written to disk as MP4

gemini_music_generate

Generate music from a text prompt via a Lyria model — lyria-3-clip-preview (30s, default), lyria-3.5 (full-length, vocals) or lyria-3-pro-preview; single-turn; written to disk as MP3

gemini_get_result

Fetch an async generation started with async: true by its job_id (status running → done result). Lets a long generation outlive a host's tools/call timeout

gemini_token_usage

Token usage and an estimated USD cost for this session so far. Call it before and after a workflow and subtract to attribute that workflow's spend. Priced per call against each call's own model from a dated rate card (GEMINI_RATE_CARD overrides it); there is no account-balance endpoint to read, so this is how spend is attributed

gemini_upload_file

Upload an image (or video/audio) to the Gemini Files API once — from a url, data_base64, or a local path — and get a reusable files/<id> reference

gemini_list_files

List the files currently uploaded under this API key, with MIME types and expiry times

gemini_delete_file

Delete an uploaded file before its ~48h expiry (confirmed first — see Confirmations)

gemini_sign_media

(hosted deployments only) Mint a fresh signed URL for generated media from its r2_key — an expired link is not a dead end

gemini_view_media

(hosted deployments only) Return a generated image as an inline image block from its r2_key, so a model can actually see what it made before refining it

gemini_get_upload_url

(hosted deployments only) Mint a short-lived signed PUT URL so a shell can upload a reference image with no auth header; the PUT returns an r2_key usable in images_r2_keys, gemini_save_character, or gemini_upload_file

gemini_save_character / gemini_list_characters / gemini_delete_character

(hosted deployments only) Persistent per-account character library: save a reference image + description under a name, then pass characters: ["name"] on generation tools. No expiry

gemini_save_style / gemini_list_styles / gemini_delete_style

(hosted deployments only) Persistent per-account style presets: a reusable prompt fragment (optionally with a reference image), applied by passing style: "name" on generation tools. No expiry

Generation tools also share three throughput/latency controls: async: true (return a job_id immediately), max_wait_ms (wait up to a budget, then hand back the job_id — fast results stay in-band, slow batches never trip the host timeout), and idempotency_key (a retry returns the recorded result instead of re-billing). On a hosted deployment, a gemini_image_set result with more than one image also carries a bundle_url — one signed URL for a zip of every image in the set. Like every hosted link it lives at most 24h (the host's blob-store ceiling); gemini_sign_media re-mints an expired one. (A set too large to zip safely in memory skips the bundle and says so via bundle_skipped; the per-image links are unaffected.)

Seeing your images (hosted)

On a hosted deployment there is no filesystem, so a generated image has to come back as something you can open. It does: every result includes a URL, with no configuration.

{
  "images": ["https://mcp.nullnet.app/b/<account>/gemini/gen/2026-07-29/ab12cd34-a-cat.png?exp=…&sig=…"],
  "media":  [{ "url": "https://…", "r2_key": "gen/2026-07-29/ab12cd34-a-cat.png",
               "expires_at": "2026-07-31T12:00:00.000Z",
               "curl_hint": "curl -sS -o a-cat.png \"https://…\"" }]
}

Those links need no auth header — the signature is in the URL — so they work in a browser, in curl, and in a chat message. They expire after at most 24h — the host's blob store refuses a longer signature — and the objects behind them are swept on the host's retention schedule. The r2_key is the durable handle for that window:

  • gemini_sign_media (hosted deployments only) mints a fresh signed URL from an r2_key, so an expired link never forces you to re-generate — and re-pay for — the image.

  • The interaction id is stored beside each image, so a hosted deployment recovers a lost turn the way the local one does: continue_last: true survives a restart, a chained 404 is re-anchored on the image that interaction produced, and gemini_list_recent_media shows the prompt, model and interaction id for every stored object rather than a wall of keys.

  • gemini_view_media (hosted deployments only) returns the image itself, inline, from an r2_key. A link is not something a model can look at, so without this a generate → refine loop runs blind. It is a separate call rather than bytes on every result: you pay image tokens only on the turns you actually look.

  • gemini_upload_file with r2_key turns media this server generated into a Files API reference (the server reads it back with its own key — no signature for you to mint), so a generated image can become the reference image for the next generation in one cheap call.

  • Idempotent replays (idempotency_key) re-mint the URLs inside the recorded result before returning it, so a reused result never carries a dead link.

Why this matters: MCP's inline image content blocks (inline: true) are visible to the assistant but many chat clients never render them to the user, and the assistant cannot extract bytes back out of its own context to save them elsewhere. A generation could bill successfully and be invisible. A URL is the portable answer; inline remains available, but it is no longer the only way to receive media.

How the bytes are served

The host stores each generated object and serves it back at a signed, expiring URL — https://<host>/b/<account>/gemini/<key>?exp=&sig=. No setup, and no auth header: the signature in the link is the authorization, so curl and a browser both work.

Auth is a signed, expiring URL rather than an unlisted key. Random keys would be simpler, but they never expire and never revoke: anything that ever logged or forwarded the link keeps working forever. A signature scopes access to one object with a deadline, and rotating the host's signing key (MCP_BLOB_SIGNING_KEY, which mcp-host injects together with MCP_BLOB_BASE_URL; this server never chooses either) invalidates every outstanding link at once. The tradeoff is that links are long and cannot be shortened by hand.

For assistants relaying a result

Show the user the URL. If your sandbox has network egress to the host, fetching it and attaching the bytes as a file gives the nicest result; otherwise present the link itself. Whether a given client renders ![](url) markdown inline varies by client — a bare URL is the safe form, and a markdown link is a reasonable enhancement where you know it renders.

Retention

Retention is the host's, not a setting of this server. On mcp-host, the blob store prunes generated media (gen/) and signed uploads (up/) on its own schedule (see mcp-host docs/BLOB-STORE.md; default 30 days), while the character/style library (lib/) is written as retention-exempt, so saved entries never expire. Every signed link is clamped to the store's 24h ceiling, so it never outlives what the store will honour; gemini_sign_media re-mints one for as long as the object exists. The variables this server reads for it are injected by the host: MCP_BLOB_BASE_URL and MCP_BLOB_SIGNING_KEY.

Prompts are stored too. Each generated object on a hosted deployment gets a small JSON record beside it holding the prompt (first 500 characters), model and interaction id — that is what gemini_list_recent_media shows and what lets a lost turn be recovered. The record lives and is swept with its object, so it is kept for the same retention window, not longer. Locally, gemini_interact writes an <image>.json sidecar (model, interaction id, options and any text the model replied with — not the prompt itself) next to each image in the output dir; those files are yours to keep or delete and never expire on their own. If your prompts describe real people, bear in mind they sit in your bucket for the retention window.

Sending reference images without burning context

Every tool that takes a reference image — gemini_image_generate, gemini_image_edit, gemini_image_set, gemini_interact, plus gemini_video_generate (reference stills) and gemini_music_generate — accepts them four ways. Only one of them costs model context:

Parameter

Where the bytes travel

Context cost

images_url (master_images_url)

the server downloads the https URL

none

images_file_uris (master_images_file_uris)

a files/<id> reference, already uploaded

none

images_r2_keys (master_images_r2_keys)

the server reads its own store (hosted deployments only)

none

images

read off local disk (stdio builds only)

none

characters / style

saved library entries, attached by name (hosted deployments only)

none

images_base64

through the tool-call JSON

~14k tokens per JPEG

images_base64 is the fallback of last resort. It costs roughly 14k tokens per modest photo, and it is silently corrupted whenever the file read that produced it was truncated — the payload still looks like base64, so the failure surfaces as a bad generation rather than an error. Prefer any of the other three.

images_url — the server fetches it

{ "prompt": "make it look like winter", "images_url": ["https://example.com/photo.jpg"] }

Fetches are restricted to public https:// URLs — private, loopback and link-local hosts are refused (IPv6 literals are parsed, so [::ffff:7f00:1] is caught as loopback), every redirect hop is revalidated, and each hop is bounded by a timeout. The response must be Content-Type: image/* and is capped at 15MB, enforced while streaming rather than trusted from Content-Length. A failure names the offending URL. Anything over 6MB is uploaded to the Files API and referenced by uri instead of inlined, since generateContent caps a whole request near 20MB.

images_file_uris — upload once, reference many times

// 1. upload
{ "tool": "gemini_upload_file", "url": "https://example.com/photo.jpg" }
// → { "file_uri": "files/abc123", "mime_type": "image/jpeg", "expires": "..." }

// 2. reference it, as many times as you like
{ "prompt": "make it winter",  "images_file_uris": ["files/abc123"] }
{ "prompt": "make it sunrise", "images_file_uris": ["files/abc123"] }

Uploads are retained ~48h; after that the reference stops resolving (as a generic 404 — see the chained-404 section above). gemini_image_set fetches or resolves such a reference once and passes it to the master and every scene call.

On stdio builds, a local images path that gets referenced more than once in a session is uploaded to the Files API automatically (keyed on path + mtime + size), so repeated edits of the same photo stop re-sending the bytes. Editing the file invalidates the cached upload.

Signed upload URLs — no token at all (hosted)

This is the intended path for an agent with a shell: disk file → curl → r2_key → tool call, with the image never entering the conversation. gemini_get_upload_url mints a short-lived (~10 min) signed PUT URL, and the shell uploads with zero auth headers — the signature in the URL is the authorization, mirroring how the download links work.

# 1. tool call: gemini_get_upload_url { filename: "photo.jpg", content_type: "image/jpeg" }
#    → { upload_url, r2_key, expires_at, curl_hint }

# 2. shell:
curl -sS -X PUT -H "Content-Type: image/jpeg" --data-binary @photo.jpg "$UPLOAD_URL"
# → { "r2_key": "up/<tenant>/2026-07-31/ab12cd34-photo.jpg", "size_bytes": 812345, ... }

The signature covers one tenant-scoped object key, the declared content type and the expiry; uploads are capped at 15MB, enforced while reading the stream. Only raster image types are accepted (jpeg/png/webp/gif/avif/heic/heif/bmp/tiff) — SVG is deliberately refused, because an SVG is a scriptable document and /media serves from the server's own origin. The returned r2_key is then usable three ways: directly as images_r2_keys on any generation tool (the server reads its own bucket — no bytes in the conversation), permanently via gemini_save_character, or as a ~48h Files API reference via gemini_upload_file({ r2_key }). Uploads themselves follow the host's blob-store retention schedule (up/ prefix).

Character & style library (hosted)

Recurring subjects and styles can be saved once, per account, with no expiry (the library's lib/ objects are written retention-exempt, so the host's prune skips them):

// once:
{ "tool": "gemini_save_character", "name": "finn",
  "description": "6-year-old boy, curly red hair", "image_r2_key": "up/…/photo.jpg" }
{ "tool": "gemini_save_style", "name": "bold-cartoon-sports",
  "prompt_fragment": "bold cartoon style, thick outlines, saturated colors" }

// afterwards, on any generation:
{ "tool": "gemini_image_set",
  "master_prompt": "Finn on a soccer field",
  "scenes": ["kicking the ball", "celebrating a goal"],
  "characters": ["finn"], "style": "bold-cartoon-sports" }

Naming a character attaches its saved reference image and weaves its description into the prompt; naming a style appends its fragment (and attaches its reference image, if it has one). gemini_image_set passes character references to the master and every scene call, which is what keeps the subject consistent across the set.

Quick Start

{
  "mcpServers": {
    "gemini": {
      "command": "npx",
      "args": ["-y", "@chrischall/gemini-mcp"],
      "env": {
        "GEMINI_API_KEY": "your-api-key-here"
      }
    }
  }
}

See SKILL.md for full usage documentation.

Available Tools

13 tools
gemini_delete_fileA
Destructive

Delete an uploaded file, image or photo (by file_uri) from the Gemini Files API before its ~48h expiry. Any tool call still referencing it will then fail with a generic 404, so delete only references you are finished with. Asks the user to confirm first: a confirmation prompt where the client supports one; otherwise the first call returns a preview and a confirmToken, and only a repeat call with that token proceeds (see MCP_CONFIRM_MODE).

Inputs: file_uri (required), confirmToken.

gemini_get_resultA
Destructive

Retrieve a generation started with async: true or handed off by max_wait_ms. Pass the returned job_id: while running it reports status "running"; on completion it returns the normal result (image URLs/paths + meta); on failure it raises the recorded error, including the case where the generation was killed before it finished. On the hosted connector job records are stored durably and survive a restart; on a local stdio server they live with the process and expire ~10 min after completion, where the output dir / .json sidecar is the fallback. A killed video/music job started with background: true is recovered from its upstream interaction when it finished there.

Inputs: job_id (required), output_dir.

gemini_healthcheckVerify credentials and upstream reachabilityA
Read-onlyIdempotent

Resolves the credential the way real tools do, then makes one authenticated request to generativelanguage.googleapis.com. Reports which source supplied the credential, whether generativelanguage.googleapis.com accepted it, the round-trip time, and a plain-English hint distinguishing 'no credential' from 'credential rejected' from 'a generativelanguage.googleapis.com-side problem'. Read-only; never returns the credential itself. Call this when a real tool fails and you want to know which hop broke.

Inputs: no named parameters.

gemini_image_editA
Destructive

Edit or compose images: provide one or more input images (paths or base64), plus a text instruction. For a SERIES of successive edits to the same image, prefer gemini_interact (multi-turn) — it keeps edit context and avoids re-processing the full image each round; use gemini_image_edit for one-off edits or composing multiple distinct inputs. Gemini over-preserves the input; there is no edit-strength control — for large structural changes, reroll with a different seed or more forceful wording. Local file inputs are confirmed first: a confirmation prompt where the client supports one; otherwise the first call returns a preview and a confirmToken, and only a repeat call with that token proceeds (see MCP_CONFIRM_MODE).

Inputs: prompt (required), seed, async, model, +20 more.

gemini_image_generateA
Destructive

Generate image(s) from a text prompt with a Gemini image model (Nano Banana / Nano Banana Pro). If the result will likely be refined iteratively, prefer gemini_interact (multi-turn) as the entry point. Local file inputs are confirmed first: a confirmation prompt where the client supports one; otherwise the first call returns a preview and a confirmToken, and only a repeat call with that token proceeds (see MCP_CONFIRM_MODE).

Inputs: prompt (required), seed, async, count, +23 more.

gemini_image_setA
Destructive

Generate a consistent SET of images: a master image from master_prompt, then one image per scene that references the master so the subject/style stays consistent. Provide scenes (explicit per-image prompts) OR count (variations of the master). Scene generations run in parallel (reference_mode "master", the default). On the hosted connector: saved characters and a saved style can seed the whole set by name, multi-image results include a bundle_url zip of every image (one curl instead of N), and max_wait_ms returns a pollable job handle if the batch runs long. Local file inputs are confirmed first: a confirmation prompt where the client supports one; otherwise the first call returns a preview and a confirmToken, and only a repeat call with that token proceeds (see MCP_CONFIRM_MODE).

Inputs: master_prompt (required), seed, async, count, +23 more.

gemini_interactA
Destructive

Preferred tool for iterative refinement of a single image — multi-turn generation and editing via the Interactions API. To refine, pass the returned interaction id as previous_interaction_id on the next call; do NOT start a new interaction or re-send the image for each tweak. continue_last: true chains from this session's most recent interaction without threading the id. If a call times out client-side the generation usually still completes: the image and an <image>.json sidecar holding its interaction id land in the output dir, and continue_last: true still resumes it — look there before re-issuing, which bills a second generation. A chained 404 is re-anchored on the prior output and re-issued un-chained (chain_recovered); a second 404 means the interaction id was not the cause — check the model id / files uri. Output is JPEG. Local file inputs are confirmed first: a confirmation prompt where the client supports one; otherwise the first call returns a preview and a confirmToken, and only a repeat call with that token proceeds (see MCP_CONFIRM_MODE).

Inputs: input (required), async, model, images, +21 more.

gemini_list_filesA
Read-only

List files, images and photos currently uploaded to the Gemini Files API under this API key, with their reusable file_uri (files/<id>) references, MIME types and expiry times. Retention is ~48h, so an entry that has vanished has expired rather than failed.

Inputs: page_size.

gemini_list_modelsA
Read-only

List the Gemini image-generation models available to your API key (Nano Banana / Nano Banana Pro family), and the current default model.

Inputs: no named parameters.

gemini_music_generateA
Destructive

Generate music from a text prompt (mood, genre, instruments, structure, or lyrics inline) via a Lyria model: lyria-3-clip-preview (30s instrumental clip, default, cheapest), lyria-3.5 (full-length song with vocals) or lyria-3-pro-preview (longer-form). Output is MP3, written to disk (or returned inline). Single-turn: a track cannot be refined by a follow-up call, so put the whole brief in the prompt. Runs long — give it a max_wait_ms budget (or async: true + gemini_get_result on a local install), or raise timeout_ms. Needs a funded account. Local file inputs are confirmed first: a confirmation prompt where the client supports one; otherwise the first call returns a preview and a confirmToken, and only a repeat call with that token proceeds (see MCP_CONFIRM_MODE).

Inputs: prompt (required), async, model, images, +12 more.

gemini_token_usageA
Read-only

Token usage for this session so far — what every generation has cost in tokens, added up. Call it before and after a workflow and subtract to get that workflow's cost; call it after a single generation for that call's. Reports tokens AND an estimated USD cost, priced per call against each call's own model and stamped with the date its rates were read (override with GEMINI_RATE_CARD). Note there is no account-balance endpoint to query — Google Cloud is post-paid and its billing data lags by hours — so this is the accurate way to attribute spend to a call.

Inputs: reset.

gemini_upload_fileA

Upload a file — an image, reference photo, picture, screenshot, video or audio clip — to the Gemini Files API ONCE, and get back a reusable file_uri (files/<id>) to attach to later image, video or music generations. Keywords: upload, upload file, upload image, upload photo, attach, reference image, reference photo, file_uri, files api, image reference, reuse across calls. Use this instead of pasting base64 into a tool call: the reference is a short string, so no image bytes ever enter the conversation, and it can be reused across many generations until it expires (~48h). Provide exactly one of url (the server downloads it), data_base64, or path (a local file). A local path is confirmed first: a confirmation prompt where the client supports one; otherwise the first call returns a preview and a confirmToken, and only a repeat call with that token proceeds (see MCP_CONFIRM_MODE).

Inputs: url, path, r2_key, mime_type, +3 more.

gemini_video_generateA
Destructive

Generate a short video (~10s) via the Gemini omni model: text→video, image→video / reference→video (supply reference image[s]), interpolate between two stills (pass first frame then last frame as images), or continue a prior video (task: "edit" or "extend" + previous_interaction_id / continue_last; extensions add ~3-10s each, to ~40s total). Cost scales with resolution — draft at 360p, keep at 1080p/4k. Output is written to disk as MP4 (video has no inline MCP block). Video runs long — give it a max_wait_ms budget (or async: true + gemini_get_result on a local install), or raise timeout_ms. Needs a funded account. Local file inputs are confirmed first: a confirmation prompt where the client supports one; otherwise the first call returns a preview and a confirmToken, and only a repeat call with that token proceeds (see MCP_CONFIRM_MODE).

Inputs: prompt (required), task, async, model, +18 more.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4.3/5.0

    Scored across 13 tools

    Disambiguation4/5

    The four image-centric tools (gemini_image_generate, gemini_image_edit, gemini_image_set, gemini_interact) genuinely overlap, but the descriptions explicitly route between them (use interact for iterative work, edit for one-off edits, set for batches). Video and music tools are clearly distinct modalities, and get_result/token_usage/healthcheck have no ambiguity. Only the generate-vs-interact boundary remains a mild judgment call.

    Naming Consistency4/5

    All names share the gemini_ prefix and snake_case, so the set reads predictably. However, ordering is mixed: media tools use resource_action (image_generate, video_generate) while file tools use action_resource (upload_file, list_files), and a few tools are noun-only (healthcheck, token_usage). Minor deviation, not confusing.

    Tool Count5/5

    13 tools is well within the sweet spot and each earns its place: generation per modality (image/video/music), file lifecycle, async result retrieval, cost tracking, and healthcheck. No tool appears redundant or filler. The surface is appropriately scoped for a generative-media API server.

    Completeness4/5

    Coverage is strong: generation, iterative refinement, file upload/list/delete, async job retrieval, and token/cost accounting form a full lifecycle with no obvious dead ends. Minor gaps exist — gemini_list_models appears image-only (no video/music model listing) and there is no explicit job-cancel tool, though agents can work around both.

    Maintenance

    ActivityActive
    ResponsivenessUsually handled

    Related MCP Connectors

    Related MCP Servers