io.github.molkex/omni-flash-veo3-nano-banana
repo:https://github.com/molkex/mcp-flow-google
Omni Flash and Veo video, Nano Banana images on Google Flow, from any MCP client
- transport:
- remote
- credential class:
- gated
Owner verification
Not yet verified. Verifying proves you control this server and is free, permanently — it never changes a published score.
Start verification →Tools
- add_account_tokenshallow
Attach one of YOUR OWN Google accounts to the pool using an oauth_token captured on the USER'S OWN machine (password/2FA never leave it). This is the self-serve onboarding path — no server-side browser, no SSH. HOW TO GET oauth_token: the agent must first run the local grabber on the user's machine (it opens a native Chrome at accounts.google.com/EmbeddedSetup; the user logs in and clicks "Принимаю"/Accept): npx --yes github:... local_grab (or: node browser-tools/local_grab.js 9222) It prints {"email", "oauth_token"}. Pass those here. The oauth_token is SINGLE-USE: if this call fails, the user must re-login and grab a FRESH token — never retry the same one. On success the account is bound to YOUR key's owner group and the worker picks it up within ~30s (no restart). Adding an account is always allowed — even for a key that has already spent its free quota, since that is a prerequisite, not a reward. Only onboard accounts YOU control — a master token grants full account access.
- check_creditsshallow
Check projects for a farm account (or all). NOTE: for the credit BALANCE and a full at-a-glance overview, prefer `flow_dashboard()` — it returns real credit numbers per account + totals. This tool only returns the project list.
- check_jobshallow
Check the status/result of a job previously returned by generate_image, generate_video, generate_video_from_image, or generate_video_with_reference. Besides status/result it reports PROGRESS, so you can tell the person something truthful instead of "still waiting": queue_position — how many jobs are ahead (1 = next to be picked up); only while queued queue_seconds — how long it sat in the queue run_seconds — how long the generation itself has been running account_used — which Google account it ran on, once finished hint — the same thing in one human sentence A job that is queued behind others needs patience; one that has been running far longer than its model's typical time (see list_models) is the one worth reporting as stuck. Once status is 'done', SAVE THE FILES: the response carries `download_urls` (no auth header needed) and `save_as` (filenames). Write them into the user's project — e.g. ./media/<save_as> — and tell them where. The URLs expire within the hour, and the server's own copy can be reclaimed when its disk fills; the copy in their project is the one that lasts.
- create_charactershallow
Create a new, empty Flow character (just gets you an entity_id — no portrait/body, no description yet). Plain HTTP, no browser involved. Low-level building block — for "make me a character from a description and generate its portrait", call create_character_from_description instead of this; it does this step plus the two below in the right order for you. Next steps after you have entity_id, IN THIS ORDER (reversing them 500s on the first portrait write, confirmed live 2026-07-25): 1) update_character with personality_notes (and display_name) — the slot generation below needs a saved description to succeed at all; 2) generate_character_image with character_slot_index=0 (portrait), then =1 (body) — each slot accepts exactly ONE write, a second call into an already-filled slot 500s rather than overwriting.
- create_character_from_descriptionshallow
Invent a new character from a text description and generate its portrait — the full "make me a character, no photo involved" path in ONE call, instead of gluing together create_character + update_character + generate_character_image yourself. name: short and unique among YOUR OWN characters (see list_characters()) — how you'll refer to this character afterwards, e.g. character="detective_marlowe" in generate_with_face. description: physical description — build, hair, eyes, clothing, distinguishing features. Saved on the character's card AND used to generate the portrait, so write it as concretely as you would any image prompt. account: farm account (and its project) to create the character under. The portrait is written to Flow's card exactly ONCE — that slot cannot be regenerated. Calling this again with the SAME name does not retry it: it fails fast with a clear message instead of hitting a raw HTTP 500 downstream. Want a different look? Use a new name. Returns {"name", "entity_id", "portrait_media_id", "portrait_url", "hint"} once done. Next step for ANY further image of this character: generate_with_face( character=name, prompt="...") — never entity_id/character_slot_index, which only works for that one portrait write and cannot place the character into new scenes.
- create_character_from_photoshallow
Create a new Flow character whose portrait (and optionally body) is a REAL PHOTO, not a text description or generation. Both photos become the character's slot-0 (portrait) and slot-1 (body) images directly — Flow's own upload mechanism in its New Character composer, discovered live 2026-07-11 — no image generation call happens for either slot, so resemblance is exact, not "similar style". Boots the on-demand Chrome for this account (~15-30s, longer if body_photo_base64 is also given), same as create_character, no Android/recaptcha involved. photo_base64: raw base64-encoded image bytes, no data: URI prefix — portrait. body_photo_base64: same format, optional — ideally a full-body photo of the same person, for a guaranteed-exact body image (no generation at all for that slot). physical_description: IMPORTANT, look at the photo yourself and write this — a detailed physical description (build, hair color/style, eye color, clothing, distinguishing features), similar in spirit to: "Adult male, mid-20s, ~180cm, lean build. Medium-brown wavy hair, light blue-grey eyes, faint stubble. Wears a dark grey hoodie, dark jeans, white sneakers." This gets saved into the same "Character Info" field as Flow's own UI. CORRECTED same day as this tool was first built: an earlier version of this doc claimed body/multi-view generation can never stay consistent with a photo-seeded portrait — WRONG, confirmed live. The actual missing ingredient was this detailed text spec — with it, both generate_character_turnaround and generate_character_expression_sheet below produce genuinely consistent, on-model results (reproduced live against Flow's real UI, not just guessed). Skip this only for a bare portrait-only character with no further generation planned. Next step after you have entity_id: update_character for a display name, then generate_character_turnaround / generate_character_expression_sheet if you want those (skip if you already passed body_photo_base64 for an exact body photo — generating over it would replace the real photo with a generated approximation). Fidelity note added 2026-07-11 (later same day): "genuinely consistent" above means consistent WITH ITSELF across panels (same invented-looking person in every view), not necessarily an exact match to the real person's face — real-world feedback was "I don't recognize myself." Good for stylized/invented character sheets; if the goal is content that's recognizably the actual person, use generate_video_with_reference (r2v) instead, which conditions on the real photo's pixels rather than a description. name: optional, added 2026-07-25 — give the character a short human-readable name and it's saved to YOUR list (list_characters()), keyed on the uploaded photo as the identity reference (portrait_media_id). Once named, use generate_with_face(character=name, prompt=...) for further images instead of tracking portrait_media_id yourself. Must be unique among your own characters; a clash does NOT fail the call — the character is still created in Flow, just reported back with a `registration_error` instead of a `name` in the result, so pick a different name and register it yourself later if that happens.
- create_projectshallow
Create a NEW Flow project on one of your farm accounts and return its project_id. Use this to give every one of YOUR OWN clients their own namespace: create a project per client once, then pass that project_id to generate_image / generate_video so their results never mix with anyone else's. account — which farm account creates it (see flow_dashboard / check_credits for the emails). The project is created under that account, but a project id is a label every account accepts: generation keeps rotating accounts as before, so results stay grouped by project_id, not by account. What is still account-bound is media_ids — a follow-up that reuses one (image_inputs edit-in-place, extend_video, upscale) only works on the account that produced that particular frame, exactly as today. name — optional human-readable title, e.g. the client's name. The returned project is usable for generation IMMEDIATELY. It may not show up in the Flow web UI's project list (`registered: false` in the result says so) — that only affects browsing in Google's own interface, not this API: every result comes back as urls/media_ids in the generation response either way. Returns {"project_id": ..., "account": ..., "registered": true|false}.
- edit_videoshallow
Rewrite a video this service already generated, from a plain description: "make the sky stormy", "take the passer-by out of the shot", "warmer light". media_id: the id from a previous generate_video* result. Only our own videos can be edited — the id belongs to a farm account's project, so the job is pinned to that account. 20 credits per edit (abra_edit is the only model Flow offers here). This edits the WHOLE clip. It is not a mask tool: describe the change, not the region.
- extend_videoshallow
Continue a video this service already generated — Flow writes what happens next. media_id: the id from a previous generate_video* result (the bare id, not the /v1/media/... path). Only videos made through this service can be extended: the id belongs to a specific farm account's project, so the job is pinned to that account instead of rotating. An id we never produced comes back as a clear error, not a mystery failure. Use this for shots that need to run longer than one generation, or to keep a scene going without re-describing it: the continuation inherits the source clip's world, which a fresh text-to-video call cannot do. Default model veo_3_1_extension_lite: 10 credits, adds 8 seconds. project_id: which project the continuation lands in. The job is pinned to the source clip's account regardless, so pass the project the source was generated in (or omit it).
- fetch_mediashallow
Download a generated media file (video, frame) and return its bytes, base64-encoded, so the file can be saved or shown even though the media endpoint isn't publicly reachable with your MCP key. THIS IS THE EXPENSIVE PATH — prefer `download_url` from the job result. Bytes returned here travel as TEXT, and text is where context dies: a 480 KB audio stem is ~640 thousand base64 characters, roughly 160 000 tokens, in ONE tool result. The same file behind `download_url` costs about twenty. An inline image preview is cheap by comparison (it travels as an image, ~450 tokens) — it is base64 in a text field that hurts. Because of that this tool REFUSES big files by default and hands back a download link instead. Pass force_bytes=True only when you genuinely need the bytes inside the conversation and know what it costs. path: the `download_path` / `first_frame_path` value from a job result (e.g. "/v1/media/<id>.mp4"), or just the bare filename. max_kb: size ceiling for an in-band answer (default 64 KB ≈ 21 000 tokens). Returns {"filename", "media_type", "base64"}. The download is scoped to your own account group — you can only fetch media your key produced. Note videos can be several MB, so the base64 payload is large; fetch only when you actually need the bytes (to save/display), not to check status (use check_job for that). On storage: generated files are NOT deleted on a timer — there is no retention window to race. Space is only ever reclaimed when the server's disk runs low, and then only from files that were already downloaded through this call; a result nobody fetched is never removed to make room. So fetching once and saving the bytes locally is the way to keep something for good, and a file you never fetched stays available. A file that was reclaimed answers 410 with the date, not a bare 404.
- flow_dashboardshallow
The account-pool control panel: for EVERY farm account, the real credit balance, subscription tier, project count, and health status, plus totals — one call, formatted for reading. Use this to answer "how many accounts, how many credits on each and in total, what projects" — the operator's dashboard. Returns a `summary` string (human-readable table) plus structured `accounts` and `totals`. Credit numbers are live (Flow's /v1/credits). Credit REFRESH date is not exposed by Flow's API, so it's shown as an estimate note, not a hard date.
- flow_healthshallow
Check whether the Flow generation backend is reachable and see current queue depth (queued + warming + running jobs). Note: the Android emulator is now OFF — generation runs on a pure-HTTP token path, so there's no warm-up delay anymore.
- flow_statusshallow
What this key still needs before it can do everything — READ-ONLY, spends nothing. Call this BEFORE the first generation of a session, whenever a call is refused, and whenever the user asks why something does not work. It answers in one shot: is a Google account connected, how much of the free trial is left, is the key linked to a GitHub identity, is video paid for. The important field is `next_step`: it is the single most blocking thing right now, with ready-made wording (`text` in Russian, `text_en` in English) and a `url` to open. When it is null, nothing is missing. DO NOT keep this to yourself. If `next_step` is set, say it to the user in their own language and give them the URL — a step like linking GitHub happens in THEIR browser and cannot be done by you. `support` is the operator's Telegram, the service's only human channel; there is no email on file for a self-registered key, so nobody will reach out to the user first.
- generate_character_expression_sheetshallow
Generate a single image showing the character's FACE with several different expressions in one row, labeled — an "expression sheet". Same job type and same history as generate_character_turnaround — see its docstring for the full story: the 2026-07-11 finding (plain Android-bearer image path is inconsistent for multi-view prompts, the real web composer was reliably consistent) is why this tool exists, but as of 2026-07-26 it no longer drives that composer — pure HTTP with image_inputs=[portrait_media_id] instead (no browser). Multi-view consistency on THIS new path has not been re-verified live yet; the recommendation to keep a detailed physical description saved on the entity carries over from the old finding but hasn't been separately re-tested against the new mechanism either. account: farm account that owns this entity_id's project. expressions: list of expression labels, e.g. ["нейтральное выражение", "удивление", "лёгкая улыбка", "смех"] (default if omitted). Keep to 3-5 for a readable single-row layout. character_slot_index: which slot to write into (0 = portrait, default — this overwrites the existing portrait image with the expression sheet, matching how this was used when reproducing the feature; 1 = body slot also works).
- generate_character_imageshallow
Generate a portrait or body image for an existing Flow character. entity_id: the character's entityId — from create_character or create_character_from_photo, or create_character_from_description's own result (which already calls this for slot 0 — no need to call it again for that slot). character_slot_index: 0 for portrait, 1 for body. Flow keeps the two slots visually consistent server-side once they share an entityId — no reference image needed for the body shot. ONE-SHOT PER SLOT, confirmed live 2026-07-25: each slot can be written exactly once — a second generate_character_image call into an ALREADY-FILLED slot fails (HTTP 500), it does not overwrite. Also confirmed: the FIRST write into a slot 500s on a card with no personality_notes saved yet — call update_character with personality_notes before the first generate_character_image on a fresh entity_id. If you're using create_character_from_description, both of these are already handled for slot 0; this caveat mainly matters if you're driving slot 1 (body) or entity_id yourself. THIS TOOL DOES NOT PLACE A CHARACTER INTO A NEW SCENE — it only ever (re)writes the character's own portrait/body slot, once. For "generate a picture of this character doing X", use generate_with_face(character=..., prompt=...) instead, which conditions on the reference image, not entity_id. CAVEAT confirmed live 2026-07-11: for a character seeded from a REAL PHOTO (create_character_from_photo), this text-prompt generation is NOT reliable for identity — it conditions on a text description, not the real photo's pixels, and was confirmed to drift to an unrelated-looking person even with a detailed physical description saved on the entity. Fine for invented/stylized characters. If the goal is "content that looks like a real person," use generate_video_with_reference (r2v) instead — see its docstring. Only works for the account whose project actually owns this entity_id — characters are per-account, same as projects.
- generate_character_turnaroundshallow
Generate a single image showing the character's FULL BODY from 3 angles (front/side/back) in one row, labeled — a "turnaround sheet". Pure HTTP as of 2026-07-26 — no browser involved (see below for what changed and what that does and does NOT prove). History, so the mechanism change doesn't erase the reason this tool exists: confirmed live 2026-07-11 that the plain Android-bearer generate_character_image path produces an INCONSISTENT result for this exact kind of multi-view prompt, even with a detailed physical description already saved on the entity — a real web composer (Chrome/CDP) driving Flow's own translation/agent layer was reliably consistent for the same prompt. That is why this tool exists as a separate path from plain image generation, and that finding still stands. What changed 2026-07-26: this no longer drives that browser composer. The underlying job type (generate_character_scene) moved to a THIRD mechanism, not either of the two compared above — plain HTTP with image_inputs=[the character's own portrait_media_id from the registry], the same face-preserving mechanism generate_with_face uses. This was done to remove the last browser dependency (worker.py's BROWSER_JOB_TYPES is now empty), not because this new path's multi-view consistency was re-verified — it has NOT been checked live yet whether image_inputs alone holds up as well as the old composer did for a 3-angle sheet. Treat multi-view reliability here as unverified-but-plausible until confirmed by eye against real output, not as re-proven. Still recommend a detailed physical description saved first (create_character_from_photo's physical_description param, or update_character's personality_notes) — that recommendation carries over from the 2026-07-11 finding above; whether it still matters mechanically on this new image_inputs path (vs. the composer's own entityContext-driven translation layer, which this path does not use) has not been separately tested, so keeping it costs nothing and there's no evidence yet that it's safe to drop. account: farm account that owns this entity_id's project. character_slot_index: which slot to write the result into (0 = portrait, 1 = body — default 1).
- generate_imageshallow
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): NARWHAL = "Nano Banana 2" — the DEFAULT, ~30s 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: 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.
- generate_sceneshallow
Build a location precisely from a scene-layout/v2 map and generate its plate. This is the "exact location building" path: instead of describing the room in prose (which the model reinterprets — furniture drifts, depths change between shots), it renders a control image from the map's boxes (each object a colored block at its true position/size/depth, plus a 1-meter floor grid in true perspective), then asks the generator to REPLACE each block with its real object in the same camera — so the plate follows the geometry pixel-wise. Same room from another camera_id is the same space. scene_layout: a scene-layout/v2 dict — {format, units, room{w,d,h}, objects{...boxes}, cameras{<id>:{pos,look_at,fov_deg,framing?}}, ...}. The camera must carry fov_deg. camera_id: which camera in scene_layout.cameras to render from. aspect: PORTRAIT (9:16), LANDSCAPE (16:9) or SQUARE. 9:16 and 16:9 from one camera share the vertical FOV, so depths are identical across aspects. style / extra: prepended / appended prose (art style, mood) — geometry comes from the map. A box may carry `rot: [rx, ry, rz]` (degrees around the world X/Y/Z axes) and `pivot: [x, y, z]`, applied as p' = Rx·Ry·Rz·(p − pivot) + pivot, pivot defaulting to the box centre. That is how a POSE is expressed — a raised arm is a box rotated about the shoulder. Measured live 2026-08-09: moving a hand by 2–20 cm is ignored by the generator, rotating the arm by 15–60° comes through. Build motion out of angles. seed / image_inputs: same meaning as in generate_image. For a SEQUENCE of frames of one character, generate a reference frame first, then pass its mediaId as image_inputs on every following frame — that is what keeps the face, clothes and colours identical. A fixed seed alone does not: it only repeats an unchanged control image. depth: render the guide as a plain greyscale depth map instead of the colour hybrid (for an external depth-ControlNet). calibration: add frame markers, a back-wall grid and a 2 m ruler with 10 cm ticks — measured to cut the framing drift roughly fourfold. background: "dark" (default, unchanged) or "light". Use "light" when the plate must be on a white background: the generator sometimes copies the guide's own palette into the result, and a light guide makes that leak land as white rather than as a dark grid. control_png: return the layout guide itself, base64-encoded. OFF by default because it is hundreds of thousands of characters of TEXT — one guide can cost more context than the whole conversation around it. `control_png_kb` always reports its size. Returns {"urls", "media_ids", "legend", "control_png_kb"} — legend maps block colors to objects. Add control_png=True to also get the guide itself for inspection/acceptance.
- generate_videoshallow
Generate a video from a text prompt via Google Flow (Veo models). video_model_key options: abra_t2v_4s (default, 7 credits), veo_3_1_t2v_lite (10cr, visibly cleaner), veo_3_1_t2v (100cr, "Quality" tier), veo_3_1_t2v_fast (20cr). project_id: put the clip into a project made with create_project instead of the account's default one — one project per end client keeps their work separate. Video generation routinely takes 1-3+ minutes, so this almost always returns a job_id rather than a finished result — call check_job with it, waiting a few seconds between checks, until status is 'done' or 'failed'.
- generate_video_between_framesshallow
Generate the transition between TWO given frames: the video starts at the first image and ends at the second one, Flow invents everything in between. This is Flow's "Кадры" with both slots filled — a different mechanism from generate_video_from_image, which only pins the FIRST frame and lets the ending drift. Use this when the ending matters: a logo that must resolve exactly, a character that must land in a specific pose, two stills from a storyboard that need connecting. Both images are raw base64 bytes, no data: URI prefix. The default model (veo_3_1_interpolation_lite, 10 credits, 8 seconds) is the cheap one — transitions are something you retry a few times, and defaulting to the 100-credit key would make every experiment expensive. project_id: put the clip into a project made with create_project instead of the account's default one.
- generate_video_from_imageshallow
Generate a video that starts from a given image (i2v — image-to-video). start_image_base64: raw base64-encoded image bytes, no data: URI prefix. Mutually exclusive with reference-image (r2v) generation. For "make content that looks like this real photo of a person" specifically, prefer generate_video_with_reference (r2v) over this — see its docstring for why. i2v is better suited to "continue visually from this exact frame" (e.g. chaining clips), not identity preservation across a whole new scene. project_id: put the clip into a project made with create_project instead of the account's default one.
- generate_video_with_referenceshallow
Generate a video using up to 3 reference images (r2v — e.g. a consistent character/subject across the video). reference_images_base64: raw base64-encoded image bytes (no data: URI prefix), up to 3. Mutually exclusive with start-image (i2v) generation. THIS IS THE RECOMMENDED WAY to get content that actually looks like a real person from a real photo — confirmed live 2026-07-11: r2v conditions generation on the reference photo's actual pixels and reliably preserves the real face, unlike the character system's `generate_character_image`/`generate_character_turnaround` (those condition on a TEXT description + a loosely-attached reference and were confirmed to drift to an unrelated-looking person). For a still IMAGE rather than video, use this and read `first_frame_path` off the result once done (via check_job) — same-day testing found no reliable image-only equivalent: a plain generate_image call with image_inputs pointed at an external photo was confirmed to silently ignore the reference entirely. project_id: put the clip into a project made with create_project instead of the account's default one.
- generate_with_faceshallow
Generate a NEW image of the SAME PERSON/character as an existing photo or portrait — dress them differently, move them somewhere else, make an avatar. This is the tool for "here is my photo, now put me in a suit / in a park", and also the ONLY tool for "generate another picture of <character I already made>". Pass exactly ONE of: character: the name you gave a character via create_character_from_description or create_character_from_photo(..., name=...). Looked up in your own list — see list_characters(). This is the normal way once a character has a name. photo_media_id: a mediaId directly (create_character_from_photo's `portrait_media_id`, or any earlier generate_image media_id) — for a one-off face you haven't registered as a named character. prompt: describe the NEW scene/outfit and say it is the same person, e.g. "the same man, now in a navy suit in a bright office". Why this and not entity_id/character_slot_index: a character's Flow CARD is not what carries resemblance into a NEW scene — the reference image itself does (verified live, repeatedly). Combining entity_id with an image reference in the same call also fails outright (HTTP 500). So this always generates from the reference image alone, never from entity_id — that is deliberate, not a workaround to fix later. project_id: put the result into a project made with create_project instead of the account's default one. photo_media_id itself stays account-bound, as always.
- list_charactersshallow
List the characters YOU created (create_character_from_description, or create_character_from_photo with name=...) and can now generate more images of via generate_with_face(character=<name>, prompt=...). Read-only, no Flow calls, no credits spent. Returns {"characters": [{"name", "source", "description", "portrait_media_id", "entity_id", "project", "account", "created_at"}, ...]}, oldest first. `source` is "description" (create_character_from_description) or "photo" (create_character_from_photo). `portrait_media_id` is what generate_with_face actually uses — a character with it set to null has no usable reference yet.
- list_modelsshallow
List every valid model id this service accepts — READ-ONLY, spends no credits, calls nothing outside this service. Call this BEFORE generate_image/generate_video if you're unsure of an exact id: guessing (e.g. the family key "nano_banana_pro" or a display name like "Nano Banana 2" instead of the id "NARWHAL") gets a hard HTTP 400 on a call that already committed to a task, not a helpful list. Returns: images: {id: {label, typical_seconds, notes}} for the three valid `model` values (generate_image, generate_character_image). videos: {id: {label, credits, duration_s, mode, orientation}} for the curated `video_model_key` values this server's tools accept via their Literal type — mode is one of t2v/i2v/r2v (which generate_* tool it belongs to). `credits` or `duration_s` is null where Google's docs never gave that number — a null does NOT mean free/instant, it means unconfirmed. defaults: the id each tool falls back to when you omit the parameter — unchanged from before this tool existed, so already-working callers aren't affected. Note: service/api.py (the HTTP layer these tools call through) additionally accepts a wider set of rarer, exotic video_model_key values not listed here (confirmed-real but uncommon r2v/i2v variants) — this tool only lists the ones actually worth choosing from, to stay a short, readable list.
- music_chatshallow
Talk to the Google Flow Music Producer agent instead of one-shotting a track. Use this when the work is a conversation rather than a single brief: asking what it can do, having it write lyrics first, or editing a track it already made ("drop the vocals", "same song, 30 seconds shorter", "make the chorus bigger"). For a plain "make me a song about X", music_generate is the shorter path. message — what to say. conversation_id — omit on the first message, then pass the one that comes back so the Producer keeps its memory of the track. model — same choices as music_generate. Returns {"conversation_id", "text", "suggested_actions", "clips": [...], "media": [...]}. `text` is the Producer's reply. `suggested_actions` are the follow-ups it offers — show them to the user, they are good prompts for the next turn. `clips` is EMPTY when the Producer only talked, and filled when it decided to actually make audio; treat a filled `clips` exactly like a music_generate result and save the audio. A reply is usually seconds, but a turn that produces a song takes minutes and comes back as a job_id to poll with check_job.
- music_creditsshallow
Check remaining flowmusic credits and subscription tier.
- music_downloadshallow
Download the raw .m4a file of a track to the server.
- music_generateshallow
Generate a full song from a text brief via Google Flow Music (Lyria). prompt — free text: genre, mood, BPM, instruments, and whether you want vocals or an instrumental (e.g. "dreamy synthwave, retro 80s, 110 bpm, instrumental"). The Producer agent turns it into a finished track (usually ~2-3 minutes, and it returns TWO variants). model — "lyria" (Lyria 3.5, the default flagship) or "lyria-pro" (Lyria 3 Pro, legacy). lyrics — optional explicit words to sing; omit for the model to write its own / stay instrumental. SAVE THE RESULT. Each returned clip carries a public `audio_url` (a Google Cloud Storage .m4a, no auth header needed) plus `download_path` on our server. Unless the user said otherwise, download the audio into their project. Fields per clip: clip_id, title, duration (seconds), lyrics, audio_url, wav_url, image_id (cover, feeds music_video), image_url. Returns {"clips": [...], "media": [...], "conversation_id": "..."} when done, or a job_id to poll with check_job if it isn't ready within ~90s. conversation_id — pass the one from an earlier result to keep working on the same track ("same song but 30 seconds shorter"); the Producer remembers what it just made. Omit it for a fresh start. Every result carries one, so a follow-up is always possible.
- music_getshallow
Get metadata for a single music track.
- music_listshallow
List the user's music tracks.
- music_stemsshallow
Split a track we generated into stems (vocals, instrumental, drums, bass, …). clip_id — the id of a clip returned by music_generate (or music_video's song). Runs on the same account that made the track. Returns {"stems": {name: "/v1/media/..."}, "media": [...]} when done, or a job_id to poll with check_job. Each stem is a downloadable .m4a on our server (public download_path). Save the ones you need into the user's project.
- update_charactershallow
Save a character's display name and/or personality notes. Without this, a character stays 'Untitled Character' with no description even after portrait/body images exist. account must be whichever farm account's project owns this entity_id.
- upscale_imageshallow
Upscale an existing generated image (from a prior generate_image call) to a higher resolution, via Flow's own Download panel -- the same "1K/2K/4K" picker shown when downloading an image in the Flow UI. account must be whichever farm account's project owns media_id (generate_image returns media_ids scoped to whichever account handled that job -- reuse the same account here). target_resolution: "2K" or "4K". Not every image supports upscaling (depends on the source model/size) and 4K may be locked behind a paid plan tier on some farm accounts -- both cases come back as a clean error rather than a crash, so just report it if that happens instead of retrying. This is slower than generation (drives a real browser, ~15-30s) -- returns a job_id to poll with check_job if it's not done within ~35s. Returns {"media_id": <new upscaled mediaId>, "download_path": "/v1/media/....jpg", "resolution": ...} when done.
- upscale_videoshallow
Upscale an existing generated video (from a prior generate_video call) to a higher resolution, via Flow's own grid-view download menu (the "270p/720p/1080p/4K" picker). account must be whichever farm account's project owns media_id (generate_video returns media_ids scoped to whichever account handled that job -- reuse the same account here). target_resolution: "1080p" or "4K". 4K may be locked behind a paid plan tier on some farm accounts -- comes back as a clean error rather than a crash, just report it. Slower than generation (drives a real browser for the kickoff, then polls like a normal video generation) -- returns a job_id to poll with check_job if it's not done within ~40s. Returns {"media_id": <new upscaled mediaId>, "download_path": "/v1/media/....mp4", "resolution": ...} when done.
Embed this server’s score
Tool count and median score across every tool in this server’s corpus — honest in a way a single cherry-picked tool’s badge wouldn’t be.
[](https://vouch.tools/servers/4dfdc9c8-bb12-4648-8251-e7473d5c73a3)