nano-banana-gemini
Drives Google's Gemini web app to generate images from prompts using a signed-in Google account, with no API key. Supports exact output sizing by generating at the closest native aspect ratio and cropping, and the upstream Flow mode can also use reference images.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@nano-banana-geminiGenerate a 16:9 image of a futuristic city at sunset"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
nano-banana-gemini-mcp
A fork of frannkurt/nano-banana-mcp (Apache-2.0, by Franco Escudero) that adds a second backend: the Gemini web app.
The original drives Google Flow. Flow isn't offered in every country, but gemini.google.com is, and it makes images with the same Nano Banana model. This fork gives you one MCP tool, generate_image, that works through Gemini instead. Free, no API key, uses your own Google account.
Not a Google product, not affiliated with Google. See the warnings at the bottom.
What was added
src/gemini.ts- drives gemini.google.com in a temporary chat (nothing piles up in your history). Finds buttons by icon names, not visible text, so any interface language works.src/gemini-server.ts- separate MCP entry point with onlygenerate_image, so agents never pick the Flow tools by mistake.src/autolaunch.ts- starts its own background Chromium with its own profile whenFLOW_CHROMIUM_PATHis set. No need to keep a browser open.scripts/gemini-smoke.mjs- one real generation without MCP, to check the setup.Small change in
src/browser.tsto hook in autolaunch. WithFLOW_CHROMIUM_PATHunset, the original Flow behaviour is untouched.
Related MCP server: google-flow-mcp
Setup (macOS, Node 20+)
git clone https://github.com/yourname/nano-banana-gemini-mcp.git
cd nano-banana-gemini-mcp
npm install
npm run build
npx playwright-core install chromiumGet the path of that Chromium (you'll use it twice):
node -e "import('playwright-core').then(m => console.log(m.chromium.executablePath()))"Sign in to Google once, in the profile the server will use. Close the window when Gemini shows the message box:
"<chromium path>" --remote-debugging-port=9333 --use-mock-keychain --no-first-run \
--user-data-dir="$HOME/.nano-banana-mcp/chromium-profile" https://gemini.google.comKeep --use-mock-keychain. The server launches Chromium with it, and the saved login only decrypts if both use the same flag.
Test it:
FLOW_CHROMIUM_PATH="<chromium path>" node scripts/gemini-smoke.mjs "a red apple on a white background"You should get OK ...png 1024x1024.
Add it to your MCP client (Claude Desktop: claude_desktop_config.json):
{
"mcpServers": {
"nano-banana-gemini": {
"command": "node",
"args": ["/absolute/path/to/nano-banana-gemini-mcp/dist/gemini-server.js"],
"env": { "FLOW_CHROMIUM_PATH": "<chromium path>" }
}
}
}Restart the client. Then ask it to generate an image.
The tool
generate_image(prompt, size?, aspect?, out_dir?, basename?, format?, fit?, background?)
sizelike"1200x630"gives an exact output size. It generates at the closest of 1:1, 3:4, 4:3, 9:16, 16:9 and crops to fit.Saves to
~/nano-banana-imagesby default and returns the file path plus a small preview.Requests run one at a time. A second call waits for the first.
Environment variables
Variable | What it does |
| Chromium binary. Setting it turns on the background browser. Required for this fork's setup. |
|
|
| Browser profile folder. Default |
| Debug port. Default |
| Where images are saved. |
| Max wait per image. Default |
Warnings
This automates the Gemini website, not an official API. It can break whenever Google changes the page, and it may go against Google's terms. Use a spare Google account.
The browser profile holds your Google login on disk. Never commit or share
~/.nano-banana-mcp.Only tested on macOS (Apple Silicon).
Gemini can refuse a prompt or hit a daily limit. The error text from the reply is passed back to you.
Everything below is the original README from upstream (Flow mode).
generate_image(prompt: "an orange fox on a white background", size: "1200x630")
-> images/an-orange-fox-on-a-white-background.jpg 1200x630 0 creditsEvery image in this README was generated by this server. The banner above, the crops below, and the logo renders further down. Nothing was touched up by hand.
Why this one is different
Every other image MCP server bills you. You register for an API key, attach a credit card, and pay per image — a few cents each, which quietly becomes real money once a model is iterating on a design and throwing away nine attempts out of ten.
This one doesn't, because it isn't calling a paid API at all. It drives Nano Banana, the image model inside Google Flow, through the web app you already have access to. Flow charges credits for video. Images cost zero.
API-based image MCPs | nano-banana-mcp | |
API key | Required | None |
Billing account | Required | None |
Cost per image | Cents each, and it adds up | $0.00 |
Setup | Register, key, billing, secret | Sign into Google in a Chrome window |
Exact pixel sizes | Rarely | Yes |
Reference images | Sometimes | Yes |
The trade-off is honest and worth stating: it needs a real Chrome window that you are signed into, so it can't run headless or in CI. That's the price of not having a bill.
What it solves
Flow generates in five fixed aspect ratios: 16:9, 4:3, 1:1, 3:4 and 9:16. Real design work almost never lands on one of them — an Open Graph card is 1200×630, a repo banner is 1456×180, an avatar is 400×400.
This server generates at the closest native ratio and crops to the exact size, using saliency detection so the crop
doesn't decapitate your subject. Ask for 1200x630, get a 1200×630 file.
What "exact size" does and doesn't mean. The model is not generating at your dimensions — Flow always returns its own native resolution, around 1 megapixel (1376×768 for 16:9, 1024×1024 for 1:1). The exact size is produced here, locally, by cropping and scaling that result. The file you get really is 1200×630; the pixels in it came from a 1376×768 render.
That's a genuine convenience when you're going down from native, which covers most web work. Going up it will still hand you the file you asked for — request 3000×3000 and you get 3000×3000 — but those extra pixels are interpolated, not generated. There is no more detail in them. The server prints a warning when this happens; if you need real resolution beyond native, upscale deliberately with a tool built for it.
One generation, three sizes. Same source image, cropped three ways — note how the crop follows the subject instead of blindly taking the centre:
|
|
1456x180 — repo banner
Reference images
Give it an image and the prompt stops describing what to create and starts describing what to change. Feed it a flat logo and ask for it letterpressed into cotton paper, or cast as a matte signage object:
Left: the source vector, handed in as a reference. Centre and right: two generations from it, four variants each, 0 credits, about a minute per batch.
generate_image({
prompt: "this logo letterpressed into thick warm off-white cotton paper, raking side light",
reference_images: ["assets/logo.png"],
count: 4
})
// iterating on the same reference? don't re-upload it
generate_image({
prompt: "same, but with a deeper impression and visible paper tooth",
reference_library_names: ["logo.png"],
count: 4
})Flow doesn't take a file straight into the composer: it uploads to the project library first, and you pick it from there. Both steps are handled for you, including the confirm click that actually attaches it. Any reference left over from a previous turn is cleared first — a forgotten one silently changes the image, and the result gets blamed on the prompt.
How it works
Flow has no public API. Its internal generation call is signed with a reCAPTCHA Enterprise token minted by the page's own JavaScript, so it cannot be replayed from outside the browser — and this project does not try to. That single constraint shapes the whole design.
So it does what a person would do: type into the composer and press Enter. What's different is how it reads the result.
It intercepts the page's own network response instead of watching the library for something new to show up. That response already carries the media id, the true dimensions and a signed URL, so there's no polling, no guessing which thumbnail is yours, and no ambiguity when several generations are in flight. The only fragile part left is typing the prompt.
One request, four responses. Ask for four variants and Flow doesn't return an array — it sends four separate HTTP responses, staggered by a couple of seconds. Waiting for "the next response" quietly drops three of them and looks exactly like an account limit. The collector listens to the whole stream and closes on whichever comes first: all expected images, a 20-second silence, or the hard timeout. It never discards what already arrived.
UI anchors are Material Symbols ligature names (crop_16_9, image, add_2) and numeric labels (16:9, x4).
Those are identifiers, not translatable text, so it behaves the same whether the interface is in English, Spanish or
Japanese.
The cost gate closes before sending. The server reads the cost Flow itself computes in its settings panel and
aborts if it exceeds FLOW_MAX_COST, which defaults to 0. The refusal happens while refusing is still free. If the
number can't be read, it doesn't send either — it won't guess.
Requirements
Node.js 20 or newer
Google Chrome
A Google account with access to Flow
That's the whole list. No API key, no cloud project, no billing account, no secret to rotate.
Install
git clone https://github.com/frannkurt/nano-banana-mcp.git
cd nano-banana-mcp
npm install
npm run buildSetup
1. Let the server reach Chrome
Recommended — your everyday Chrome (version 144 or newer). No second browser, your own session, extensions and tabs:
Open
chrome://inspect/#remote-debuggingand tick "Allow remote debugging for this browser instance". Below it Chrome should show the server running at127.0.0.1:9222.The first time the server attaches, Chrome asks whether to allow it. Accept. The server keeps that connection for the whole session, so it doesn't ask again on every image.
The server finds it on its own: Chrome writes the port to DevToolsActivePort inside its user-data folder, and the
server reads it there. Leave FLOW_CDP_URL unset for this.
Alternative — a separate Chrome with its own profile. Chrome won't open --remote-debugging-port on your
everyday profile, which is why this needs a profile of its own (it will look like a fresh Chrome, without your
extensions). If nothing is found through the option above, the server falls back to port 9222 on its own. The easiest
way is the bundled launcher (persistent, dedicated profile so you sign in only once):
npm run chromeIt opens flow.google.com in a dedicated profile (<userData>/nano-banana-flow-profile) with the debug port on,
without touching your everyday Chrome. Sign in once; the session persists for next time.
Or do it by hand, with a profile separate from your everyday one.
Windows
"C:\Program Files\Google\Chrome\Application\chrome.exe" --remote-debugging-port=9222 --user-data-dir="%USERPROFILE%\.nano-banana-mcp\chrome" https://flow.google.commacOS
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --remote-debugging-port=9222 --user-data-dir="$HOME/.nano-banana-mcp/chrome" https://flow.google.comLinux
google-chrome --remote-debugging-port=9222 --user-data-dir="$HOME/.nano-banana-mcp/chrome" https://flow.google.com2. Sign in and open a project
In that Chrome, sign in with your Google account and open a Flow project. The URL must end up at
flow.google.com/project/<id>.
Without an open project there is no composer, and without a composer nothing can be generated. The server remembers
the last project it worked in (~/.nano-banana-mcp/state.json): if Flow is open on its home page, or not open at
all, it takes a single tab back to that project.
3. Register the server
In Claude Code:
claude mcp add nano-banana --env FLOW_OUTPUT_DIR=./images -- node /path/to/nano-banana-mcp/dist/index.jsAdd --env FLOW_CDP_URL=http://127.0.0.1:9222 only if you want to force a specific Chrome instead of the automatic
choice.
Or by hand, in your MCP client's config:
{
"mcpServers": {
"nano-banana": {
"command": "node",
"args": ["/path/to/nano-banana-mcp/dist/index.js"],
"env": {
"FLOW_OUTPUT_DIR": "./images",
"FLOW_MAX_COST": "0"
}
}
}
}4. Check it
node scripts/doctor.mjsThat checks the browser, session, project, composer and balance in order, and stops at the first thing that's wrong with instructions for fixing it. Once it's clean, try a real generation:
node scripts/smoke.mjs "an orange fox on a white background" 1200x630Tools
flow_status
Connection state: session, account, open project, credit balance. Start here when something fails.
generate_image
Parameter | Type | Default | What it does |
| string | — | Image description, in any language |
| string | native | Exact output size, |
|
| derived from | Native ratio to generate at |
| 1–4 | 1 | How many variants |
| string[] | — | Local paths to use as references; uploaded and attached for you |
| string[] | — | Files already in the project library, attached without re-uploading |
| string |
| Destination folder |
| string | derived from prompt | Base filename |
|
|
| Output format |
|
|
|
|
| CSS color |
| Padding color when |
|
| — | Ask Flow's own upscaler for real detail beyond native (see below) |
Returns the saved paths, each media id, and a thumbnail of every result — so the model can see what came out and decide whether it's worth another try.
generate_batch
Generates several different prompts in one call, queued in the same Flow tab: up to 8 jobs, each with its
own optional size, aspect, basename, reference_images and reference_library_names. Shared out_dir,
format, fit, background and upscale.
Flow accepts a new prompt while the previous ones are still generating, so the tool sends them one after another without waiting, and collects everything at the end. No extra tabs are opened. Three prompts land in about 40 seconds.
One failed job doesn't sink the rest: you get the saved files that worked and a per-job error for the ones that didn't.
list_library
Lists the images in the project library, newest first: uploads (with the exact filename reference_library_names
expects) and generated images (with their prompt and media id). Read via the project API — no UI is touched. Filter
with only: uploaded, generated or all.
download_image
Fetches an existing image by media id, with optional cropping (size, fit, background). Useful for recovering
something generated earlier, or pulling several sizes out of the same original. Accepts upscale too.
upscale_image
Upscales an image that already exists in the open project, by media id, with Flow's own upscaler, and saves it
(out_file, optional size/fit/background). target is 2k (default) or 4k.
generate_video
Generates a video with Veo (text to video, 16:9 or 9:16) and saves it as .mp4. Video costs credits, so it
only runs when FLOW_MAX_COST is above the cost Flow quotes; otherwise it refuses before sending anything. The
result is downloaded at its original 720p (Flow's 1080p and 4K are upscales and are never chosen). Videos take a few
minutes.
Upscaling
Nano Banana delivers 1024x1024 in square and 1376x768 in landscape, and that is where real detail ends: a larger
size on its own only interpolates. Flow ships its own upscaler that reconstructs the image at 2K or 4K, and it is
the only thing that adds detail. Pass upscale: "2k" to generate_image or download_image, or call
upscale_image on a media id.
Native | 2K |
1376x768 | 2752x1536 |
1200x896 | 2400x1792 |
1024x1024 | 2048x2048 |
2K is free and takes about 10 s per image. 4K is offered only on paid plans; on a free account the menu entry is disabled and the tool says so instead of trying. Like generation, this goes through the interface (the upscale RPC is signed with a single-use reCAPTCHA token): the tool right-clicks the tile, picks Download → 2K and takes the result from the download the page itself starts. That means the image must belong to the project open in the Flow tab, and upscales run one at a time.
Configuration
Variable | Default | What it does |
| automatic | Force a Chrome debugging endpoint ( |
| Chrome's default folder | Where to look for |
|
| Where images are saved |
|
| Credit ceiling per generation |
|
| How long to wait for Flow to answer |
| system locale, else | Language of this server's messages: |
Languages
Two different languages meet in this project, and it's worth not confusing them.
Flow's interface language is whatever your Google account is set to, and this server never depends on it. It
anchors on Material Symbols ligature names (crop_16_9, add_2, image) and numeric labels (16:9, x4) — those
are identifiers, not copy, so they read the same in every locale. It never matches translatable text like "Add to
prompt". Tested against a Spanish interface; the anchors are language-independent by construction.
The one place that used to depend on it was reading the cost. That's now taken from the panel's structure — the leaf
<a> element holding the number — instead of matching the word next to it. It matters because the cost gate refuses
to send when it can't read the number, so a German user seeing "0 Punkte" would have been blocked from generating
anything at all. Safe, but useless.
This server's own messages — errors, warnings, status, and the MCP tool descriptions your model reads — come in
English and Spanish. It picks from FLOW_LANG, falling back to your system locale, defaulting to English.
FLOW_LANG=es node dist/index.jsCode comments stay in Spanish. That's a choice about how this codebase is written, not something a user ever sees.
Generating several at once: one tab, queued
The server works in a single Flow tab and never opens extra ones. It doesn't need to: the composer frees up as soon as a prompt is sent, and Flow keeps generating it while you send the next one.
Which image belongs to which prompt: Flow draws each submission above the previous one, and the images take their submission's place even if they finish in a different order. So, in screen order, the last prompt's images come first, and the queue hands them out from the end. Reference images are uploaded before the queue starts, because an uploaded image shows up in the grid just like a generated one.
The generate_batch tool does this for you. For scripts, the same queue is available as a library API:
import { generateQueue } from "nano-banana-mcp/dist/generate.js";
const { results } = await generateQueue([
{ prompt: "a red apple on a white table", aspect: "1:1", count: 1 },
{ prompt: "a blue vintage car on an empty street", aspect: "16:9", count: 2 },
{ prompt: "macro of these veneer sheets", aspect: "4:3", count: 1, referenceImages: ["ref.jpg"] },
]);
// results[i].images → that job's images; results[i].error → why it gave noneThe UI is driven in the foreground (Chrome freezes requestAnimationFrame in background tabs, and React stops
responding there), so the Flow tab is brought to the front while prompts are being sent.
On cost
Images in Flow cost 0 credits. Video costs, and it costs a lot.
The gate described above is what keeps that true by accident rather than by trust: the server reads Flow's own quoted cost and refuses to send anything above the ceiling.
Roadmap
Video is in (generate_video, Veo), scenes are not yet. Video is where the cost gate stops being a formality: it
only runs with an explicit, non-zero FLOW_MAX_COST above Flow's quoted cost, and it downloads the original 720p
(never the paid upscales). Nothing that spends credits will ever run because a default let it.
Privacy and credentials
It never handles a credential. It attaches to a session you opened yourself.
The balance is read with a token that is fetched and used inside the tab. That token never crosses into this process, is never written to disk, and is never logged.
Nothing is sent anywhere except Google Flow.
Troubleshooting
Run node scripts/doctor.mjs first — it checks the whole chain in order and stops at the first thing that's wrong.
The messages below are the English ones; with FLOW_LANG=es you'll see the Spanish equivalents.
On the new Flow interface (flow.google.com). It's supported: images, upscaling, references, the queue and video were verified against it. On it, the credit balance can't be read anymore (the session endpoint is gone), so
flow_statusshows it as unknown; the signed-in account is read from the page instead.
"Couldn't connect to Chrome at …" — with your everyday Chrome: open chrome://inspect/#remote-debugging, check
that "Allow remote debugging for this browser instance" is ticked and that it shows the server running, and accept the
prompt Chrome shows when the server attaches. With a separate Chrome: it isn't running with
--remote-debugging-port=9222, or you launched it without its own --user-data-dir and it attached to an existing
instance. Close every window of that profile and relaunch with the command above.
"No Flow (flow.google.com) tab is open in that Chrome" — open Flow in that Chrome window.
"Couldn't find the prompt composer on the page" — you're on the project list, not inside a project. The URL must
contain /project/.
"I couldn't read what this generation would cost, so I'm not sending it" — Flow's interface changed. If the text the error quotes mentions "Confirm before generating", see the note on the new interface above. Otherwise the error includes the text it did read; open an issue pasting it and it gets fixed in one place. Either way this is a refusal, not a crash: nothing was sent and nothing was spent.
"Couldn't find X in the library picker" — the reference file isn't in this project's library, or the name doesn't match. Check the exact filename as it was uploaded.
"Selected X in the library but it didn't attach to the composer" — the picker's confirm button moved. Open an issue with the Flow's interface changed template.
It generated but the crop is wrong — try fit: "contain", or pass an explicit aspect closer to your final size
instead of letting it be derived.
Limitations
Images only. Video and scenes are in development, not available yet.
Needs a visible, signed-in Chrome window. It does not work headless or in CI.
It depends on Flow's interface to type the prompt. Google can change it; when they do, the submit step breaks and needs adjusting.
Not a Google product. Not endorsed by or affiliated with Google.
Contributing
Yes, please — see CONTRIBUTING.md. The most valuable contribution is a fix for a Flow UI change, and that guide explains how to diagnose one properly instead of guessing at selectors.
Also welcome: setup reports from macOS and Linux (this was built on Windows), and testing against interfaces in languages other than Spanish and English.
By participating you agree to the Code of Conduct. Security issues go here, privately.
License
Apache-2.0. See LICENSE and NOTICE.
Not a Google product. Not endorsed by or affiliated with Google.
Available Tools
7 toolsdownload_imageA
Download an image that already exists in Flow by its media id, with optional cropping to an exact size.
| Name | Required | Description | Default |
|---|---|---|---|
| fit | No | cover | |
| size | No | Exact size, "WIDTHxHEIGHT" format. | |
| upscale | No | Ask Flow to upscale the result: "2k" (free, about 2x the native size, ~10 s per image) or "4k" (paid plans). It is the only way to get real detail beyond native; a larger size alone just interpolates. | |
| media_id | Yes | Media id, as returned by generate_image. | |
| out_file | Yes | Output path. The extension decides the format. | |
| background | No | Padding color for fit="contain", as a CSS color ("#0f172a", "black"). White by default. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description bears the full disclosure burden. It establishes that this is a read-from-Flow/write-to-disk operation by naming out_file as required, but says nothing about overwrite behavior, error cases (missing media id), latency, or that 4k upscaling is paid — those details live only in the schema property text.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler; the core action and its optional behavior are both stated before any detail. Nothing superfluous is present.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With six parameters, no annotations, and no output schema, the description is somewhat thin: it never states that the result is written to out_file on disk or what a successful call returns. The schema compensates for parameter-level meaning, but the absence of any behavioral disclosure leaves the definition only minimally complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 83%, so the schema already documents media_id, size, out_file, upscale, and background thoroughly. The description only adds the framing that cropping is 'optional' and targets an 'exact size', which slightly reinforces size/fit semantics but does not meaningfully extend what the schema says.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb (download) and resource (an image that already exists in Flow) and scopes it to lookup by media id, which implicitly distinguishes it from generate_image. It does not name the sibling upscale_image, even though the schema exposes an 'upscale' parameter, leaving some ambiguity about which tool to pick for upscaling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
"already exists in Flow by its media id" implies the image must be produced first (e.g. via generate_image) and that media_id is the selector, which is useful usage context. However, there is no explicit when-to-use/when-not statement and no guidance on choosing between this tool's 'upscale' option and the separate upscale_image sibling.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
flow_statusA
Check the connection to the Google Flow Chrome window: signed-in session, account, open project and credit balance. Call this first when something fails.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden of behavioral disclosure. It reveals that the tool checks connection-related details and implies a read-only operation, but it does not describe side effects, error handling, or return format. It adds some context beyond a bare 'check status' but lacks deeper behavioral specifics.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise: one sentence specifying the check and one giving usage guidance. It is front-loaded with the action and scope, with no redundant wording or unnecessary details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the simplicity (no params, no annotations) and lack of output schema, the description is somewhat complete but misses return value information. It tells the agent what is checked and when to call it, but it does not explain what the tool returns or how to interpret the result, which would be valuable since there is no output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, and the input schema is empty. The baseline for 0 params is 4, and the description does not need to explain parameter semantics. It appropriately focuses on the tool's purpose rather than parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool checks a connection to the Google Flow Chrome window, detailing specific aspects (signed-in session, account, open project, credit balance). This specific verb-resource combination distinguishes it from sibling tools like generate_image and download_image, which serve entirely different purposes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit guidance: 'Call this first when something fails.' This tells the agent when to use the tool, but it does not mention when not to use it or suggest alternative tools. Still, the clear directive covers a key usage scenario.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
generate_batchA
Generate several DIFFERENT prompts in one call. All of them go to the SAME Flow tab, queued: each prompt is sent while the previous ones are still generating, and everything is collected at the end. No extra tabs are opened. Up to 8 jobs; each can have its own size, filename and reference images. Optional upscale (2k) applies to all.
| Name | Required | Description | Default |
|---|---|---|---|
| fit | No | How to fit into `size`: "cover" crops to fill, "contain" fits everything and pads the edges. | cover |
| jobs | Yes | The jobs to queue. Each needs a prompt; size (e.g. 1200x630), aspect, basename, reference_images and reference_library_names are optional per job. | |
| format | No | Output format. | jpg |
| out_dir | No | Destination folder. Defaults to FLOW_OUTPUT_DIR. | |
| upscale | No | Ask Flow to upscale the result: "2k" (free, about 2x the native size, ~10 s per image) or "4k" (paid plans). It is the only way to get real detail beyond native; a larger size alone just interpolates. | |
| background | No | Padding color for fit="contain", as a CSS color ("#0f172a", "black"). White by default. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does meaningful work: it discloses the queuing model, that all jobs share one Flow tab, that no extra tabs open, the 8-job ceiling, and that upscale applies globally. It leaves open what happens if one job fails mid-batch and whether partial results are returned, which matters for a batch mutation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short sentences, front-loaded with the core purpose, then the queuing mechanics, then limits. No filler; the capitalized DIFFERENT and SAME efficiently carry the key constraints.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description's note that 'everything is collected at the end' is doing necessary work, but it does not say what the return looks like (paths, per-job status, filenames). For a tool with a global option and per-job overrides, that is a modest gap rather than a fatal one.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents every parameter including fit, format, out_dir, background and the per-job fields. The description adds one genuinely useful cross-parameter fact, that 'upscale applies to all' jobs rather than per job, and notes per-job independence for size, filename and reference images; otherwise it restates the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (generate multiple prompts) and adds a distinguishing qualifier: 'several DIFFERENT prompts in one call' versus the single-prompt sibling. It never names generate_image explicitly, so the contrast with the sibling is inferred rather than stated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear context for when this tool is appropriate: multiple different prompts that should share one Flow tab and be queued rather than run sequentially. It stops short of explicit exclusions such as 'use generate_image for a single prompt' or guidance on when upscale_image should be called separately instead.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
generate_imageA
Generate one or more images with Google Flow and save them to disk. You can ask for an exact pixel size (e.g. 1200x630): it generates at the closest native aspect ratio and crops to the size you asked for. Images cost no credits.
| Name | Required | Description | Default |
|---|---|---|---|
| fit | No | How to fit into `size`: "cover" crops to fill, "contain" fits everything and pads the edges. | cover |
| size | No | Exact output size, "WIDTHxHEIGHT" format, e.g. "1200x630". Omit to use the native size. | |
| count | No | How many variants to generate (1 to 4). | |
| aspect | No | Native aspect ratio. If omitted and `size` is given, the closest one is chosen. | |
| format | No | Output format. | jpg |
| prompt | Yes | Image description. In any language. | |
| out_dir | No | Destination folder. Defaults to FLOW_OUTPUT_DIR. | |
| upscale | No | Ask Flow to upscale the result: "2k" (free, about 2x the native size, ~10 s per image) or "4k" (paid plans). It is the only way to get real detail beyond native; a larger size alone just interpolates. | |
| basename | No | Base filename. Derived from the prompt by default. | |
| background | No | Padding color for fit="contain", as a CSS color ("#0f172a", "black"). White by default. | |
| reference_images | No | Local paths to images to use as references. Flow starts from them instead of from scratch, so the prompt describes what to change rather than what to create. Useful for versioning a logo, iterating on a previous result, or holding a style across pieces. | |
| reference_library_names | No | Filenames ALREADY in the project library, to attach without uploading them again. Use this when iterating on the same reference: re-uploading the same file only leaves duplicate rows in the library and makes each generation slower. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does disclose two valuable traits: images cost no credits and exact-size requests are achieved by native-ratio generation plus cropping. It omits important behavior for a write-to-disk tool: authentication requirements, whether existing files are overwritten, generation latency, failure modes, and what the tool returns.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with what the tool does and what it produces, followed by the most decision-relevant caveat (the crop behavior). No filler or repetition of schema content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a twelve-parameter tool with no output schema and no annotations, the description is thin at the edges: it does not say what is returned (file paths, a confirmation, a count), how out_dir/FLOW_OUTPUT_DIR behaves when missing, or how reference_images interact with prompt length limits. The core workflow is explained adequately, but an agent still has open questions before calling it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is already 100%, so the baseline is 3, but the description adds genuine cross-parameter meaning the schema does not: the interaction between size and aspect (closest native ratio is chosen automatically, then cropped). That is real interpretive value beyond the per-field descriptions, though it covers only two of twelve parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("Generate one or more images with Google Flow") plus the side effect ("save them to disk"), which clearly separates it from siblings like generate_video, upscale_image, and download_image. It stops short of naming any sibling explicitly, so differentiation is inferred rather than stated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives useful conditional guidance for the size parameter ("ask for an exact pixel size... generates at the closest native aspect ratio and crops") and a cost note. However, it never says when to prefer this over generate_batch, upscale_image, or download_image, and no prerequisites or exclusions are given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
generate_videoA
Generate a video with Google Flow (Veo) and save it to disk. UNLIKE images, video COSTS CREDITS: it only runs when the FLOW_MAX_COST ceiling is raised above the quoted cost; otherwise it refuses before generating. Text-to-video from a prompt; pick an aspect (16:9 or 9:16).
| Name | Required | Description | Default |
|---|---|---|---|
| aspect | No | Aspect ratio for the video. Flow's Veo supports 16:9 and 9:16. Defaults to 16:9. | 16:9 |
| prompt | Yes | Image description. In any language. | |
| out_dir | No | Destination folder. Defaults to FLOW_OUTPUT_DIR. | |
| basename | No | Base filename. Derived from the prompt by default. | |
| out_file | No | Output path. The extension decides the format. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are supplied, so the description carries the full burden, and it does disclose the most consequential behavior: video consumes credits and a cost ceiling gates execution with a pre-generation refusal. It omits other traits an agent would want for a video job — expected latency/async behavior, what the response returns, and error handling after the quote passes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the purpose, then the credit risk, then the input shape — no filler. Capitalized emphasis on COSTS CREDITS and FLOW_MAX_COST is the only styling and it correctly flags the blocking information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no annotations and no output schema, the description does the heavy lifting on the one risk that matters (credit spend and the refusal gate) and states the input modality and format choice. For a paid long-running generation tool, a note on where the result lands or that the call may be slow is the remaining gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all five parameters including the aspect enum, and the description only restates 'pick an aspect (16:9 or 9:16)'. It adds no meaning for out_dir, basename, or out_file, notably not how the extension in out_file interacts with format selection.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Sentence one gives a specific verb (generate) plus resource (video) plus destination behavior (save to disk) and names the provider (Google Flow/Veo). Sentence three further narrows scope to text-to-video with an aspect choice, and the 'UNLIKE images' clause separates it from the sibling generate_image without the agent needing to open another schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states a concrete precondition for invocation: the tool only runs when FLOW_MAX_COST is raised above the quoted cost, and otherwise refuses before generating — that is real when-to-use/when-it-will-fail guidance. It also implicitly routes image work elsewhere, though it never names generate_image or explains when a still image is preferable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_libraryA
List the images in the Flow project library: uploads (reusable via reference_library_names without re-uploading) and generated images (re-downloadable by id with download_image).
| Name | Required | Description | Default |
|---|---|---|---|
| only | No | Filter: "uploaded" (reference uploads), "generated", or "all". | all |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are supplied, so the description must carry the behavioral load; "List" implies a safe read, which is the main trait disclosed. It does not mention pagination, result ordering, permissions, or size limits — meaningful gaps for a library listing that could be large.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single sentence with zero waste, front-loading the verb and resource before parenthetical clarifications of each category. Nothing is repeated or padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-optional-parameter list tool with no output schema, the description covers what is returned and how each category is consumed downstream. The remaining gap is return-shape and pagination behavior, which is minor given the tool's simplicity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single enum parameter is fully documented in the schema, so the baseline applies. The description reinforces the meaning of the "uploaded" and "generated" categories by explaining what each contains, but adds no syntax or edge-case detail.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ("List") and resource ("images in the Flow project library") and then enumerates the two content categories returned: uploads and generated images. It also implicitly differentiates from the download_image sibling by noting generated images are re-downloadable there rather than here.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete downstream context for the results — uploads can be reused via reference_library_names without re-uploading, generated images can be fetched with download_image by id. It stops short of explicit when-not-to-use or prerequisite guidance, but the usage intent is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
upscale_imageB
Upscale an image that already exists in the open Flow project, by its media id, and save it to disk. 2K is free.
| Name | Required | Description | Default |
|---|---|---|---|
| fit | No | cover | |
| size | No | Exact size, "WIDTHxHEIGHT" format. | |
| target | No | Ask Flow to upscale the result: "2k" (free, about 2x the native size, ~10 s per image) or "4k" (paid plans). It is the only way to get real detail beyond native; a larger size alone just interpolates. | 2k |
| media_id | Yes | Media id, as returned by generate_image. | |
| out_file | Yes | Output path. The extension decides the format. | |
| background | No | Padding color for fit="contain", as a CSS color ("#0f172a", "black"). White by default. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must carry the behavioral load: it does disclose the write side effect ('save it to disk') and a cost fact ('2K is free'). It omits whether an existing out_file is overwritten, what permissions or project state are required, and any failure behavior, leaving meaningful gaps for a mutation tool with zero annotation coverage.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with the operation, scope, and output front-loaded; '2K is free' is terse but earns its place by flagging cost. Slightly clipped phrasing ('2K is free.') reads as a fragment rather than a fully formed note, but nothing is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 6-parameter tool with no annotations and no output schema, the description covers what it does, the prerequisite, and that results land on disk (partly compensating for the missing output schema). It still leaves the semantics of fit/size/background and any return value to the schema, which is adequate but not fully self-contained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 83%, so the schema already explains media_id, out_file, size, target, fit, and background in detail. The description only reinforces media_id ('by its media id') and the disk-output meaning of out_file; it adds nothing about the pricing/size/fit interplay that the schema itself documents. Baseline 3 applies when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Upscale an image'), scopes it to images already in the open Flow project, names the lookup key (media id), and states the outcome (saved to disk). It implicitly distinguishes itself from generate_image (new images) and download_image (fetching), though it never names a sibling outright.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Upscale an image that already exists in the open Flow project' implies a prerequisite (the media must already exist, presumably from generate_image), and '2K is free' gives a cost-based decision hint. There is no explicit when-not guidance, no mention of what to do if the media id is missing, and no routing to alternatives such as regenerating at higher resolution.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
7 tool updates
v0.4.0- First observed
download_image - First observed
flow_status - First observed
generate_batch - First observed
generate_image - First observed
generate_video - First observed
list_library - First observed
upscale_image
TDQS
Scored across 7 tools
Most tools target clearly distinct actions: status check, single-image generation, download, upscale, library listing, batch, and video. The only mild overlap is between generate_image (which can already produce 'one or more images') and generate_batch (several different prompts), so an agent could occasionally hesitate over which to pick.
Six of seven names follow a clean verb_noun snake_case pattern (generate_image, download_image, upscale_image, list_library, generate_batch, generate_video). The outlier is flow_status, a noun phrase rather than an action, but it remains readable and unambiguous.
Seven tools is well-scoped for a browser-automation image/video generation server, with each tool covering a distinct step in the workflow (diagnose, list, generate, batch, upscale, download, video). Nothing feels padded or missing at the count level.
The lifecycle is largely covered: connection diagnostics, library inspection, generation (single, batch, video), upscaling, and retrieval by media id. The notable gap is there is no tool to upload a new reference image into the Flow library, even though reference images are a first-class concept, forcing the agent back to the UI.
Maintenance
Related MCP Connectors
Generate images with your own ChatGPT subscription (Plus, Pro or Team), without spending API credits
Let AI agents use your real, signed-in Chrome: tabs, clicks, forms, screenshots and video.
11Image and video AI tools and your own pipelines, run from any AI assistant.
Generate images, GIFs, videos, and PDFs from HTML, URLs, or templates — from your AI agent.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables image generation using Google Gemini models (flash/pro) with support for multiple sizes, reference images, and access control via Google OAuth and email allow-lists.1-
- AlicenseNot gradedqualityCmaintenanceEnables generating images and videos in Google Flow through an automated browser session using your Google AI Pro subscription, without API keys or third-party credit fees.120 npm2MIT
- AlicenseAqualityBmaintenanceEnables image generation and editing through the Gemini web app using your own browser session cookies, avoiding API keys and per-image billing.231MIT
- AlicenseAqualityCmaintenanceLets AI agents generate images in Google Flow by driving the real web app in a Chrome window you sign into once, selecting the model, aspect ratio, and image count from a prompt. Results can be downloaded at 1K, 2K, or 4K, all without an API key.4MIT