Are you the author? Sign in to claim
MCP server that drives Google Flow (Veo / Nano Banana) through its internal tRPC API, with a hard credit-cost gate
An MCP server that lets an agent drive Google Flow (labs.google's Veo video / Nano Banana image tool) — with a hard credit-cost gate so it cannot quietly spend your money.
Flow has no public API. This server does not work around that by blindly clicking buttons: Flow's frontend is a tRPC client, so an undocumented API exists, and this speaks that API first. Clicking is the fallback, not the interface.
Status: v0.1, uncalibrated. Everything compiles, 33 unit tests pass, and the tool surface loads — but the DOM selectors and the tRPC endpoint map have not yet been re-verified against live Flow from this codebase. Run the calibration in First run before trusting it with credits; all three steps are free. See Verification status for exactly what is and is not proven.
Read ARCHITECTURE.md for the full reasoning. The short version:
flow_estimate_cost is therefore not an
estimate; it is the real price, at zero cost.| Tier | Mechanism | Used for |
|---|---|---|
1 http | Node fetch + the browser's cookies | Read-only GETs proven safe by flow_verify_http_tier. Parallelisable |
2 page-fetch | fetch() inside the authenticated tab | Default. Auth and CORS free — the page's own origin makes the call |
3 dom | Clicking | Only what has no endpoint: settings, Scenebuilder timeline, Approve/Reject |
Every result reports which tier served it, so you can see when the server has degraded from API to clicking.
git clone https://github.com/roshanarnav25-sloth/google-flow-mcp.git
cd google-flow-mcp && npm install && npm run build
Requires Node 20+ and a local Google Chrome. This server never handles credentials — it attaches to a browser you have already signed into.
Start Chrome with remote debugging and sign into Flow in that window:
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222 --user-data-dir="$HOME/.google-flow-mcp/chrome-profile"
Then open https://labs.google/fx/tools/flow, sign in, and open a project.
If you omit FLOW_CDP_URL, the server launches its own persistent browser
instead — you sign in there once and the profile persists.
claude mcp add google-flow --env FLOW_CDP_URL=http://127.0.0.1:9222 --env FLOW_OUTPUT_DIR="$HOME/flow-output" --env FLOW_BUDGET_CEILING=120 -- node "$PWD/dist/index.js"
Set FLOW_BUDGET_CEILING. It is the backstop that makes a runaway loop
impossible: any generation that would push total run spend past it is rejected
before approval and costs nothing.
flow_check_session # confirm signed in, credits visible, gate ON
flow_discover_api # learn Flow's current tRPC endpoints (free, observes only)
flow_estimate_cost # price one clip and reject it (free) — proves the gate works
If flow_check_session reports the confirm gate is anything but always, fix it
in Flow's settings before generating. With that gate off, Flow charges without
ever showing a cost card, and no amount of client-side care can help.
Session & discovery
| Tool | Charges | What it does |
|---|---|---|
flow_check_session | no | Browser, login, credits, project, and the confirm-gate state |
flow_discover_api | no | Observes Flow's own traffic and writes an endpoint map |
flow_verify_http_tier | no | Promotes proven read-only GETs to direct HTTP |
flow_api_map | no | Reads the learned endpoint map |
Generation
| Tool | Charges | What it does |
|---|---|---|
flow_generate_still | no — free | Stills. Iterate composition here; this is the free sandbox |
flow_estimate_cost | no | Real quoted price, then rejects. Zero cost |
flow_generate_video | YES | Video. Requires expected_max_cost; rejects anything above it |
flow_collect | no | Downloads clips submitted with no_wait |
Composer, settings & projects
| Tool | Charges | What it does |
|---|---|---|
flow_settings | no | Read/set the per-project model tier, aspect, outputs, duration. Free, and the biggest cost lever there is |
flow_upload_media | no | Upload a local image for use as a start frame |
flow_upscale | 1080p no / 4K yes | 1080p is free — always take it. 4K is 50 cr and unquoted, so it needs an explicit ack |
flow_list_projects / flow_open_project / flow_create_project | no | Projects scope settings, library and scenes |
Media & assembly
| Tool | Charges | What it does |
|---|---|---|
flow_list_media | no | Project library, paginated |
flow_download | no | Media id → signed CDN url → disk, magic-byte verified |
flow_delete_media | no | Destructive. Explicit ids only; there is no delete-all |
flow_create_scene / flow_add_clips_to_scene | no | Build a Scenebuilder scene. Flow's chat agent cannot do this |
flow_export_scene | no | Export the scene to MP4. Stitching is free; Extend is not, and is never used |
Tools marketplace
| Tool | Charges | What it does |
|---|---|---|
flow_list_apps | no | Lists Type Overlays, Transition Machine, Mask Magic, Storyboard Studio, custom tools… |
flow_open_app | unknown | Opens an app and hands back. Requires an explicit unknown-cost ack |
Budget
| Tool | Charges | What it does |
|---|---|---|
flow_budget | no | Read or set the ceiling and run spend |
flow_ledger | no | Append-only audit trail of every generation attempted |
Flow is a large product. This is what is and is not reachable through the server.
Generation modes — the mode is not a switch; it is decided by what is attached
to the composer when you submit. flow_generate_video covers all of them:
| Mode | How | Covered |
|---|---|---|
| Text-to-Video | attach nothing | yes |
| Frames-to-Video (start frame) | start_frame_media_id | yes — the normal path |
| Frames-to-Video (start + end) | + end_frame_media_id | yes |
| Ingredients-to-Video (≤3 refs) | reference_media_ids | yes |
| Stills (Nano Banana) | flow_generate_still | yes, free |
| Scene extension (>8s clips) | — | no — deliberate, see below |
Deliberately not covered, with reasons:
Extend (40 cr). It is the one paid action inside an otherwise
free surface, and it sits one keyboard-row away from Add Clip in the same
popover. Excluding it means scene assembly can never charge by accident.flow_open_app opens an app and stops.
Each app has a bespoke UI and some call Veo internally with no quote, so
blind-clicking through one is how an unbounded charge happens.Not yet covered (real gaps, not principled ones): timeline editing inside a
scene (reorder, trim, delete a placed clip), the scene editor's own 16:9↔9:16
toggle, and per-clip regeneration from within Scenebuilder. Assemble in Flow, then
do timeline work locally — ffmpeg -f concat -c copy stitches same-codec Veo
clips identically and costs nothing.
The three references — credit economics, Veo prompting craft, and the verified UI playbook — are also exposed as MCP resources, so an agent can read them without a separate skill.
Price before committing. Free, and the number is real:
flow_estimate_cost(prompt: "slow dolly-in, ambient sound only, no dialogue")
→ Flow quoted 20 credits. Proposal rejected — nothing charged.
The stills-first loop. Compose free, animate once:
flow_generate_still(prompt: "<full composition prompt>", out_file: "shot-03.jpg")
# human approves the still
flow_generate_video(prompt: "maintain the exact composition of the start frame; slow dolly-in; ambient sound only", expected_max_cost: 20, out_file: "shot-03.mp4")
Parallel batch. Flow renders concurrently, so N clips cost about one clip of wall-clock:
flow_list_media() # capture ids BEFORE
flow_generate_video(..., no_wait: true) × N
flow_collect(known_media_ids: [...the ids from before])
| Generation | Credits |
|---|---|
| Still image | 0 |
| Veo 3.1 Lite | 10 |
| Veo 3.1 Fast | 20 |
| Veo 3.1 Quality | 100 |
| Scenebuilder extend | 40 |
Prices verified 2026-07 and re-checked in src/constants.ts. Budget ~1.4 takes
per needed clip: Veo's first-try acceptance is roughly 70%.
Honest accounting, because this handles money:
| Component | Status |
|---|---|
| Build, tool surface, resource surface | Verified — compiles clean; 24 tools and 3 resources load via MCP Inspector |
| Budget gate logic, ledger, magic-byte checks | Implemented; unit-level behaviour not yet exercised against live Flow |
| Composer / Approve-Reject / Download selectors | Ported from live-verified runs (2026-07-09/10), not re-verified from this codebase. Class hashes and labels rot |
| Settings panel, media picker, upload, upscale | Unverified. Written against the documented UI patterns but never run — expect one calibration round |
| Projects, scene create/add-clip, Tools gallery | Unverified. Same caveat; scene export is the only part with a live-run precedent |
| tRPC endpoint map | Three procedures verified by hand; the rest is learned at runtime by flow_discover_api |
| End-to-end paid generation | Not yet run from this server |
The unverified rows fail the same way: a refusal with a "nothing was charged" message naming the control it could not find. That is the design goal — when this server is wrong about the UI, it should cost nothing, not guess.
Calibrate with flow_check_session → flow_discover_api → flow_estimate_cost
before any paid run. All three are free.
Full threat model and reporting process: SECURITY.md.
Issues and PRs welcome — especially selector drift reports, which are expected maintenance rather than defects and usually have small fixes. There is a dedicated issue template for them.
Everything builds and tests offline; you need no Google account and no credits to contribute. See CONTRIBUTING.md for the rules around generation and budget code, which are stricter than the rest.
npm install && npm run typecheck && npm run lint && npm test && npm run build
This automates a Google product through an interface Google does not publish, using your own account and your own credits. Flow's UI and internal API change without notice; expect calibration to be part of using it.
Not affiliated with, endorsed by, or sponsored by Google. "Google Flow", "Veo" and related marks belong to Google LLC. Provided as-is under the MIT License — you are responsible for your own account, your own credits, and your own compliance with Google's terms.
Browser automation using accessibility snapshots instead of screenshots
Run Claude Code as an MCP server so any agent can delegate coding tasks to it
Google's universal MCP server supporting PostgreSQL, MySQL, MongoDB, Redis, and 10+ databases
Official GitHub integration for repos, issues, PRs, and CI/CD workflows