Skip to main content
Glama

generate_image

Generate an image from a text prompt via Google Flow.

model — pass ONE of these exact ids (from GET v1/flow/models, verified 2026-07-25):
  BELUGA       = "Nano Banana 2"      — the DEFAULT, ~30s (legacy id NARWHAL is accepted as an alias)
  GEM_PIX_2    = "Nano Banana Pro"    — highest quality, ~40s, has a separate DAILY
                                        per-account quota (429 rotates accounts)
  HARBOR_SEAL  = "Nano Banana 2 Lite" — ~40s
Anything else is rejected with HTTP 400 — there is no silent fallback, so a wrong id
wastes a round trip, not credits. Do NOT guess names like "nano_banana_pro": that is
the model FAMILY key from the config, not the id the generate call takes.

image_inputs: mediaIds from prior generations, edit-in-place (keeps them pixel-exact).
control_images: up to 10 base64 image bytes (no data: prefix) of a locally rendered layout/control
image — uploaded first, then prepended to image_inputs so the generator follows an exact
spatial layout instead of prose. For whole-scene layout control prefer generate_scene.

seed: 1..900000, fixes the generation so the same request returns the same image. Omit
for a random seed. Needed to compare two prompts, two models or two control images
honestly — without it every run is a fresh roll and the difference you are measuring
drowns in noise. Measured 2026-08-09: with an UNCHANGED control image a fixed seed
reproduces the frame to ~0.1%; once the control image changes, the seed no longer keeps
the character — for that use image_inputs with a reference frame's mediaId.

project_id: put the result into a project made with create_project instead of the
account's default one — one project per end client keeps their work separate. Omit it
and nothing changes from before.

include_preview: ON by default since 2026-08-21 — a generated image nobody can see
in the chat is half a result. Pass False to get the plain dict back and nothing else
(worth doing in a loop of many generations, where the previews would fill the
context). When on and the job finished with at least one url, the call returns the
usual result dict, a short card naming the parameters actually used, and a small
compressed JPEG (long side capped at 768px, ~100-160KB once base64-encoded) as an
inline image content block, so a human can actually see the result without leaving
the chat. This is deliberately a shrunk preview, never the original — the real Flow
image is ~0.5MB (~740KB in base64), enough to burn a whole tool call's worth of a
client's context budget on its own. The preview is for EYES ONLY: urls/media_ids
stay the authoritative result in both modes, and every downstream call (upscale_image,
image_inputs edit-in-place, ...) must keep using media_ids, never the preview bytes.
If the preview download/shrink fails for any reason, this silently falls back to the
plain (no-preview) result instead of failing the whole call.

SAVE THE RESULT INTO THE USER'S PROJECT. A finished job also carries `download_urls`
(plain URLs, no auth header needed) and `save_as` (the filenames to use). Unless the
user said otherwise, write them to ./media/<save_as> in their working directory and
tell them the path. The server keeps its own copy, but only the file in their project
is theirs: our copy can be reclaimed when the disk fills, and the URLs expire within
the hour. Downloading costs no credits and no quota.

Returns {"urls": [...], "media_ids": [...]} when done, or a job_id to poll
with check_job if it's not ready within ~60s (rare for images unless the
device is cold). With the default include_preview=True and a finished result,
returns [that dict, <card>, <inline image>] instead — see include_preview above.
idempotency_key: optional, any string unique to this logical request (e.g. a uuid).
  Repeating a call with the same key within 24h returns the SAME job instead of a
  new one — use it when you may retry after a timeout or a busy error.

Input Schema

NameRequiredDescriptionDefault
seedNo
modelNoBELUGA
aspectNoIMAGE_ASPECT_RATIO_LANDSCAPE
promptYes
project_idNo
image_inputsNo
control_imagesNo
idempotency_keyNo
include_previewNo

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • addedInput schema / properties / idempotency_key
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "title": "Idempotency Key"
      +}
  2. Changed1 schema field changed
    • changedInput schema / properties / aspect / enum
      Previous value: -[
      -  "IMAGE_ASPECT_RATIO_LANDSCAPE",
      -  "IMAGE_ASPECT_RATIO_PORTRAIT",
      -  "IMAGE_ASPECT_RATIO_SQUARE"
      -]New value: +[
      +  "IMAGE_ASPECT_RATIO_LANDSCAPE",
      +  "IMAGE_ASPECT_RATIO_PORTRAIT",
      +  "IMAGE_ASPECT_RATIO_SQUARE",
      +  "IMAGE_ASPECT_RATIO_LANDSCAPE_FOUR_THREE",
      +  "IMAGE_ASPECT_RATIO_PORTRAIT_THREE_FOUR"
      +]
  3. Changed2 schema fields changed
    • changedInput schema / properties / model / default
      Previous value: -"GEM_PIX_2"New value: +"BELUGA"
    • changedInput schema / properties / model / enum
      Previous value: -[
      -  "NARWHAL",
      -  "GEM_PIX_2",
      -  "HARBOR_SEAL"
      -]New value: +[
      +  "BELUGA",
      +  "GEM_PIX_2",
      +  "HARBOR_SEAL"
      +]
  4. Changed1 schema field changed
    • changedInput schema / properties / model / default
      Previous value: -"NARWHAL"New value: +"GEM_PIX_2"
  5. First observed

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes far beyond the annotations: per-model latency, a separate daily per-account quota on GEM_PIX_2 with 429 account rotation, HTTP 400 on bad ids with no silent fallback, ~0.1% reproduction with a fixed seed, URL expiry within the hour, and server copies subject to reclamation. Crucially it also discloses silent degradation paths — preview failure falls back to the plain result rather than erroring, and a slow job returns a job_id instead of blocking.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads purpose, then walks parameters in a stable order with the operational save instruction placed after them. Almost every sentence carries non-obvious information, but it is long and occasionally discursive ("worth doing in a loop of many generations, where the previews would fill the context"), and the all-caps save paragraph is stylistically heavy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 9-parameter generative tool with no output schema, it covers return shapes ({urls, media_ids} or job_id, plus the three-block preview form), polling handoff, file persistence, and preview-vs-media_id authority. The only meaningful omission is aspect ratio handling, which is a parameter issue rather than a missing call-critical behavior.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema coverage the description carries the full burden and mostly succeeds: it gives exact model ids with aliases, destination semantics, and rejection behavior, explains seed ranges plus why a seed is needed for honest comparison, and defines image_inputs vs control_images (mediaIds vs base64 bytes without data: prefix, up to 10) and idempotency_key's 24h window. The notable gap is `aspect`, which is never mentioned despite being an enum parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource+provider ("Generate an image from a text prompt via Google Flow") and immediately differentiates scope by routing whole-scene layout work to generate_scene. An agent can distinguish it from generate_character_image or generate_with_face without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit routing to siblings: control_images are for spatial layout but "For whole-scene layout control prefer generate_scene", and image_inputs with a reference frame's mediaId is named as the fix when seeds stop holding the character. create_project, check_job, and upscale_image are each given a condition for use. It stops short of saying when to use this tool versus generate_character_image or generate_with_face, which is the main unresolved fork among siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.