Skip to main content
Glama
README.md
# google-flow-mcp

[![CI](https://github.com/Dilantha-Wijesinghe/google-flow-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/Dilantha-Wijesinghe/google-flow-mcp/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

An [MCP](https://modelcontextprotocol.io) server that lets AI agents like Claude generate images in **[Google Flow](https://flow.google.com)** and download them to disk.

An agent can:
- choose the **model**, **aspect ratio** and **number of images**
- submit a prompt and wait for the results
- download them at **1K** (original), **2K** or **4K** (upscaled)

It works by operating the real Flow web app in a Chrome window that you sign into once. You don't need an API key.

> **Unofficial.** This project is not affiliated with or endorsed by Google. It automates Flow's web UI on your own account, using your own subscription and credits. Review [Google's terms](https://policies.google.com/terms) before using it heavily, and expect breakage when Flow changes its UI.

## Contents

- [Requirements](#requirements)
- [Install](#install)
- [First run](#first-run)
- [Tools](#tools)
- [Configuration](#configuration)
- [How it works](#how-it-works)
- [Troubleshooting](#troubleshooting)
- [Security](#security)
- [Contributing](#contributing)

## Requirements

- Node.js 20 or newer
- Google Chrome (or Chromium)
- A Google account with access to Flow (a Google AI plan for paid models and credits)

## Install

```bash
git clone https://github.com/Dilantha-Wijesinghe/google-flow-mcp.git
cd google-flow-mcp
npm install        # also builds dist/
```

### Claude Code

```bash
claude mcp add google-flow -- node /absolute/path/to/google-flow-mcp/dist/index.js
```

### Claude Desktop and other MCP clients

```json
{
  "mcpServers": {
    "google-flow": {
      "command": "node",
      "args": ["/absolute/path/to/google-flow-mcp/dist/index.js"]
    }
  }
}
```

## First run

1. Ask your agent to call `flow_status`, or run `npm run call -- flow_status`.
2. The server launches Chrome with a **dedicated profile** (`~/.flow-mcp/chrome-profile`) and remote debugging on `127.0.0.1:9222`.
3. **Sign into Google in that window** and open flow.google.com once. The sign-in persists for later sessions.

> Why a separate profile? Chrome 136 and later refuse remote debugging on your everyday profile. Google sign-in also blocks browsers launched by automation tools. So the server starts a normal Chrome process on its own profile and attaches to it.

## Tools

| Tool | Purpose |
|---|---|
| `flow_status` | Connect to Chrome, launching it if needed, and report `signedIn`. |
| `flow_get_options` | List the models, aspect ratios and counts Flow currently offers your account, read live from the UI. |
| `flow_generate_images` | Generate images. Returns new `mediaIds`, and downloads them too when `download_size` is set. |
| `flow_download_images` | Download images by media id at `1K`, `2K` or `4K`. |

### `flow_generate_images` arguments

| Argument | Description |
|---|---|
| `prompt` | Required. |
| `aspect_ratio` | `16:9`, `4:3`, `1:1`, `3:4` or `9:16`. Omit to keep the current setting. |
| `model` | Full name or a unique fragment, e.g. `Nano Banana Pro` or `2 lite`. |
| `count` | 1–4. |
| `project` | `default` (a project the server creates and reuses), `new`, `current`, or a `https://flow.google.com/project/<id>` URL. |
| `max_credits` | Default `0`. The server refuses to submit when Flow says the generation costs more. |
| `dry_run` | Apply the settings and return the credit cost without generating. |
| `download_size` / `output_dir` | Download the results in the same call. The default directory is `~/Downloads/flow-mcp`. |
| `timeout_sec` | Default 240. |

### Example

> "Generate 4 cinematic 16:9 images of a lighthouse at golden hour with Nano Banana Pro and save them to ~/Pictures/lighthouse."

The agent calls:

```json
{
  "prompt": "A lighthouse on a rocky coast at golden hour, cinematic wide shot",
  "model": "Nano Banana Pro",
  "aspect_ratio": "16:9",
  "count": 4,
  "download_size": "1K",
  "output_dir": "/Users/you/Pictures/lighthouse"
}
```

And it gets back:

```json
{
  "projectUrl": "https://flow.google.com/project/…",
  "mediaIds": ["37be9df5-…", "38d1a484-…", "…"],
  "credits": 0,
  "settings": "Nano Banana Pro · 16:9 · x4",
  "files": [{ "mediaId": "37be9df5-…", "path": "/Users/you/Pictures/lighthouse/Lighthouse_…_1K_37be9df5.jpg", "bytes": 917811 }],
  "failures": []
}
```

### Command-line testing

```bash
npm run call                                  # list tools
npm run call -- flow_status
npm run call -- flow_get_options
npm run call -- flow_generate_images '{"prompt":"a red fox in snow","aspect_ratio":"16:9","count":2,"download_size":"1K"}'
```

## Configuration

Set these environment variables in your MCP client config:

| Variable | Default |
|---|---|
| `FLOW_MCP_CDP_URL` | `http://127.0.0.1:9222` |
| `FLOW_MCP_AUTO_LAUNCH` | `1`. Set `0` to require a Chrome you started yourself. |
| `FLOW_MCP_CHROME_PATH` | Auto-detected for macOS, Windows and Linux. |
| `FLOW_MCP_PROFILE_DIR` | `~/.flow-mcp/chrome-profile` |
| `FLOW_MCP_OUTPUT_DIR` | `~/Downloads/flow-mcp` |

## How it works

These details were observed on flow.google.com in October 2026.

- **Settings:** the prompt bar's settings chip opens a popover containing:
  - Image/Video toggles, aspect ratio and count, all Angular Material `role=radio` buttons matched by label.
  - A model menu.
- **Prompt:** a ProseMirror editor. The server types into it with real keyboard input.
- **Credits:** before submitting, the server reads the "Generating will use N credits" line and enforces `max_credits`.
- **Progress:** each pending image shows a `.loading-percentage` placeholder. Finished images are `<img data-media-id>` tiles. New images are found by diffing media ids before and after.
- **Download:** the tile menu offers Download → 1K, 2K or 4K. Flow builds the file as a `blob:` URL and clicks an `<a download>`. The server intercepts only the click it triggered and writes the bytes where you asked, so Chrome's download settings don't matter.
- **One job at a time:** jobs are serialized. Flow attaches a single-use reCAPTCHA token to each generation and flags rapid-fire requests.

All selectors live in `SEL` at the top of [`src/flow.ts`](src/flow.ts).

### Why UI automation and not Flow's private API?

In September 2026 Flow moved from `labs.google/fx` to `flow.google.com`, and the old `aisandbox-pa.googleapis.com` endpoints stopped working. The new backend uses Google's internal `batchexecute` RPC, and each generation needs a single-use reCAPTCHA Enterprise token minted in the browser. Replaying that traffic over plain HTTP means working around the bot check. It also breaks every time RPC ids rotate. Driving the real UI is slower, around 20 seconds per batch, but it stays within normal use of the site.

## Troubleshooting

| Symptom | Fix |
|---|---|
| `signedIn: false` | Sign into Google in the Chrome window the server opened, then retry. |
| `No Chrome DevTools endpoint` | Chrome isn't running with remote debugging. Leave `FLOW_MCP_AUTO_LAUNCH=1`, or start Chrome with `--remote-debugging-port=9222 --user-data-dir=<dir>`. |
| Port 9222 in use | Set `FLOW_MCP_CDP_URL=http://127.0.0.1:9333`. The server launches Chrome on that port. |
| Timeouts or "not found" after a Flow update | Flow's UI changed. Update the selectors in `SEL` and [open an issue](https://github.com/Dilantha-Wijesinghe/google-flow-mcp/issues). |
| `would use N credits … above max_credits` | Working as intended. Raise `max_credits` if you accept the cost. |

### Known limitations

- Images only. Flow's video mode is not wired up yet.
- 2K and 4K downloads trigger Flow's upscaler, which may use credits. `max_credits` does not cover upscaling.
- Tested on macOS with Chrome 155. Windows and Linux paths are auto-detected but less tested.

## Security

- `~/.flow-mcp/chrome-profile` holds a **signed-in Google session**. Treat it like a password and never share or commit it.
- The DevTools port is bound to `127.0.0.1`. Anything running locally as your user can drive that browser while it is open, so close the window when you're not using it.
- To report a vulnerability, use GitHub's [private vulnerability reporting](https://github.com/Dilantha-Wijesinghe/google-flow-mcp/security/advisories/new).

## Contributing

Issues and pull requests are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md).

## Related projects

These were reviewed while building this one:
- [miyakejima/google-flow-mcp](https://github.com/miyakejima/google-flow-mcp)
- [luongvietan/google-flow-mcp](https://github.com/luongvietan/google-flow-mcp)
- [TMSSS05/google-flow-browser-mcp](https://github.com/TMSSS05/google-flow-browser-mcp)
- [Mitanshp5/Google-Flow_MCP](https://github.com/Mitanshp5/Google-Flow_MCP)
- [crisng95/flowkit](https://github.com/crisng95/flowkit)

## License

[MIT](LICENSE)

Maintenance

ActivityMaintained
ResponsivenessNo issues