Dropl MCP vs OpenFlow

A side-by-side look at the Dropl MCP and OpenFlow MCP servers: transport, auth, tools, quality signals, and the config to install either one in Claude, Cursor, Windsurf or VS Code.

Dropl MCP logoDropl MCPMultimedia Process · Local subprocess (stdio)Create client-editable photo and video galleries from Cursor or Claude Code, then embed them.61GoodAuth: not declaredOpenFlow logoOpenFlowMultimedia Process · Remote HTTP/SSEOmni Flash and Veo video, Nano Banana images on Google Flow, from any MCP client60GoodAuth: not declared

Verdict: choose Dropl MCP for multimedia process work as a local process; choose OpenFlow for multimedia process over a hosted endpoint. You can also run both side by side in one mcpServers block.

Which MCP server should you choose?

Dropl MCP logoChoose Dropl MCP when

  • You need dedicated capabilities in the Multimedia Process domain.
  • You prefer a local stdio subprocess transport.
  • You have the keys it needs: DROPL_API_KEY.
  • You want tools like whoami, list_sites, create_site.
Explore Dropl MCP

OpenFlow logoChoose OpenFlow when

  • You need dedicated capabilities in the Multimedia Process domain.
  • You prefer a remote HTTP/SSE transport.
  • You want tools like generate_with_face, generate_image, music_generate.
Explore OpenFlow

Feature & specification comparison

Rows where the two servers differ are marked.

SpecDropl MCP logoDropl MCPOpenFlow logoOpenFlow
CategoryMultimedia ProcessMultimedia Process
Quality signal61/100 · Good60/100 · Good
Install commandConfirmedConfirmed
TransportLocal subprocess (stdio)Remote HTTP/SSE
AuthNot declaredNot declared
PricingNot declaredNot declared
Required env varsDROPL_API_KEYNone listed
Verified ownerCommunity listingCommunity listing
GitHub stars18
Directory activity 1 views 0 installs 0 upvotes 1 views 0 installs 0 upvotes
Tools3849

Tools & capabilities

Dropl MCP tools 38

  • whoamiShows the connected Dropl account, user, role, and API key (name, prefix, scopes, site restriction) plus the web app URL. Use it first in a session to confirm which account you're acting on, or when another tool reports a sign-in or permission error. Needs a saved sign-in or DROPL_API_KEY; it never returns the full key.
  • list_sitesLists the client sites (one per client website) this connection can reach, with their domains and the plan's site allowance. Use it before creating anything, to find the site id for the client the user means and avoid duplicate sites. Keys restricted to some sites only see those sites.
  • create_siteCreates a client site: the home for one client website's showcases, videos, collections, and feedback. Use it when the client has no site yet; check list_sites first to avoid duplicates. Only call after showing the plan to the user and getting explicit confirmation. Counts toward the plan's site allowance; safe to retry, since the same name and domain return the same site.
  • list_showcasesLists a client site's showcases (embeddable photo and video galleries), newest first, with their type (gallery or projects) and item and project counts. Use it to reuse an existing gallery or portfolio instead of creating a duplicate, or to find a showcase id. Paged: pass nextCursor to get more.
  • create_showcaseCreates a showcase: an embeddable photo/video gallery the client can update from their phone. Use it when the user wants a gallery, portfolio, project photos, or a section the client can update themselves. Requires a site id from list_sites or create_site. Only call after showing the plan to the user and getting explicit confirmation. Use type: "projects" for a portfolio where each project gets its own page, photos, and details (then create_project for each); the type can't change once the showcase has items. Turn on showCategoryFilters when items or projects will be grouped into categories. Safe to retry with the same arguments.
  • get_showcaseSummarizes a showcase: type, settings, item counts by status (processing/ready/failed) and kind, project counts and details (projects showcases), categories with counts, photos without alt text, and failed items. Use it to check that an upload finished processing or to review a gallery before changing it. It returns counts, not items: use list_showcase_items for ids, alt text, and categories, or list_projects for projects.
  • list_showcase_itemsPages through a showcase's items in display order: id, kind, status, file name, the local path it was uploaded from, alt text, and categories. Use it to find item ids for update_items or tag_items, or photos that still need alt text (missingAlt: true). Up to 200 items per call; local paths only appear for files uploaded from this machine.
  • update_itemsSets alt text and adds/removes categories on many showcase items in one call. Use it after an upload to fix alt text or categories by id (files[].id from upload_photos / upload_videos, library video ids, or ids from list_showcase_items) instead of uploading again. Up to 1000 items per call; category names that don't exist yet are created. Alt text: Write concise, descriptive alt text: what the photo shows (e.g. "Cedar deck with glass railing at dusk"), without "image of" or "photo of". Leave it empty for purely decorative photos. Show the user the alt text you plan to write before saving a large batch.
  • update_showcaseChanges a showcase's title, layout, grid fit, category filter tabs, or items per page. Use it when the user wants the gallery to look or page differently; embeds pick up the change without new code. Pass only the settings to change; at least one is required.
  • create_categoryAdds a category (a filter tab) to a showcase. Use it to group items, e.g. one category per project type or source folder, before tagging them; upload and tagging tools also create missing categories by name. If one with the same name or slug exists, it's returned instead of creating a duplicate.
  • tag_itemsAdds and/or removes the same categories on many showcase items (photos or videos) at once. Use it to put uploaded items into filter tabs, with itemIds from upload_photos / upload_videos (files[].id; library video ids work too) or list_showcase_items. Up to 1000 items per call; category names that don't exist yet are created. For per-item changes or alt text, use update_items.
  • upload_photosUploads local photos (JPEG, PNG, WebP, AVIF, HEIC; up to 20 MB each) into a showcase, straight to storage. Use it to turn a folder of project photos into a client-editable gallery: pass files, folders (recursive by default), and globs via paths, and per-photo alt text and categories via files. Skips hidden files and validates file contents. Run with dryRun: true first and show the result to the user; Only call after showing the plan to the user and getting explicit confirmation. Resumable: re-running with the same arguments skips files already uploaded (and still applies changed alt text and categories). categoryFromFolder tags each photo with its top-level folder's name; categories tags every photo (both created if missing). In a projects showcase, pass project: the photos join the end of that project (categories belong to the project there, not to photos); the same file can go into several projects. Returns files: each local path with its showcase item id and status, for update_items and tag_items. Alt text: Write concise, descriptive alt text: what the photo shows (e.g. "Cedar deck with glass railing at dusk"), without "image of" or "photo of". Leave it empty for purely decorative photos.
  • +26 more on the listing page

OpenFlow tools 49

  • generate_with_faceGenerate 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.
  • generate_imageGenerate 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): BELUGA = "Nano Banana 2" — the DEFAULT, ~30s (legacy id NARWHAL is accepted as an alias) 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: up to 10 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.
  • music_generateGenerate 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_chatTalk 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_stemsSplit 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.
  • music_listList the user's music tracks.
  • music_getGet metadata for a single music track.
  • music_downloadDownload the raw .m4a file of a track to the server.
  • music_creditsCheck remaining flowmusic credits and subscription tier.
  • generate_sceneBuild 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), SQUARE, PORTRAIT_THREE_FOUR (3:4) or LANDSCAPE_FOUR_THREE (4:3). 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_videoGenerate 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'. beats: how many DISTINCT action phases the prompt describes — "ears flick back", "tail lashes", "strikes the ball", "ball flies off" are four. Give it and the server picks the clip length for you (about two phases per second) and says in the reply what it picked and why. Measured 31.08.2026: the model STRETCHES whatever you describe over whatever length you ask for, so one phase in four seconds comes out as slow motion, and the same text at six seconds instead of four loses 15% of its movement. Adjectives are not phases: "springy cartoon motion" adds nothing. Leave beats out and the length you passed is used unchanged. seed (all video tools): the result always reports the seed it used. Same seed + same prompt + same inputs = the same clip, so a good take can be re-made. A fixed seed does NOT keep the composition when the prompt changes — use edit_video for that.
  • edit_videoRewrite a video from a plain description: "make the sky stormy", "take the passer-by out of the shot", "warmer light", "put the product from the image on the table". Source — ONE of: media_id: id from a previous generate_video* result (OUR OWN generation). Job is pinned to the account that produced it. video_base64: base64-encoded YOUR OWN clip (mp4/mov/avi/3gp, up to 60s/1GB). Worker uploads it via Flow's Scotty resumable upload (reversed via Flow Web Ingredients, 2026-10-14) onto a healthy account, then runs the edit on that account. The upload itself costs no credits. start_sec / end_sec: edit only this piece of the source (both or neither, at most 10 s). The result is ONLY that piece — not the full clip with the piece replaced. reference_images_base64: up to 5 raw base64 images (no data: prefix); the object in the image is put into the clip — say in the prompt what to do with it. 20 credits per edit (abra_edit_360p: 10). Not a mask tool — describe the change and where it goes ("on the left", "in the sky"); mask/style image types are not honored. Prompt template that lands best — fill each part, one or two sentences each: Goal: what changes ("Replace the man on the left with the character from image 1"). Source: "The source video drives camera, motion, timing and lip movement." Reference: what to take from each image ("use only the character's look; ignore the image background"). Scene: describe the room/background in words (helps the model keep it intact). Keep: "Everything else stays exactly as in the source." Timing: "The new character inherits the exact movement and position of the one it replaces, from the first frame to the last." Draft on abra_edit_360p (10 credits) to check the edit lands, then run abra_edit; the seed does not carry an edit take across resolutions, so the final can differ in details. Only edit footage the user owns or is licensed to use; do not put real people's likeness into clips without their consent.
  • +37 more on the listing page

Ready-to-paste client configs

Paste either block (or both) into your client config, e.g. claude_desktop_config.json or ~/.cursor/mcp.json. We only show a config when the install command is confirmed.

Dropl MCP

mcpServers (Claude Desktop / Cursor)
{
  "mcpServers": {
    "dropl-mcp": {
      "command": "npx",
      "args": [
        "-y",
        "@dropl/mcp"
      ],
      "env": {
        "DROPL_API_KEY": "YOUR_DROPL_API_KEY_HERE"
      }
    }
  }
}

OpenFlow

mcpServers (Claude Desktop / Cursor)
{
  "mcpServers": {
    "openflow": {
      "url": "https://openflowmcp.com/mcp"
    }
  }
}

Frequently asked questions

Dropl MCP is categorized under Multimedia Process and uses a local stdio subprocess. OpenFlow belongs to Multimedia Process and uses a remote HTTP/SSE transport. Pick Dropl MCP for multimedia process work and OpenFlow for multimedia process.

Copy the mcpServers block from the config section on this page into your client's config (for example claude_desktop_config.json or ~/.cursor/mcp.json), then fully restart the client.

Dropl MCP has no declared pricing — check the project's own site. OpenFlow has no declared pricing — check the project's own site. If a server needs environment variables such as API keys, define them under the env key in your client's MCP config.

Yes. MCP clients support multiple servers: add dropl-mcp and openflow as separate keys in the same mcpServers object, and your assistant will call tools from either one.

On AllMCPs, Dropl MCP has a quality signal of 61/100 (Good) with 1 views, 0 installs and 1 GitHub stars. OpenFlow has 60/100 (Good) with 1 views, 0 installs and 8 GitHub stars.