Skip to content
verify mcp Beta VerifyMCP is currently in beta. If you notice any issues, get in touch and we’ll put it right.

FilmLab

REMOTE · MCP-LAB.THEFILMRADAR.COM · SCANNED OCT 5

AI film lab for filmmakers: generate and review images/clips with input provenance, cost preflight

+40 this week 76 Trust /100
Trust breakdown (7 categories)

How this component scores in each security and reliability category. Every signal is checked automatically against the live server, and we only credit what we can confirm. How we score → Why this is hard to score →

Endpoint Security89
Transport & Reachability100
Schema Quality & AI Usability76
  • 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).Pass
  • AI-judged instruction clarity (excellent).Pass
  • Context-footprint check failed: tool/resource definitions use about 32442 tokens (~345/item across 94 items; 93 tools + 1 resources), over budget; trim descriptions and params. See how to fix → Fail
  • Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management3
  • Stability check failed: schema churn in the 1 day we've observed: 0 tool removals, 1 breaking changes, 0 auth/transport breaks, 4 additions. See how to fix → Fail
Tool Coverage100
  • 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
  • 100% of tool parameters carry a description.Pass
Tool Safety75
  • No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
  • All 1 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation.Pass
  • Manipulation not yet verified: none of the 95 captured unit(s) of tool text has been judged yet, so we will not certify text no model has read as clean.Unverified
Capabilities100
  • Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.Pass
  • Supports UI / widget rendering.Pass
Install

How do I install the FilmLab MCP server?

FilmLab is a hosted endpoint at https://mcp-lab.thefilmradar.com/mcp, so there is nothing to install locally. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

remote · mcp-lab.thefilmradar.com

# add to Claude Code
claude mcp add --transport http com-thefilmradar-filmlab 'https://mcp-lab.thefilmradar.com/mcp'
// .cursor/mcp.json
{
  "mcpServers": {
    "com-thefilmradar-filmlab": {
      "url": "https://mcp-lab.thefilmradar.com/mcp"
    }
  }
}
// .vscode/mcp.json
{
  "servers": {
    "com-thefilmradar-filmlab": {
      "type": "http",
      "url": "https://mcp-lab.thefilmradar.com/mcp"
    }
  }
}
# ~/.codex/config.toml
[mcp_servers.com-thefilmradar-filmlab]
url = "https://mcp-lab.thefilmradar.com/mcp"
// opencode.json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "com-thefilmradar-filmlab": {
      "type": "remote",
      "url": "https://mcp-lab.thefilmradar.com/mcp",
      "enabled": true
    }
  }
}
# add to OpenClaw
openclaw mcp add com-thefilmradar-filmlab --url 'https://mcp-lab.thefilmradar.com/mcp' --transport streamable-http
# ~/.hermes/config.yaml
mcp_servers:
  com-thefilmradar-filmlab:
    url: "https://mcp-lab.thefilmradar.com/mcp"
// ~/.netclaw/config/netclaw.json
{
  "McpServers": {
    "com-thefilmradar-filmlab": {
      "Transport": "http",
      "Url": "https://mcp-lab.thefilmradar.com/mcp"
    }
  }
}
# add to Vellum
assistant mcp add com-thefilmradar-filmlab -t streamable-http -u 'https://mcp-lab.thefilmradar.com/mcp'
// mcp.json
{
  "mcpServers": {
    "com-thefilmradar-filmlab": {
      "type": "http",
      "url": "https://mcp-lab.thefilmradar.com/mcp"
    }
  }
}

The mcpServers block is a cross-client convention. Remote transports vary, so check your client's docs.

Changelog

Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.

  • 5 Oct 26 0
    • Stability: unverified → fail ▼ security
    • The server rewrote its instructions, which are the text every model session reads security
    • Tool “lab_whoami” rewrote its description, which is the text the model reads security
  • 4 Oct 26 +40
    • Transport: unverified → pass ▲ security
    • Injection markers: unverified → pass ▲ security
    • First check of Judged manipulation: unverified security
    • Authorization: Authorisation is enforced on tool calls, advertised via RFC 9728 protected-resource metadata. Discovery is public, which costs nothing: no tool can be invoked without a token. security
    • MCP protocol: unverified → pass ▲ functional
    • Schema quality: unverified → 100 ▲ functional
    • Tool coverage: unverified → 100 ▲ functional
    • First check of Schema quality: fail functional
    • First check of Schema quality: excellent functional
    • First check of Schema quality: fail functional
    • First check of Capabilities: pass functional
    • First check of Destructive annotations: 100 functional
    • First check of Tool coverage: 100 functional
  • 28 Sept 26 0
    • We updated how we score, so this day's move reflects our rubric, not a change to the server See what changed → functional
  • 25 Sept 26 0
    • We updated how we score, so this day's move reflects our rubric, not a change to the server See what changed → functional
  • 26 Aug 26 0
    • We updated how we score, so this day's move reflects our rubric, not a change to the server See what changed → functional
  • 17 Aug 26 0

    First indexed and scored.

Diagnostics

Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.

Captured 7 Oct 2026 · Probed https://mcp-lab.thefilmradar.com/mcp

TLS valid

Negotiated TLS 1.3 with TLS_AES_128_GCM_SHA256 .

Subject Issuer Valid from Valid until Key Signature Serial
CN=thefilmradar.com CN=WE1,O=Google Trust Services,C=US 6 Sept 2026 5 Dec 2026 ECDSA 256 ECDSA-SHA256 e40c48743b6b9189133ceb0cd0ece3c0
SANs: thefilmradar.com, mcp-lab.thefilmradar.com, *.mcp-lab.thefilmradar.com
CN=WE1,O=Google Trust Services,C=US (CA) CN=GTS Root R4,O=Google Trust Services LLC,C=US 13 Dec 2023 20 Feb 2029 ECDSA 256 ECDSA-SHA384 7ff31977972c224a76155d13b6d685e3
CN=GTS Root R4,O=Google Trust Services LLC,C=US (CA) CN=GlobalSign Root CA,OU=Root CA,O=GlobalSign nv-sa,C=BE 15 Nov 2023 28 Jan 2028 ECDSA 384 SHA256-RSA 7fe530bf331343bedd821610493d8a1b

Background: What to check on a remote MCP endpoint →

DNSSEC insecure

Validation of mcp-lab.thefilmradar.com. — Not signed

Zone DS Keys Algorithms Outcome
. trust_anchor 20326, 38696 8, 8 Verified
com. present 19718 13 Verified
thefilmradar.com. absent Unsigned (proven) parent-signed NSEC/NSEC3 proves an unsigned delegation
Authentication Enforced and verified

The endpoint asked for a token and published valid RFC 9728 metadata describing how to get one.

Result Enforced and verified
Enforced On tool calls
HTTP status 200

WWW-Authenticate challenge Bearer realm="OAuth", resource_metadata="https://mcp-lab.thefilmradar.com/.well-known/oauth-protected-resource/mcp", scope="filmlab:read filmlab:write"

Bearer realm="OAuth", resource_metadata="https://mcp-lab.thefilmradar.com/.well-known/oauth-protected-resource/mcp", scope="filmlab:read filmlab:write"

Protected resource metadata

Document https://mcp-lab.thefilmradar.com/.well-known/oauth-protected-resource/mcp
Retrieved Yes
Resource https://mcp-lab.thefilmradar.com/mcp
Authorisation server https://mcp-lab.thefilmradar.com

Background: How OAuth 2.1 works in the 2026 MCP spec →

Transports 2 probes
Transport URL Outcome Status Location
streamable-http https://mcp-lab.thefilmradar.com/mcp Verified 200
http (plaintext) http://mcp-lab.thefilmradar.com/mcp HTTPS enforced 301 https://mcp-lab.thefilmradar.com/mcp
MCP tools · 111 exposed · ~39,090 tokens

The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →

Tool Tokens
lab_abgleich ~219

Prompt check of ONE generated image or clip: does the result show what its prompt asked for? The backend first DESCRIBES the result without seeing the prompt, then splits the prompt into checkable claims (counts as digits, quoted text, identity, place, framing, style; for clips the motion) and scores each. verdict: pass | mismatch | unverified, plus `checks`, `issues` and the neutral `beschreibung`. Runs automatically after every generation (lab_job_status shows it as `abgleich`); call this to read it, or with neu=true to check again. On mismatch: offer at most ONE retry per original, lead the new prompt with the failed claim; never re-run a video on your own. Free for the account (FilmLab carries the cost).

NameTypeReqDescription
idstringyesAsset id (positive integer as string)
neuboolean–Discard an existing result and check again (ignored within 60 s of the last check)
reference_typestringyesWhat kind of asset

No output schema declared.

No examples provided.

lab_add_clip ~529

Append a shot to a sequence's timeline. Call it once per shot, in cutting order — `start_time` is computed from the clips already there, so appending in order is enough. The continuity pass reads exactly this timeline: a shot missing here is a shot nobody checks. Returns the new clip's index and the sequence's total duration.

NameTypeReqDescription
duration_secondsnumber–Clip duration in seconds. Backend default is 5.0 — pass the clip's REAL length, otherwise the sequence duration and the render drift apart
metadataobject–JSON stored alongside the clip. The continuity pass reads video_id (a generated video's id — it checks the start image), image_url (a frame URL), location_id and scene_num from here; for a 'lower_thi…
seq_idstringyesSequence id (from lab_create_sequence/lab_list_sequences) — positive integer as string
source_idstring–For type 'image': the id of a generated image (from lab_generate). For type 'video': source_id is IGNORED by the continuity pass (a video id used to be misread as an unrelated image, see vault/follow…
start_timenumber–Absolute start on the timeline. Omit to append after the last clip (the normal case); set it only to place a clip deliberately
textstring–Text content for type 'title', 'credits' or 'lower_third'
typestringyesWhat this clip is. 'image' references a generated image via source_id; 'title', 'credits' and 'lower_third' carry `text` instead. 'lower_third' is an OVERLAY: appended without start_time it is laid o…

No output schema declared.

No examples provided.

lab_add_media ~486

Bring your own video, audio or image into a project — not generated, yours. Two ways: `media_url` (a public http(s) address; the server fetches it, max 100 MB) or `file_name` + `content_type` (you get a signed `upload_url` and the `header` that are part of its signature: PUT the file's raw bytes there within the hour with EXACTLY those headers — the answer's `anleitung` has the ready curl line; a missing header is a 403). Either way the answer is the `asset_key` — use it in lab_timeline_apply as clips[].asset_key (video) or bett.asset_key (audio). Exception: in projects that check images, an uploaded image is not in the project after the PUT — the answer then carries `abschluss_noetig` and an `abschluss_key`; after the PUT call lab_add_media again with the same project_id, art, herkunft and `abschluss_key` only. That call checks the image and returns the `asset_key`, or says why it was refused. Free. Internal addresses are refused.

NameTypeReqDescription
abschluss_keystring–Only after an upload whose answer said `abschluss_noetig`: the `abschluss_key` from that answer, given AFTER the PUT returned 200. Give it instead of media_url and file_name
artstringyesWhat the file is
content_typestring–Media type of the upload, e.g. video/mp4, audio/mpeg — required with file_name
file_namestring–Name of a local file to upload, with extension. Give this OR media_url
herkunftstringyesRequired, no default: 'eigen' = shot, recorded or made by people (no AI generation); 'ki' = generated or altered with AI. Decides the EU AI Act Art. 50 disclosure of every export that uses this file.…
media_urlstring–Public http(s) URL of the file. Give this OR file_name
project_idstringyesProject id (from lab_list_projects) — positive integer as string

No output schema declared.

No examples provided.

lab_analyze_location_image ~124

Read a photo and extract location fields from it (Gemini Vision, costs quota). Returns the fields — it does NOT create a board; feed the result into lab_create_location yourself. Note the payload: the image travels as base64 inside the call, so keep it small (a downscaled JPEG, not a full-resolution capture).

NameTypeReqDescription
image_base64stringyesThe image as base64. A data-URL prefix ('data:image/jpeg;base64,…') is stripped by the backend
mime_typestring–Defaults to 'image/jpeg'

No output schema declared.

No examples provided.

lab_animate ~2,629

Animate a completed image into a clip with a video model. Pick the model from lab_list_models; check the price with get_cost or let the user confirm a card via lab_propose. Costs credits when called without get_cost.

NameTypeReqDescription
abdruck_startframeboolean–Generate frame one WITH the character's trained Figurenabdruck (LoRA) instead of taking the flat studio portrait from the character sheet — the clip then starts IN the scene rather than in a photo st…
apply_lensboolean–Defaults to TRUE on the backend: the project's lens_state UrPrompt is appended to the prompt. Pass false only to deliberately opt out for this one call.
audio_urlstring–URL of an existing audio track to lay under the clip. Independent of generate_audio, which asks the PROVIDER to synthesise its own.
camera_motionstring–Structured camera move sent to the model itself — only models whose lab_list_models entry lists camera_motions. Prefer this over prose when a keyframe chain must MOVE rather than cross-fade.
character_refsarray–Character ids (positive integer strings) whose reference image locks the cast's identity for this clip. On most providers only the FIRST character's image is used, as the start frame — with two chara…
character_statesobject–Which STATE each character is in for this clip, as { characterId: stateKey } — e.g. { "12": "wet" }. A state is its own asset with its own full descriptor (clean / soaked / bloodied are three assets,…
character_voicesobject–Bind a voice per character: character id -> fal voice id. Voice ids come from fal-ai/kling-video/create-voice — FilmLab keeps no voice registry of its own, the id is passed through unverified. Every…
duration_secondsnumber–Clip length in seconds. Must lie inside the model's duration grid from lab_list_models; inside the grid the provider may snap to its nearest step. IGNORED when `shots` is given — then the rendered le…
end_image_idstring–id of a completed image to land the clip on (last frame). REQUIRES a start frame (source_image_id or character_refs) — an end frame alone is rejected before quota is spent. Only kling_3_pro.
familiestring–Pick the MODEL, not the access route: 'seedance-2.0' or 'seedance-2.5'. The server takes the cheapest route that this account may use and that can do the job (OpenRouter only with the user's consent;…
generate_audioboolean–Ask for the model's native audio track. Only meaningful where lab_list_models says audio: schaltbar — models with audio: immer always have it, audio: nie never.
get_costboolean–Preflight: return the price in credits and your balance WITHOUT generating, reading the same catalog as lab_list_models. Do this before a batch or when the user wants to see the cost. For a card the…
in_secnumber–Cut the reference clip server-side before it reaches the provider: start of the excerpt, in seconds from the clip's beginning. Only together with out_sec, and only with source_video_id.
intentstring–Say WHAT the shot is instead of picking a model — the router chooses by priority and a cost cap. 'draft' and 'ambient' route to the cheapest provider, 'dialog' to the one with the steadiest faces, 'h…
kamerapfadobject–The camera move as INPUT instead of prose: an object following shared/kamerapfad/schema.json — poses over time (position, look-at or quaternion, metres, Y up) from the Kadrage terrain flight or drawn…
kamerapfad_urlstring–Address of a kamerapfad JSON instead of the object — the url of a file in THIS project (lab_list_assets), e.g. the kamerapfad JSON that Kadrage writes next to its flight video. Fetched by the backend…
location_idstring–Location board id (from lab_list_locations). The board's `prompt_prefix_en` is appended to your prompt as 'Location: …', so a clip stays in the same place as the images shot there. A board WITHOUT a…
metadataobject–Free-form JSON stored alongside the video. Not interpreted by the pipeline.
ohne_keyframeboolean–Skip the keyframe checkpoint on purpose. By default a paid clip only starts from a start image the user has approved (lab_review_asset verdict: accepted) — look at the frame first, then spend on the…
out_secnumber–End of the excerpt in the reference clip, in seconds. Must lie behind in_sec; both are set together or neither. Only with source_video_id.
project_idstringyesProject id (from lab_list_projects)
promptstringyesMotion/camera instruction for the animation
referenzenarray–Typed references for the clip path (source_video_id). The position IS the address: the first image is @Image1, the first extra clip is @Video2 (the reference clip itself is @Video1), the first sound…
resolutionstring–Resolution tier, exactly as listed for the model in lab_list_models. Omit for the model's default. Some models have no resolution field at all — then leave it out.
scene_refstring–Scene label (e.g. 'SZ 04'). Stored on the row, so clips can be matched back to a shot list and reviewed per scene with lab_review_queue.
seedinteger–Seed for a repeatable run. Omit it and the project's stored seed applies (POST /api/lab/projects/{id}/einstellungen), and without that the provider picks one. The seed that actually rendered comes ba…
shot_typestring–How to cut a multi-shot clip. 'customize' (default) renders exactly the shots you gave. 'intelligent' lets the model decide the cutting — your shot prompts become a suggestion, not a spec. Belongs to…
shotsarray–Multi-shot: a sequence of shots rendered as ONE output, holding character, place and voice across the cuts. This is NOT the same as several clips stitched together — those you pay for individually an…
source_image_idstring–id of a completed image (from lab_generate/lab_job_status) to animate — positive integer as string. Required unless get_cost is true
source_video_idstring–Animate FROM A CLIP instead of a still: the id of a generated video (from lab_animate/lab_job_status) or the asset key of an uploaded one (from lab_list_assets, asset_type 'video'). The run then goes…
toolstring–Video model id — copy it verbatim from lab_list_models (kind: video). Omit to let the intent router choose. Every model has its own resolutions, duration grid, audio behaviour and price; the catalog…

No output schema declared.

No examples provided.

lab_animate_batch ~276

Animate MANY images into videos in ONE call (max 25 jobs). Prefer this over looping lab_animate: it validates every job BEFORE spending any quota, so an invalid job 12 of 15 does not leave 11 paid-for generations running. Quota is spent once, collectively (one ledger row); refunds stay per-clip, so a partial failure refunds only that clip. Returns a batch_id — poll lab_batch_status with it instead of polling each id separately. `get_cost: true` preflights the whole batch without generating anything.

NameTypeReqDescription
get_costboolean–Preflight: return the summed price in credits for the WHOLE batch and your balance WITHOUT generating, reading the same catalog as lab_list_models. For a card the user confirms, use lab_propose inste…
jobsarrayyesOne entry per clip, max 25. All jobs are validated before any quota is spent
ohne_keyframeboolean–Skip the keyframe checkpoint on purpose. By default a paid clip only starts from a start image the user has approved (lab_review_asset verdict: accepted) — look at the frame first, then spend on the…
project_idstringyesProject id (from lab_list_projects)

No output schema declared.

No examples provided.

lab_apply_rhythm ~518

Compute the sequence's clip durations from the project's cutting preset and — when the tempo allows it — pull the cut points onto the measured beat grid. WRITES the timeline; costs nothing. The old duration of every changed clip is kept in `clip.metadata.dauer_vorher`, so one undo step exists (a second differing run overwrites it — there is no history). Clip count is never changed: no clip is added or removed. SNAPPING IS NOT GUARANTEED, AND A REFUSAL TO SNAP IS A RESULT, NOT A FAILURE — read `gerastet` and `raster.grund` before you repeat anything: 'tempo_unverlaesslich' = measured below the confidence threshold (deliberate; pass trotz_unsicherem_tempo to override), 'nicht_gemessen' = run lab_beatgrid first, 'keine_musikspur'/'musikspur_nicht_aufgeloest' = run lab_bind_audio first, 'rhythmus_ohne_raster' = the preset's rhythm is 'frei' or 'atmend', which means not snapping IS the promise ('auf den Beat', 'auf die Songstruktur' and 'gegen den Takt' are the three that snap), 'toleranz_null' = you passed toleranz_s 0. In every one of those cases the durations are still recomputed from the preset and written — that alone is the difference between 40 and 6 cuts over 30 seconds. Also read `raster.getroffen` of `raster.von`: `gerastet: true` only says snapping ran; this pair says whether it landed. And `geklemmt` lists clips the renderer's own duration clamp moved back OFF the grid.

NameTypeReqDescription
seq_idstringyesSequence id (from lab_create_sequence/lab_list_sequences) — positive integer as string
toleranz_snumber–How far a cut point may travel to land on a beat, in seconds (default 0.12 — three frames at 25 fps). 0 disables snapping entirely and only recomputes the durations
trotz_unsicherem_tempoboolean–Snap onto a grid whose own measurement reports `verlaesslich: false`. Default false, and that default is the honest one: below the threshold the detector has not confirmed it found the pulse. Set it…

No output schema declared.

No examples provided.

lab_auto_lauf ~312

Auto run with a hard spending cap: the person approves ONE run with an upper limit in credits; inside it you may generate without asking per item, but never above the cap. aktion: anlegen (project_id + deckel_credits → status 'angelegt', nothing can be spent yet) · freigeben (ONLY after the person explicitly approved the cap) · stand (cap, reserved, free, items) · beenden. While a run is active, EVERY paid call in that project reserves its price against the cap — whichever tool makes it; reservations are never refunded (a failed item keeps its share, a retry reserves again), upscales and exports count too. The cap counts credits: runs on the person's OWN provider key (BYOK, 0 credits) are not counted. Other projects are not affected. When the cap would be crossed the backend answers budget_exceeded: stop, report what finished, what is open and the minimum budget still needed. Under budget pressure lower the resolution first, never cut runtime, never drop character or location variants.

NameTypeReqDescription
aktionstringyesWhat to do
deckel_creditsinteger–anlegen only: the cap in credits. Name it to the person in credits AND in the price list's terms before freigeben
lauf_idstring–freigeben / stand / beenden: the id from anlegen
project_idstringyesProject id (from lab_list_projects)

No output schema declared.

No examples provided.

lab_auto_storyboard ~521

Auto-generate a storyboard from a script: an LLM splits the script into scenes, then one storyboard frame is generated per scene. COSTS CREDITS — every scene is one generated image, charged up front for the number of scenes the script is split into (at most max_scenes). Ask the human before running it. CHARACTERS ARE NOT GUESSED: every character who appears in more than one frame first gets a reference image (an existing project character with a reference is reused for free; a new one is created and its reference sheet is charged separately as character_sheet_generate), and every frame showing such a character is generated WITH those references on seedream_5_pro instead of `model`. Frames without a recurring character use `model`. The answer lists `figuren` (name, status, scenes), `figuren_kosten_geschaetzt` and `kosten_je_bild`; prices per model come from lab_list_models. If a reference cannot be made, the frames that need it fail and are refunded — they are never generated without it. The scene split is SYNCHRONOUS and can take up to ~55s and then time out (504) for long scripts; run it in the app if so. The answer lists the new image ids; the frames themselves render in the background as pending images — poll them with lab_job_status (type 'image').

NameTypeReqDescription
creativitystring–Krea 2 creativity setting; ignored by flux_pro. Default medium.
figuren_ratenboolean–Opt-out, off by default: true skips the character references and lets the image model invent every character from the text — a different face in every frame. Only set it when the human explicitly ask…
max_scenesinteger–Upper limit for the number of scenes, and therefore images charged. Backend default when omitted.
modelstring–Image model for the frames. Default krea_2_medium. Prices per model: lab_list_models.
project_idstringyesProject id
scriptstringyesScreenplay or scene description to storyboard. Required — the backend splits it into scenes; each scene becomes one image.
style_reference_urlstring–Shared moodboard image applied to ALL frames for one consistent look. Used by the Krea 2 models only. Must be an asset of this project or an absolute URL — anything else is refused before credits are…

No output schema declared.

No examples provided.

lab_batch_status ~121

Aggregated progress of a video batch started by lab_animate_batch. Returns {total, completed, failed, pending, done, items[]} — poll this ONCE per batch instead of calling lab_job_status per clip. `done: true` means nothing is pending any more (some items may still have failed). Each item carries retry_count (an automatic second attempt happened) and fallback_from (the provider was swapped after a content-policy rejection).

NameTypeReqDescription
batch_idstringyesThe batch_id returned by lab_animate_batch (format: vb_<hex>)

No output schema declared.

No examples provided.

lab_beatgrid ~588

Measure the TEMPO of the sequence's bound music track and store the beat grid — opens the real file with ffmpeg and analyses it, no guessing and no provider, so it costs nothing but a few seconds. Writes `bpm` and `metadata.beat_grid` on the audio row; it does NOT touch the timeline (`timeline_geaendert: false`). Deterministic and cached: a second call returns the same numbers without downloading again (pass `neu_messen` to force). READ `confidence` AND `verlaesslich` BEFORE YOU CUT. Below the threshold (0.35) lab_apply_rhythm computes durations but deliberately does NOT snap them to the grid — that is a decision, not a failure. Soft material measures badly: a real swing track came out at 0.164, an ordered hard pulse (techno, 128 bpm) at 0.621. Half and double tempo are the classic misreads, so `bpm_alternativen` is part of the answer. `frame_konflikt` reports the collision between beat grid and frame grid, for BOTH renderers: `export` (24 fps, the delivered MP4) and `murnau` (25 fps, the editor timeline). Read `frames_pro_schlag` as a DEVIATION, not a count: it is how far one beat sits from a whole frame, between 0 and 0.5. 0 means beat and frame coincide (100, 125 and 150 bpm at 25 fps do); anything above means beat-accurate and frame-accurate cannot both hold, and the rounding error accumulates across clips — measured on a finished MP4 at 128 bpm: up to 64.7 ms off the audible beat although every cut point had snapped. Shown here, not fixed: that decision belongs to a human. Refusals that name their own remedy: 409 without a bound music track (run lab_bind_audio), 409 when the track is pending (poll lab_list_audio), 502/504 when the audio host is unreachable or slow, 422 when the file carries no usable audio, 503 when ffmpeg is missing.

NameTypeReqDescription
neu_messenboolean–Measure again even though a result for this exact file already exists. Default false. The measurement is deterministic — the same file gives the same number, so this only helps after the track behind…
seq_idstringyesSequence id (from lab_create_sequence/lab_list_sequences) — positive integer as string
taktinteger–Beats per bar (default 4). INPUT, not detection — time-signature detection is explicitly out of scope. It only affects where the downbeats fall, which is what the rhythm 'auf die Songstruktur' snaps…

No output schema declared.

No examples provided.

lab_bilder ~299

See a clip at EXACT seconds: up to 12 frames, in the order you list them, tiled into one image and shown. Use it to check what is on screen where you plan a cut, whether a motion has ended, or whether a face drifted between two moments — lab_contact_sheet spreads frames evenly and cannot answer 'what is at 3.2 s'. A second past the clip's end is rejected by name, not clamped. Works on generated clips (video_id) AND on your own uploaded footage (project_id + asset_key from lab_add_media) — look at it before you cut it. Free (no credits).

NameTypeReqDescription
asset_keystring–Storage key of uploaded footage (from lab_add_media / lab_list_assets). Needs project_id
kachel_breiteinteger–Width of one frame in px (default 480)
previewboolean–Show the image inline (default true)
project_idstring–Project the asset_key belongs to — required with asset_key
sekundenarrayyesSeconds into the clip, e.g. [0.5, 3.2, 3.24]. Order is kept: left to right, then the next row (4 per row)
video_idstring–Generated video id (from lab_animate/lab_job_status) — positive integer as string. Give this OR asset_key

No output schema declared.

No examples provided.

lab_bind_audio ~278

Bind the project's generated audio to a sequence's tracks — ONE call that does both halves of the job, because doing only the first half silently produces a silent film. Half one (`POST …/soundmix`) creates the four empty tracks (dialog, music, sfx, atmo); half two (`POST …/soundmix/resolve-stems`) is what actually attaches the audio rows to them. On 2026-08-28 that split cost a complete silent export: the mix looked configured, and every track was empty. From here it is one tool, and it is idempotent — an existing mix is NOT re-initialised (that would throw away volumes, effects and the other tracks' bindings), only re-resolved. Per track it takes the audio row marked `selected`, otherwise the newest one with a url. Rows still pending have no url and stay unbound. That choice is re-made on every call: generate a second music track and run this again, and the music track follows the NEWER row — unless one row is pinned with `selected`, which is set in the web UI, not from here. Changes state, costs nothing. Next: lab_beatgrid.

NameTypeReqDescription
seq_idstringyesSequence id (from lab_create_sequence/lab_list_sequences) — positive integer as string

No output schema declared.

No examples provided.

lab_capture ~308

See the CUT at exact seconds of the finished film: up to 12 frames, tiled into one image and shown. Each second is mapped like the export maps it — which clip is on screen, where in its source (src_in_s counts), the export's framing (scaled and letterboxed), title cards drawn. A video whose source is shorter than its clip duration ends early in the export, and everything after it moves forward; this tool follows that, so you see the film that will be rendered. The answer names per frame the clip (position, clip_id), clip start and offset; a clip that would render black says so ('schwarz'). NOT in the image: lens/grade, lower thirds, the AI badge — that needs lab_start_export. Use it after lab_timeline_apply to check cut points before exporting. Free (no credits).

NameTypeReqDescription
kachel_breiteinteger–Width of one frame in px (default 480)
previewboolean–Show the image inline (default true)
profilestring–Export profile key (default 'web'); a 9:16 profile gives portrait frames — see lab_export_profiles
sekundenarrayyesSeconds into the finished film, e.g. [0.5, 4.9, 5.1]. Order is kept: left to right, then the next row (4 per row)
seq_idstringyesSequence id — positive integer as string

No output schema declared.

No examples provided.

lab_cast_autopopulate ~144

Create character sheets for the people found in a project's material — the writing counterpart to lab_cast_gaps. Creates at most 6 per call and binds each to the project. Costs an LLM run per call. Run lab_cast_gaps first if you want to see what it would create. The sheets it creates have NO reference image: each one still needs lab_generate_character_reference before lab_generate accepts it as `character_refs`. Fail-open: no script or no AI key returns an EMPTY `created` list with a `note`, not an error.

NameTypeReqDescription
project_idstringyesProject id (from lab_list_projects) — positive integer as string

No output schema declared.

No examples provided.

lab_cast_gaps ~147

Find people who appear in a project's material (script / cast module) but have NO character sheet yet. Returns up to 6 `missing` entries, each with a name and a short hint from the text. It creates nothing — lab_cast_autopopulate does that. Costs an LLM run, so it is credit-gated. Fail-open by design: no script, no AI key, or an unparseable answer all come back as an EMPTY list (with a `note` saying which) — an empty list is the correct answer, not an error.

NameTypeReqDescription
project_idstringyesProject id (from lab_list_projects) — positive integer as string

No output schema declared.

No examples provided.

lab_contact_sheet ~282

Build a contact sheet for a generated clip — N frames spread evenly over its runtime, tiled into ONE image — and show it. This is how a clip gets judged at all: MCP has no video content type, so without a sheet a clip is just a URL and a promise. It is also the fastest way to SEE camera drift: measured 2026-08-04, the wander in one clip was a PSNR number until frames sat side by side. The sheet is cached on the video row — a second call returns the same URL without re-rendering (pass force to redo it). Rendering downloads the clip and runs ffmpeg, so the first call takes a few seconds.

NameTypeReqDescription
colsinteger–Grid columns (default 3)
forceboolean–Re-render even if a sheet already exists
previewboolean–Attach the sheet itself, downscaled to 512px, instead of only its URL. Default true — showing it is the whole point; pass false to get just the URL.
rowsinteger–Grid rows (default 3). cols x rows = number of frames
video_idstringyesGenerated video id (from lab_animate/lab_job_status) — positive integer as string
widthinteger–Total sheet width in px (default 1280)

No output schema declared.

No examples provided.

lab_continuity_check ~281

Start the continuity pass over a sequence — every shot is compared against its PREDECESSOR and, with check_references, against the character and location reference boards. This is the pass that catches drift (the flat that changed between two shots, the cardigan that turned into a coat), which is the actual enemy in AI film, not the cut. Runs in the BACKGROUND: returns a `job_id` with HTTP 202 — poll it with lab_get_job until status is done|failed, the findings sit in the job result. Two refusals worth knowing before you spend time: an empty timeline is rejected with 400 (add shots with lab_add_clip first), and the backend answers 503 if GEMINI_API_KEY is not configured.

NameTypeReqDescription
check_referencesboolean–Also check every shot against the character and location reference boards, not just against its predecessor. Backend default is true; pass false for a cheaper neighbour-only pass
modelstring–Vision model for the comparison. Omit it — the backend resolves its default through the model catalogue, so it follows a model retirement on its own. A literal passed here does not, and that is how a…
seq_idstringyesSequence id (from lab_create_sequence/lab_list_sequences) — positive integer as string

No output schema declared.

No examples provided.

lab_create_character ~378

Create a character sheet in the cast register. The backend derives an English `prompt_prefix_en` from the fields you give — that prefix is what later describes this person in every image, so the richer the description, the more stable the identity. This is step 1 of 2: a fresh sheet has NO reference image and is therefore not yet usable as `character_refs`. Run lab_generate_character_reference on the returned id to finish it. Free — it writes a row, it burns no credits.

NameTypeReqDescription
ageinteger–Age in years, as a number
buildstring–Body build and posture
clothingstring–Default costume the character is seen in
demeanorstring–How the person carries themselves, in prose
distinctive_featuresstring–Scars, tattoos, glasses, anything that must appear in every image
eyesstring–Eye colour and expression
facial_featuresstring–Face shape, nose, mouth, jaw — what makes this face recognisable
genderstring–e.g. 'female', 'male', 'non-binary'
hairstring–Hair colour, length, cut
namestringyesCharacter name, e.g. 'Maren' — the only required field
project_idstring–Bind the sheet to this project (from lab_list_projects) — positive integer as string. PASS THIS whenever the character belongs to a project. Without it the sheet stays an orphan: lab_cast_gaps will n…
project_namestring–Free-text project label shown in listings (does NOT bind the sheet — that is project_id)
skinstring–Skin tone and texture

No output schema declared.

No examples provided.

lab_create_location ~263

Create a location board. The backend derives an English `prompt_prefix_en` from the fields you give — that prefix is what later anchors every image and clip shot there, so the richer the description, the more consistent the place. Pass project_id to bind the board to a project (recommended: unbound boards are invisible to lab_list_project_locations).

NameTypeReqDescription
architecturestring–Building style, era, materials
atmospherestring–Mood, weather, sound of the place
colorsstring–Dominant palette
descriptionstring–What the place is, in prose
lighting_notesstring–Light direction, quality, sources
location_typestring–e.g. 'interior', 'exterior', 'apartment', 'street'
namestringyesBoard name, e.g. 'Wohnung Hanna — Balkon'
project_idstring–Bind the board to this project (from lab_list_projects) — positive integer as string
project_namestring–Free-text project label shown in listings
propsstring–Objects that must be present
time_of_daystring–e.g. 'morning', 'blue hour', 'night'

No output schema declared.

No examples provided.

lab_create_project ~39

Create a new FilmLab project. Returns the new project id. Optionally set a title.

NameTypeReqDescription
titlestring–Project title (optional)

No output schema declared.

No examples provided.

lab_create_sequence ~115

Create a sequence (Stage 9 timeline) inside a project — START HERE to turn generated shots into something the continuity pass can read. The new sequence is EMPTY: add shots with lab_add_clip before anything else works. lab_continuity_check rejects an empty timeline with 400. Returns the sequence record including its `id`.

NameTypeReqDescription
project_idstringyesProject id (from lab_list_projects) — positive integer as string
titlestring–Sequence title. Defaults to 'Main Sequence' on the backend

No output schema declared.

No examples provided.

lab_delete_location ~118

DELETE a location board permanently. There is no undo and no soft-archive — the row is removed. Images and clips that were generated with this `location_id` keep their already-rendered prompt, but the board they point at is gone: nothing can be re-anchored to it, and lab_get_location will 404. Confirm with the user before calling this. Use lab_restyle_location if you only want the place to look different.

NameTypeReqDescription
loc_idstringyesLocation board id to delete permanently (from lab_list_locations)

No output schema declared.

No examples provided.

lab_depth_map ~304

Create or read a depth map for a project video in FilmLab: use it for fog, depth of field, relighting or occlusion. Near is white, like Resolve's Depth Map. Free on our own CPU, no credits; processing takes minutes (about 0.5 seconds per frame). Reuses the existing map or running job by default; neu: true starts a new job. Returns status and job_id; when done, tiefe_url is FFV1 gray16 and vorschau_url is a playable H.264 grayscale preview, both signed for download without a browser session. wait_s waits at most 15 seconds (default 0). If still running, call this tool again with the same project_id and video_id, neu: false. Once done, use resolve_ergebnis_an_timeline with vorschau_url to put the preview as a matte above the original clip in Resolve.

NameTypeReqDescription
neuboolean–Start a new depth job instead of reusing the existing map or running job (default false)
nur_lesenboolean–Only read: never create a job. Without an existing job the answer is status 'keine' (default false)
project_idstringyesProject id (from lab_list_projects)
video_idintegeryesCompleted video id belonging to this project
wait_snumber–Wait up to this many seconds for completion (default 0, maximum 15)

No output schema declared.

No examples provided.

lab_diagnose ~140

Is everything wired? Backend reachability and latency, identity, credit check, catalog age, last error of this account, host widget support. Traffic light plus one sentence per point. Read-only, free.

NameTypeReqDescription
problem_reportboolean–Return the same findings as one block of text to paste into a bug report. This covers the MCP side only — server version, backend health, last failed job of this account. The Resolve bridge log lives…

No output schema declared.

No examples provided.

lab_dossier ~278

Build a dossier of a project's takes: one ZIP with an offline index.html (no external resources) plus the media files, named Project_SceneNN_YYYYMMDD-Tnn.ext. modus 'kunde' is for a client and NEVER shows seed or costs, whatever the switches say; 'intern' shows everything that helps to rebuild a take. Both modes carry the AI disclosure (EU AI Act Art. 50) on the page and in the image files. Free (no credits). Runs as a job — poll lab_get_dossier.

NameTypeReqDescription
auswahlstring–gewaehlt (default): the selected take per scene, plus every take without a scene (e.g. a series) that is not rejected; alle: every take that is not rejected. Stars/favourites do not count as a select…
bild_idsarray–Exactly these image ids (overrides auswahl)
modusstring–kunde (default) or intern
project_idstringyesProject id
schalterobject–Switches: prompt, referenzen, aufloesung_dauer, datum, modell, seed, kosten, audio, mini_proxies (480p video proxies). Unknown keys are ignored.
video_idsarray–Exactly these video ids (overrides auswahl)

No output schema declared.

No examples provided.

lab_dub ~853

Dub a sequence into another language: either a ready audio track (en_audio_url — e.g. the one lab_dub_tts just produced) OR a cloned voice reading a line of text (voice_id + dub_text), then a controlled visual lipsync runs over the sequence's own footage (ROI-crop + composite for a long static talking-head shot, or the full-frame veed_v2 path for multi-shot sequences and shots where the mouth is partly hidden). ASYNCHRONOUS: returns a job_id immediately: poll lab_job_status until it completes. Needs a cloned voice first — lab_voice_clone makes one, lab_list_voices shows what a project already has.

NameTypeReqDescription
backendstring–Lipsync engine. Omit to use the backend default (replicate — ROI-crop, best for one long static talking-head shot). veed_v2 renders the full frame instead and is the pick for multi-shot sequences or…
dub_textstring–The line(s) this cloned voice should read, in the target `language`. Required together with voice_id.
einwilligungboolean–Consent of the person whose mouth this dub re-syncs, when there is no Likeness Register id for them yet. Required together with einwilligung_notiz if likeness_ref is not given — a dub always alters a…
einwilligung_notizstring–Free text: who consented, when, and for what — required together with einwilligung. Goes on record with the generated clip.
en_audio_urlstring–URL of a READY dub track to lay under the sequence — typically the audio_url lab_dub_tts just returned. Mutually exclusive with voice_id+dub_text: a dub has exactly one audio source, and picking one…
enable_lipsyncboolean–Whether to run the visual lipsync pass at all. Omit to use the backend default (on). Off only swaps the audio track and skips the mouth-sync render entirely.
get_costboolean–`true` reports the price and your balance WITHOUT starting a dub and without spending quota. The number is computed by the same function that later charges you, from THIS sequence: a sound rate per v…
languagestringyesTarget language for the dub, e.g. 'de', 'fr', 'es' — drives the cloned voice's TTS. Required: there is no silent default here.
likeness_refstring–A Likeness Register consent id (likeness.thefilmradar.com) for the person whose mouth this dub re-syncs. Checked live against the register before anything is spent; a revoked or unknown id refuses th…
seq_idstringyesSequence id (from lab_create_sequence/lab_list_sequences) — positive integer as string
voice_idstring–A cloned voice's id (lab_cloned_voices.id, from lab_voice_clone or lab_list_voices) — positive integer as string. Required together with dub_text, and mutually exclusive with en_audio_url.

No output schema declared.

No examples provided.

lab_dub_tts ~309

Generate the EN-dub audio track for a sequence via ElevenLabs TTS — SYNCHRONOUS, returns a ready audio_url immediately, no job_id and nothing to poll. Optionally pads the track with silence up to the sequence's own length so a shorter reading doesn't shorten the final cut. Feed the resulting audio_url into lab_dub's en_audio_url to lipsync the sequence to this track.

NameTypeReqDescription
get_costboolean–`true` reports the price and your balance WITHOUT generating anything and without spending quota. This one is billed flat, one sound rate per run — the length of your text does not change it. Not dra…
pad_to_videoboolean–Pad the generated track with silence up to the sequence's own duration if the reading comes out shorter. Omit to use the backend default (on).
seq_idstringyesSequence id (from lab_create_sequence/lab_list_sequences) — positive integer as string
textstringyesThe line(s) to speak. Kept short — very long text is rejected by the backend before anything is spent.
voice_idstring–An ElevenLabs voice id, from lab_dub_voices. Omit to use the backend's configured default voice — NOT a lab_cloned_voices id.

No output schema declared.

No examples provided.

lab_dub_voices ~92

List the ElevenLabs TTS voices available for lab_dub_tts's `voice_id` — this is the EN-dub-track text-to-speech voice list, NOT a project's cloned voices (those are lab_list_voices). Reads only — no state changes, no credits. If ELEVENLABS_API_KEY isn't configured on the backend the list comes back empty and `configured` is false.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

lab_enrich_location_prefix ~148

Append context to a board's `prompt_prefix_en` (plain string concatenation server-side — no AI call, no quota). Idempotent: context already present in the prefix is not duplicated. This does NOT rewrite or regenerate the prefix — for a board whose prefix is empty, too thin or a raw field dump, use lab_restyle_location (it rewrites prompt_prefix_en with an AI call, costs quota) instead of recreating the board.

NameTypeReqDescription
contextstringyesWhat to add or sharpen, e.g. 'late 1970s West Berlin, nicotine-stained walls'
loc_idstringyesLocation board id (from lab_list_locations)

No output schema declared.

No examples provided.

lab_export_profiles ~121

List the available export delivery profiles (web, social_vertical, social_youtube, streaming_hdr, cinema, master, alpha_prores4444, alpha_png_sequence) and quality presets (draft, standard, high). Call this before lab_start_export to pick a valid profile/quality. The two alpha profiles keep transparency (ProRes 4444, or one RGBA PNG per frame delivered as a zip) and are REFUSED unless the sequence actually carries an alpha source — a cut-out layer element, or a Switch X transform whose alpha track was kept.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

lab_fassungen ~436

The history and the versions of ONE cut (sequence). Every timeline write (lab_timeline_apply, the editor, the Resolve bridge) first saves the state it replaces; this tool reads those saved states and works with them. Costs nothing. aktion 'liste' (default): the saved states, newest first, with `marke` (a name a person gave a state), plus where this sequence was branched from (`ursprung`, with what changed since the branch point) and which versions were branched from it (`abgezweigt`). 'markieren': give a state a name (`marke`); a named state is never cleaned up — states without a name are capped per sequence. Empty `marke` removes the name. 'vergleichen': what changed since a state — against the current cut, or against another state (`gegen`), clip by clip. 'zurueckholen': write a state back as the current cut; the cut it replaces is saved first, so this is undoable. 'abzweigen': make a NEW sequence (a version — e.g. a broadcast cut next to the festival cut) from a state, or from the current cut without `checkpoint_id`. The new sequence keeps the clip ids and the shot layer, knows its origin, and the branch point gets a name so it stays. There is no merging back: a version is its own cut from then on. Edit it with lab_timeline_apply on the returned sequence id.

NameTypeReqDescription
aktionstring–What to do. Default 'liste'
checkpoint_idinteger–The state (id from 'liste'). Needed for markieren, vergleichen, zurueckholen; optional for abzweigen (without: the current cut)
gegeninteger–vergleichen: a second state instead of the current cut
markestring–markieren: the name. Empty removes it
seq_idstringyesSequence id (from lab_list_sequences) — positive integer as string
titelstring–abzweigen: the name of the new version

No output schema declared.

No examples provided.

lab_feedback ~278

Tell the FilmLab team about a bug or a missing feature — it reaches the people who can fix it, the chat does not. Use art 'fehler' when a tool returned something wrong, failed without a clear reason, or contradicted its own description; 'wunsch' when a step you needed does not exist. Write what you called, what you expected and what came back; put ids, arguments and the error text into `kontext` (no secrets, no personal data of third parties). One report per problem. Do not report a refused request that was correct (e.g. 'Project not found' for someone else's project). Needs an account. Free.

NameTypeReqDescription
artstringyesfehler = something is broken; wunsch = something is missing
kontextobject–Machine-readable details: ids, arguments, error text. Max ~8000 characters as JSON
project_idstring–Your project it happened in (only your own projects are accepted)
textstringyesWhat you called, what you expected, what happened — in a few sentences
titelstringyesOne line, e.g. 'lab_capture: black frame for an image clip'
werkzeugstring–The tool it is about, e.g. 'lab_timeline_apply'

No output schema declared.

No examples provided.

lab_flow_angebot ~336

Price a whole Flow (Pipeline) before running it: one quote over every node, checked against the credit balance and the project's cost cap. `workflow` is a FilmOS workflow in schema v1 (vault/workflows/_schema.md): nodes of type `lab.tool` call FilmLab tools by name, `{{node_id.field}}` passes one node's result into the next, `parallel` and `condition` are supported, `foreach` and `workflow.invoke` not yet. Every node whose tool costs money is priced with that tool's own get_cost preflight; a paid tool without a preflight, or a price that cannot be determined, rejects the whole quote by name — nothing is estimated. Nothing is generated and nothing is charged. Returns `angebot_id` (valid 24 h, for exactly this workflow, these inputs and this project), the total, one line per node, the balance and what the cap still allows. A node whose price only exists once its input exists (lab_upscale fed by a clip from another node) is listed with `preis_folgt: true` and is NOT in the total: the run stops before it, names the exact price and continues only after lab_flow_fortsetzen — tell the person so when you name the total.

NameTypeReqDescription
inputsobject–Values for the workflow's `inputs`, referenced as {{name}}
project_idstringyesProject id (from lab_list_projects) — every node runs in this project
workflowobjectyesThe Flow (Pipeline) as a FilmOS workflow object, schema_version "1"

No output schema declared.

No examples provided.

lab_flow_fortsetzen ~199

Resume a Flow (Pipeline) run that stopped and waits (status 'wartet' with a reason like 'Wartet auf Freigabe'). A run stops when a clip node needs a start image the person has not approved yet — approve the image first (lab_review_asset, verdict accepted), then resume. A run also stops before a node whose price only exists once its input exists (lab_upscale after a clip — the quote listed it as `preis_folgt`): the reason starts with 'Wartet auf Preisbestätigung' and names the exact credits. Resuming IS the confirmation of that price — ask the person first. The confirmed amount travels as max_credits; if the price rises before the run, nothing is charged and the run stops again with the new price. The waiting nodes are tried again; nothing that already ran is repeated.

NameTypeReqDescription
lauf_idstringyesFrom lab_flow_starten

No output schema declared.

No examples provided.

lab_flow_starten ~235

Run a Flow (Pipeline) that was quoted with lab_flow_angebot. Pass the SAME workflow and inputs plus the angebot_id — a changed workflow, an expired quote (24 h) or a quote that was already used is refused; get a new quote then. Only after the person confirmed the price. Returns right away with `lauf_id`; the run continues on the server without anyone watching. Follow it with lab_flow_status. Each node calls its FilmLab tool under your account; every tool's own gates still apply (approved keyframe before a paid clip, cost cap of the project). If the cost cap is hit, the whole run stops and nothing after it starts. The quoted price is also the run's own hard cap (auto_lauf_id): every node reserves against it, failed nodes keep their share, and a run whose retries would cost more than the quote stops with budget_exceeded instead of spending more.

NameTypeReqDescription
angebot_idstringyesFrom lab_flow_angebot
inputsobject–Exactly the inputs that were quoted
workflowobjectyesExactly the workflow that was quoted

No output schema declared.

No examples provided.

lab_flow_status ~93

State of a Flow (Pipeline) run started with lab_flow_starten: the run's status (wartet, laeuft, fertig, fehlgeschlagen, abgebrochen) and, per node, its status, attempts, result and error. A node's result is exactly what its tool returned — ids from there go into the next tools.

NameTypeReqDescription
lauf_idstringyesFrom lab_flow_starten

No output schema declared.

No examples provided.

lab_generate ~1,921

Generate an image on the production pipeline (fal.ai, quota-tracked, persisted to the project's gallery). Waits up to `wait_s` seconds (default 45) for the image and then answers with the finished rows — image_url set, inline previews attached, so the picture is in the answer like lab_job_status with preview. Pass `wait_s: 0` to return right away with rows in status 'pending' (poll lab_job_status with id + project_id then). If the budget runs out, the rows come back as they are and `fertig: false` says so. Default tool is 'flux_pro'; use 'nano_banana_pro' (Gemini 3 Pro Image) for the Papercut-style look. Pass seed_image_url to run img-to-img guided by an existing image URL. `get_cost: true` preflights credits — it returns the price without generating anything. FOR A PERSON WHO MUST LOOK THE SAME across several images, do not re-describe them per prompt: get an id from lab_list_characters (or build one with lab_create_character + lab_generate_character_reference) and pass it as `character_refs`.

NameTypeReqDescription
anker_idstring–Look anchor id (positive integer string) whose CHOSEN image guides this generation as img-to-img. An anchor is a look imported from Midjourney: a handful of images plus the grammar of the old `--prof…
apply_lensboolean–Defaults to TRUE on the backend: the project's lens_state UrPrompt is appended to the prompt. Pass false only to deliberately opt out for this one call.
aspectarray–Frame as [width, height], e.g. [9, 16]. Overrides the project's pose_state — pass it when the Pose-Director's blockout is set but not yet saved. Measured 2026-07-31: without it a 9:16 blockout came b…
aspect_ratiostring–Aspect ratio as W:H (e.g. 16:9, 9:16). Must be one of the model's aspect_ratios where the model has an enum; models without an enum accept any W:H. Omit to use the project's camera aspect.
character_refsarray–Character ids (positive integer strings) whose reference images lock the cast's identity. Routes the call to img-to-img and sends EVERY listed character's reference image, in the order given, up to t…
character_statesobject–Which STATE each character is in for this image, as { characterId: stateKey } — e.g. { "12": "wet" }. A state is its own asset with its own full descriptor (clean / soaked / bloodied are three assets…
costume_refsarray–The costume plate of these characters goes along as an extra reference image — the outfit on an invisible mannequin, NO person, so it carries the costume, never the face. Every id must also be in cha…
get_costboolean–Preflight: return the price in credits and your balance WITHOUT generating, reading the same catalog as lab_list_models. Do this before a batch or when the user wants to see the cost. For a card the…
location_idstring–Location board id (from lab_list_locations). Anchors the shot: the board's `prompt_prefix_en` is appended to your prompt as 'Location: …' before generation, so every image of the same place stays in…
metadataobject–Free-form JSON stored alongside the image (e.g. { parent_id, note }). Not interpreted by the pipeline.
project_idstringyesProject id (from lab_list_projects) — generation is always project-scoped
promptstringyesWhat to generate (required)
resolutionstring–Resolution tier, exactly as listed for the model in lab_list_models. Omit for the model's default; the aspect ratio still comes from the project's pose_state — this only sets the area. Some models ha…
scene_refstring–Scene label (e.g. 'SZ 04'). Stored on the row, so results can be matched back to a shot list and reviewed per scene with lab_review_queue. Omit it and the image is an orphan.
seedinteger–Seed for a repeatable run. Omit it and the project's stored seed applies (POST /api/lab/projects/{id}/einstellungen), and without that the provider picks one. The seed that actually rendered comes ba…
seed_image_urlstring–Optional: run img-to-img guided by this existing image URL (e.g. a prior generation's url). For a PERSON who must look the same across several images, use character_refs instead — this URL binds one…
toolstring–Image model id — copy it verbatim from lab_list_models (kind: image). Omit to use the default. Every model has its own resolutions, aspect handling and price; the catalog is the only place those live…
variantsinteger–How many variants to generate (default 1, max 5)
wait_snumber–Seconds to wait for the finished image before answering (default 45, max 80). 0 = answer immediately with pending rows.

No output schema declared.

No examples provided.

lab_generate_character_reference ~640

Generate the reference sheet for a character — six core views rendered from the sheet's `prompt_prefix_en`: detail (three-quarter close-up, the identity anchor), frontal (frontal close-up), profile, fullbody (front), fullbody_back (back view: hair and the back of the costume) and costume (the outfit on an invisible mannequin, NO person — use it where the costume is meant, never as a face reference). Back view and costume are derived from fullbody, everything else from detail. The poses pose_sitting, pose_walking, pose_action are optional extras for blocking — not part of the default run and not used as references for image or video models. A seventh view, 'detail_smile', is NOT in the default set and must be asked for: the same close-up with the mouth open and the teeth visible. Render it for every character who SPEAKS — otherwise the model invents the teeth and the jaw the first time they laugh, and the smile arrives as somebody else's mouth. It is an extra view for the mouth, never an identity anchor: a smiling reference carries its smile into every shot, funerals included. MEASURED 2026-09-15 (n=10, criterion fixed beforehand): the teeth land 10/10, but the PERSON only holds in about 4 of 10 even with the anchor active — two runs were plainly a different man. Generate it, then LOOK before you rely on it; the failure is obvious to the eye (a stranger's mouth on your character), not silent. THIS IS WHAT MAKES A SHEET USABLE: until it has run, lab_generate rejects the id as `character_refs`. Step 2 of 2 after lab_create_character. COSTS CREDITS — one provider call per view, so the default run is six. Pass `views` to render fewer. Takes about 25 s PER VIEW (the tool requests them one by one, anchor first), so a full run is 2–3 minutes. If a single request times out, the answer says `noch_in_arbeit` instead of failing: that view is still rendering and already paid for — check it with lab_get_character_sheet, do NOT re-run it. The sheet needs a `prompt_prefix_en`; the…

NameTypeReqDescription
character_idstringyesCharacter sheet id (from lab_list_characters or lab_create_character) — positive integer as string
viewsarray–Which views to render. Omit for the six core views. Allowed: detail, frontal, profile, fullbody, fullbody_back, costume, pose_sitting, pose_walking, pose_action. Fewer views = fewer credits; `detail`…

No output schema declared.

No examples provided.

lab_generate_location_variants ~91

Generate reference images for a location board (costs quota). Without `variants` the backend picks its default set. The images are what makes a board usable as a visual reference.

NameTypeReqDescription
loc_idstringyesLocation board id (from lab_list_locations)
variantsarray–Which views to render, e.g. ['wide', 'detail']. Omit for the backend default set

No output schema declared.

No examples provided.

lab_generate_music ~455

Generate a MUSIC track for a project (Stable Audio via fal.ai) — the first step of the rhythm chain, and the only one that costs credits. ASYNCHRONOUS: the call returns immediately with a row whose `audio_url` is null and `metadata.status` is 'pending'. Nothing is playable and nothing can be bound yet. Poll lab_list_audio (audio_type 'music') until that row's status is 'completed' and audio_url is set — usually under a minute, and the backend gives up after five (status turns 'failed', metadata.error carries the reason, and the credits are refunded). PUT THE TEMPO IN THE PROMPT if you intend to cut on the beat. This is measured, not assumed: a soft swing track measured at confidence 0.164 (unusable), an ordered hard pulse ('techno, 128 bpm, four-on-the-floor') at 0.621. The tempo detector is autocorrelation over an onset envelope — it finds a hard pulse and shrugs at drone, ambient and rubato. Then: lab_bind_audio, lab_beatgrid, lab_apply_rhythm.

NameTypeReqDescription
duration_secondsnumber–Track length in seconds (default 30, Stable Audio's ceiling is 190). Make it at least as long as the sequence you want to cut — lab_apply_rhythm computes durations for the clips that exist and neithe…
get_costboolean–`true` preflights the credit price and your balance WITHOUT generating anything and without spending quota.
project_idstringyesProject id (from lab_list_projects) — positive integer as string
promptstringyesWhat the music should be. Name genre, instrumentation, mood AND the tempo in bpm if the cut is supposed to sit on the beat — e.g. 'driving techno, four-on-the-floor kick, 128 bpm, no vocals'. A promp…
scene_refstring–Optional scene label, stored on the row. Useful to tell several tracks of one project apart

No output schema declared.

No examples provided.

lab_get_character ~208

Get ONE character sheet in full — every descriptive field plus the three that decide what you can do with it. `prompt_prefix_en` is the text block describing this person; it is what the backend prepends wherever the sheet is used. `reference_images` decides whether the sheet is usable at all: lab_generate REJECTS a character_refs entry without one, before any quota is spent — if it is empty, run lab_generate_character_reference first. `states` carries the state sheets against character drift (costume, light, physical condition); lab_get_character_sheet renders them agent-readable.

NameTypeReqDescription
character_idstringyesCharacter sheet id (from lab_list_characters) — positive integer as string
previewboolean–Attach the reference images themselves, downscaled to 512px. `reference_images` decides whether the sheet is usable at all — seeing them is the check, counting them is not: a sheet can carry a URL to…

No output schema declared.

No examples provided.

lab_get_character_sheet ~272

The character sheet PREPARED FOR PROMPTING: base prefix, the state sheets by name, which reference views exist, and the ready-made sentence to paste into a lab_generate prompt. Same source as lab_get_character, different shape — use this one when you are about to generate, and lab_get_character when you want the raw record. State sheets exist against character drift: one sheet per costume, light or physical-condition change, so a person stays the same person when the situation changes. THIS IS THE ANSWER to 'same person, different light': character_refs alone routes to i2i and drags the reference's lighting along, so a drastically different light fights the reference. A state sheet puts the change into the TEXT, where the prompt can win. Free.

NameTypeReqDescription
character_idstringyesCharacter sheet id (from lab_list_characters) — positive integer as string
previewboolean–Attach the reference views themselves, downscaled to 512px. `usable_as_character_ref` only says a URL exists — the picture says whether it is the right person, in the right view. That check is the wh…
statestring–Render the snippet for THIS state key (from `states[].key`) instead of the base state

No output schema declared.

No examples provided.

lab_get_context ~81

Read the accumulated context/output for one pipeline module of a project (e.g. the IDEE, STORYBOARD or SHOTS stage). Needs project_id and module name.

NameTypeReqDescription
modulestringyesPipeline module/stage id, e.g. 'idee', 'storyboard', 'shots'
project_idstringyesThe FilmLab project id

No output schema declared.

No examples provided.

lab_get_dossier ~96

Poll a dossier job by job_id (from lab_dossier). status is queued|processing|done|failed. When done, result.archiv_url is a signed https link to the ZIP that loads WITHOUT a login and expires after 24 h — call again for a fresh one. result.fehlend lists takes that could not be loaded.

NameTypeReqDescription
job_idstringyesThe dossier job id returned by lab_dossier

No output schema declared.

No examples provided.

lab_get_export ~281

Poll an export render job by job_id (from lab_start_export). status is queued|processing|done|failed; when done, the result (output url) is included. Call repeatedly until done|failed. NB: this is the EXPORT poll — different from lab_get_generation. Where the address sits depends on the profile: a rendered film is in video_url, but profile alpha_png_sequence delivers a ZIP of RGBA PNGs and therefore leaves video_url null and puts the address in archiv_url — a .zip under a key called video_url would read as something playable to every client. download_url carries the address in both cases and is the safe one to hand to a user. All result addresses — video_url, download_url, archiv_url and the provenance record herkunft.pdf_url / herkunft.json_url — are signed https links that load WITHOUT a login and expire after 24 h; call lab_get_export again for fresh ones. view_url is the short session-bound form for the web app only. A finished result also carries zielmarkt_checkliste: per target market of the project (see lab_zielgruppe) what the customer must observe when delivering there — empty without markets. Pass it on to the person with the download; it is not legal advice.

NameTypeReqDescription
job_idstringyesThe export job id returned by lab_start_export

No output schema declared.

No examples provided.

lab_get_job ~88

Get the status of a background job by job_id (status is queued|processing|done|failed). Poll this after starting a long-running generate/export. Returns the job record; its payload and result are objects (for a clip chain: result.zusammenfassung, result.ketten, result.clips).

NameTypeReqDescription
job_idstringyesThe job id returned by a generate/export tool

No output schema declared.

No examples provided.

lab_get_location ~105

Get ONE location board in full — all descriptive fields plus its reference images and `prompt_prefix_en`. Use it to check what a board actually anchors before generating with it.

NameTypeReqDescription
loc_idstringyesLocation board id (from lab_list_locations) — positive integer as string
previewboolean–Attach the board's reference images themselves, downscaled to 512px — the fastest way to check whether a board anchors the place you mean before spending quota on it.

No output schema declared.

No examples provided.

lab_get_project ~44

Get a single FilmLab project with its full stage state. Needs the project_id (from lab_list_projects).

NameTypeReqDescription
project_idstringyesThe FilmLab project id

No output schema declared.

No examples provided.

lab_get_sequence ~82

Get ONE sequence in full — timeline (the shots in order), audio_tracks, transitions, duration_seconds and render status. Check `timeline` here before starting a continuity pass: an empty one is the single most common reason the pass refuses.

NameTypeReqDescription
seq_idstringyesSequence id (from lab_create_sequence/lab_list_sequences) — positive integer as string

No output schema declared.

No examples provided.

Common questions

What is the FilmLab MCP server?

FilmLab is an MCP server listed in the public MCP registry as com.thefilmradar/filmlab. AI film lab for filmmakers: generate and review images/clips with input provenance, cost preflight. This page covers its hosted endpoint (https://mcp-lab.thefilmradar.com/mcp).

Is the FilmLab MCP server safe to use?

FilmLab scores 76 out of 100 on VerifyMCP. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

What tools does the FilmLab MCP server expose?

FilmLab exposes 111 tools: lab_list_projects, lab_wissen, lab_widerruf, lab_playbook, lab_list_models, and 106 more. Their descriptions and schemas cost roughly 39,090 tokens of context every time the server is loaded.

Does the FilmLab MCP server require authentication?

Yes. FilmLab asked us for credentials when we connected, so you will need to authorise it in your MCP client before it can do anything.

Is the FilmLab MCP server still maintained?

FilmLab is still listed as active in the MCP registry. We last reached this channel on 5 October 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.