google-flow-mcp
by H0wZy
README.md
# google-flow-mcp
MCP server that generates **images and video on [Google Flow](https://labs.google/flow)**
through browser automation, so you can use your own **Google AI Pro** subscription
instead of paying per-credit services. Ships with a Claude Code skill.
Validated end-to-end: images (Nano Banana / Imagen) and video (Veo 3.1 / Omni Flash)
are generated in a real Flow project and downloaded to disk.
> Adapted and hardened for the current agent-first Flow UI (and Windows) from
> [TMSSS05/google-flow-browser-mcp](https://github.com/TMSSS05/google-flow-browser-mcp).
>
> This repository is a fork of
> [GabrielGargiuloDev/google-flow-mcp](https://github.com/GabrielGargiuloDev/google-flow-mcp)
> (MIT, see `LICENSE`), maintained here because upstream stopped working when Google
> moved Flow to `flow.google.com` in 2026-09. See [Fork changes](#fork-changes).
## flow_generate — the agent-free path
Flow's prompt bar has an **Agent** chip. Pressed, a language model reads the prompt,
rewrites it and picks the parameters; ratio and model are account-wide defaults and no price
is shown anywhere before the spend. Released, the bar exposes its own control panel — mode,
ratio, model, resolution, duration, count — and prints the exact credit cost of the next
click.
`flow_generate` drives the released state and is the preferred tool. `flow_generate_image`
and `flow_generate_video` remain for the agent path.
```jsonc
// Costs nothing: configures, reads the price off the page, returns.
{ "prompt": "a red bicycle against a yellow brick wall",
"mode": "image", "ratio": "9:16", "model": "Nano Banana Pro", "count": "x1" }
// -> { "credits_required": 0, "configured": "Nano Banana Pro · crop_9_16 · x1", ... }
// Same call plus auto_confirm submits that exact configuration.
{ "...": "...", "auto_confirm": true }
```
What it buys:
- **The price before the spend.** Read from the panel, so `auto_confirm: false` is a real
quote and asking never submits. Images are 0 credits; a 720p/10s/x1 video is 15.
- **Parameters that are per call and verified.** Every toggle carries `aria-checked` and is
read back after clicking, so a parameter that did not take throws instead of being
reported as applied.
- **The prompt reaches the model verbatim** — nothing rewrites it, and the imperative
wrapper the agent path needs is gone.
Three defects found while building it, all of which also affect the agent path:
- `createNewProject` ran its "did Flow ask for a project name?" step unconditionally. Inside
a project the only `[contenteditable]` is the **prompt box**, and its confirm list included
`[type="submit"]` — the generate button. So every new project silently generated an extra
image captioned with the project name. Free for images; **15 credits a call for video.**
- Taking the first media that appears after submitting returned a valid, correctly sized,
entirely unrelated image — the spurious generation above landed first. The scan now waits
for the set to stop growing.
- The same asset is served at several signed URLs, so comparing whole URLs downloaded one
image twice. Identity is now the media id (`mediaId` in `src/utils/media-urls.js`).
Each downloaded file is reported with the title Flow gave its tile, which is what says
whether the output answered the prompt.
## Fork changes
Upstream was written against `labs.google/fx/tools/flow` and no longer runs: Google moved
Flow to its own domain and changed how media is served. Every fix below was measured against
the live app, not inferred.
| # | Broken upstream | Fix |
|---|---|---|
| 1 | `logger.info` wrote to **stdout**, corrupting the MCP JSON-RPC channel | log to stderr |
| 2 | `labs.google/fx/tools/flow` now redirects to `flow.google.com` | `flowUrl` config + host checks accept both |
| 3 | Download endpoint `labs.google/fx/api/trpc/media.getMediaUrlRedirect` is **gone** (404 / CORS) | fetch the media URL directly on the session cookie |
| 4 | Media URLs no longer carry a uuid | `src/utils/media-urls.js` matches `flow-content.google/` (fresh generations) and `flow.google.com/asb/` (thumbnails) |
| 5 | `isVisible()` does not wait, so a late-rendering Angular button read as absent | `waitFor({ state: 'visible' })` |
| 6 | Aspect ratio was accepted as an argument and silently ignored — a 9:16 request returned 1024x1024 | applied in the Settings panel, and the result reports whether it landed |
The result payload also reported `ratio`, `model_used` and `credits_consumed` as claims rather
than measurements. They now say what actually happened, including "unknown" where the UI
exposes no number.
**Locale:** set `flowUrl` to `https://flow.google.com/?hl=en`. Without `hl=en` the UI renders
in the account's language and every English selector misses. Upstream's French/Italian
selectors are unnecessary with the override.
## What it does
Playwright connects over the Chrome DevTools Protocol to a dedicated Chrome that is
logged into your Google account. It drives Flow's agent to generate media and
downloads the result through the authenticated session. **No API keys, no password
handling** — it uses your existing browser session.
Tools (17): `flow_connect`, `flow_status`, `flow_account_check`, `flow_discover_ui`,
`flow_generate_image`, `flow_generate_video`, `flow_download_latest`, character/scene
tools, `flow_use_grid_architect`, `flow_screenshot`, `flow_queue_status`, …
## ⚠️ Terms of Service
This is **unofficial browser automation**. There is no official Google API for Flow.
The launcher starts Chrome directly so `navigator.webdriver` is false, which is an
explicit anti-bot measure. Automating Google properties can violate Google's Terms of
Service and may put your account at risk. **Use at your own risk, on your own account.**
## Requirements
- Node.js ≥ 18
- Google Chrome (Chrome 149+ needs Playwright ≥ 1.61.1, already pinned)
- A Google account with access to Flow (Google AI Pro recommended)
## Setup
```bash
npm install
cp config/flow.config.example.json config/flow.config.json
# edit config/flow.config.json → set expectedAccount and chromeUserDataDir
```
Start the dedicated Chrome (idempotent — launches only if needed):
```powershell
powershell -File scripts/ensure-flow-chrome.ps1
```
First run: in that Chrome window, sign in to your Google account **and** click
**"Sign in to Flow"** on labs.google (Flow uses a separate sign-in). The session is
saved in the dedicated profile and reused.
Register the server with your MCP client (Claude Code, etc.):
```json
{
"mcpServers": {
"google-flow": { "type": "stdio", "command": "node", "args": ["<path>/src/index.js"] }
}
}
```
Restart the client afterwards (the server loads into memory at startup).
## Notes that matter
- **Images are effectively free** against the monthly Flow credit pool; **video
consumes credits** (Veo 3.1 Lite ~10, Fast ~20, Quality ~100; Omni Flash ~15-30 of
~1000/month). Video shows a credit-confirmation dialog which the server approves.
- **Model/duration must be a valid combo** or Flow's agent asks for clarification and
nothing generates (e.g. Veo 3.1 Lite is 8s-only on the Pro plan; Omni Flash 4-10s).
- Flow is **agent-first**: prompts are wrapped imperatively so the agent generates
directly instead of asking questions.
- The UI language follows your Google account; navigation selectors cover IT/FR/EN.
## Claude Code skill
`skill/SKILL.md` is a ready-to-use skill: drop it in `~/.claude/skills/google-flow-generate/`
and Claude will pick the right tool, handle Chrome startup and fallbacks automatically.
## License
MIT — see [LICENSE](./LICENSE).
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues