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_get_state ~71

One call, the whole picture: account (tier, credits, reset), default models with price, jobs in flight, catalog freshness, project count. Pass project_id for that project's sequences, assets and review-queue length. Read-only, free.

NameTypeReqDescription
project_idstring–Add a project view

No output schema declared.

No examples provided.

lab_grade ~421

Apply a deterministic colour grade to an image already in the project gallery — no re-generation, no provider, no credits. The look is computed pixel-exact (exposure, saturation, hue, lightness, contrast, film grain) and lands as a new gallery image the sequencer and export pick up. The same recipe on the same image always yields the same result (grain is fixed-seed), so a look is reproducible across every still. Set from_colorist to start from the project's colorist crew brief (look, contrast, grain) and tune with the sliders on top. At least one adjustment OR from_colorist is required. Synchronous — the graded image_url comes straight back, no polling.

NameTypeReqDescription
contraststring–Contrast curve: high is an S-curve, low flattens it
exposurenumber–Exposure in stops; positive brightens, zero is neutral
from_coloristboolean–Start from the project's colorist crew brief (look/contrast/grain), then apply the sliders on top
grainnumber–Film grain amount; zero is none, monochrome
huenumber–Hue rotation in degrees; zero neutral
image_idstringyesId of the source image in the project gallery (from lab_list_assets / lab_generate)
lightnessnumber–Lightness; negative darkens, zero neutral
lookstring–Named look from the bundle catalogue (e.g. filmlab-neutral, filmlab-warm, filmlab-cool, filmlab-soft, filmlab-punch) — a hand-authored LUT, applied on top of the sliders. The server resolves the name…
look_opacitynumber–Blend of the named look, 0..1 (default 1)
project_idstringyesProject id (from lab_list_projects)
saturationnumber–Colour saturation; minimum is greyscale, zero neutral

No output schema declared.

No examples provided.

lab_grade_clip ~810

Set the colour grade of ONE clip in the edit (Murnau), or of the whole programme with `programm: true`. It is the same grade a colourist sets in Murnau's colour workspace, and the export uses it: Murnau bakes the export LUTs when you set it. Only the fields you send change (`zuruecksetzen: true` starts from neutral). Fields and ranges, as the sliders: exposure in stops (−5..5); contrast, saturation, temperature, tint −100..100; hue −180..180; lift/gamma/gain/offset as {x, y, master}, each −1..1 (x/y move the colour wheel); log as {shadow|midtone|highlight: {x, y, master}} — the Log wheels in ACEScct, each acting only on its range of brightness (shadows below ~4 % linear, highlights above ~50 %), master ±1 ≈ ±2 stops there; hdr as {dark|shadow|light|highlight: {x, y, master}} — HDR zone wheels centred −3/−1/+1/+3 stops around 18 % grey, master ±1 ≈ ±1.5 stops; curves as {master|r|g|b: [[x,y],…]} 0..1; boost, shadows, highlights −100..100; intensity 0..100 (0 = original). Per clip also `sek` — a secondary correction: {qualifier: {hueCenter, hueWidth, satLow, satHigh, lumLow, lumHigh, softness, invert}, fenster: [{form: kreis|rechteck|verlauf|polygon|bezier, cx, cy, rx, ry, winkel, weich, invert, modus: add|sub, punkte (polygon/bezier only: 3–16 resp. 3–12 [x, y] in the window's own unit space, scaled by rx/ry and turned by winkel — bezier draws a smooth closed curve through them)}], grade: {saturation, exposure, temperature, tint, hue, schutz}} — schutz 0..100 takes the clip's and the programme's grade back inside the selection (100 = ungraded there, e.g. to protect skin); `sek: null` removes it. Any level also takes `warper` — the Color Warper: {huesat|chromalum: {res: 6|12|24, punkte: [[i, j, dx, dy], …]}}; node (row i, column j) sits at (j/res, i/res) and is moved by (dx, dy) in −1..1. huesat plane: x = 0.5 + 0.5·sat·cos(hue), y = 0.5 + 0.5·sat·sin(hue) (lightness kept); chromalum plane: x = sat, y = 1 − lightness (hue kept). Only moved nodes; `warper: null` remov…

NameTypeReqDescription
clip_idstring–The clip to grade (from the listing); omit with programm:true
gradeobject–Fields to set — see description; omit to list clips and grades
programmboolean–Grade the whole programme instead of one clip
seq_idstringyesSequence id — positive integer as string (lab_list_sequences)
zuruecksetzenboolean–Start from a neutral grade before applying `grade`

No output schema declared.

No examples provided.

lab_grade_from_resolve ~188

Suggest a FilmLab grade look from a Resolve LUT name or path — read-only, no cost. First call resolve_node_graph_lesen on the local FilmLab bridge (filmlab_bruecke_mcp.py), a SEPARATE MCP server, and pass its lut field here. The agent connects these two calls: this Cloudflare Worker cannot reach the bridge at 127.0.0.1 on the user's computer or fetch the name itself. Only the name is matched; the Resolve LUT file is neither read nor imported, and its exact grade is not reproduced. Returns look, reason, alternatives and sicher (false means the name was not confidently recognised). Apply with lab_grade(look: …) only once the user agrees.

NameTypeReqDescription
lutstringyesLUT name or path from the lut field returned by resolve_node_graph_lesen on the local FilmLab bridge

No output schema declared.

No examples provided.

lab_grade_suggest ~107

Suggest a grade look for a project — read-only, no cost. With image_id, includes the image prompt; without it, uses only the colorist crew brief. Returns a recommended look name with a reason and alternatives; apply it with lab_grade(look: …) once the user agrees.

NameTypeReqDescription
image_idinteger–Generated image id belonging to the project; includes its prompt in the suggestion
project_idstringyesProject id (from lab_list_projects)

No output schema declared.

No examples provided.

lab_herkunft ~165

Declare or list where a project's material comes from: 'eigen' (made by people) or 'ki' (AI-generated or AI-altered). Exports decide the EU AI Act Art. 50 disclosure per clip from this — undeclared material counts as AI. With asset_key + herkunft: declare (the file is checked for an AI mark; one found keeps it AI and the answer says why). With project_id only: list every declaration with its effect (`wirksam`).

NameTypeReqDescription
asset_keystring–Storage key of the file (from lab_add_media or lab_list_assets). Omit to list
herkunftstring–Required together with asset_key
project_idstringyesProject id — positive integer as string

No output schema declared.

No examples provided.

lab_job_status ~628

Poll the status of an image or video generation started by lab_generate/lab_animate. There is no single-item status endpoint on the backend — this fetches the project's full image/video list and filters by id, so it needs BOTH project_id and id (the id alone is not enough). status inside the returned item's metadata is 'pending'|'completed'|'failed'; when completed, image_url/video_url is populated. When the run is done, the answer may additionally carry schritte (the step trail of this run) and review (a machine check against the confirmed brief, present once for a run that went through lab_propose/lab_run_proposal — absent for a still-pending run, a run started outside a proposal, or a repeat poll after the one-time check already ran): abweichung lists every field that came back different from what was confirmed, possibly empty; tool means the provider fallback chain degraded the run; bild means a vision check found the result contradicting an explicit statement of the brief (free for the user, once per run; bild_review says why it was skipped). A failed or degraded proposal run may also carry plan_b: alternatives with checked prices and proposal IDs, offered once. Present them to the human; never start them yourself. Call lab_run_proposal only after the human confirms an alternative.For a run that carried a kamerapfad, metadata.kamerapfad says what arrived and, as `angewandt`, WHICH form of it was actually sent — als_text (prose), als_regiebefehle (bracketed director commands, MiniMax/Hailuo), eigene_regie (the prompt already carried bracketed commands, so the path was deliberately NOT added next to them — eigene_regiebefehle lists them) or nicht_ableitbar (nothing of the path reached the prompt, with the reason). `sprache` next to it names the family rule and the source it rests on. For a reference-motion run, metadata.referenz_masse is the reference trail: one row per reference with what it measured (original_px) and, if the backend had to scale it to the mode…

NameTypeReqDescription
idstringyesThe id returned by lab_generate (image) or lab_animate (video)
previewboolean–Attach the image itself, downscaled to 512px, so it can be LOOKED at instead of described. Costs one extra fetch and adds roughly 15-25 KB to the answer. Videos carry no still and return no picture —…
project_idstringyesProject id — required, since there is no global id lookup
typestringyesWhether the id refers to a generated image or a generated video

No output schema declared.

No examples provided.

lab_jobs_inflight ~368

Are any FilmLab generations running RIGHT NOW, across ALL projects? Use this before anything that restarts the backend (a deploy recreates the container and kills running jobs, losing paid credits), or to answer 'is the lab busy?'. Unlike lab_job_status/lab_batch_status this needs no id — it lists every job in queued/processing PLUS every direct image/video/audio/vfx generation currently within its own grace window (lab_generate/lab_animate write straight to their result tables, never to the job queue — omitting job_type covers both; naming one job_type narrows to the job queue only, since a direct generation's type vocabulary differs). Returns {busy, warm[], stale_count, stale[]}: `warm` are jobs that actually progressed within stale_after_seconds and are the ones a restart would destroy; `stale` are queue jobs stuck longer than that (a crashed worker leaves rows in 'processing' forever) — they are reported but do NOT make busy true, otherwise one zombie would block every future deploy. A direct generation is never 'stale' here — past its own grace window it stops being reported by the backend entirely and becomes the orphan sweep's job, not this check's. Carries no prompts or payloads: this view crosses project boundaries, so it returns only type, state and age.

NameTypeReqDescription
job_typestring–Only this job type, e.g. 'video_generate', from the JOB QUEUE. Omit to see everything, including direct generations — for a pre-deploy check, omitting is usually right.
stale_after_secondsinteger–How long without progress before a job counts as a zombie rather than running. Default 1800, same threshold as the deploy guard in scripts/deploy_backend.sh.

No output schema declared.

No examples provided.

lab_layers ~558

Produce ONE element on a transparent background: generated, then cut out and stored as an alpha PNG in the project's gallery. This is the counter-move to the one-shot lottery — cast, props and foreground pieces are made SEPARATELY, arranged as a set afterwards and only then unified, so a wrong hand or a wrong lamp is re-made alone instead of re-rolling the whole frame. The element is deliberately optics-neutral: no lens or camera suffix travels with it, because the look is decided later on the finished comp and every layer is meant to inherit the same focal length and bokeh. ASYNCHRONOUS: the row comes back with status pending and image_url null; poll lab_job_status (type 'image') with its id until the url is populated — that url IS the cut-out. Costs credits when called without get_cost.

NameTypeReqDescription
get_costboolean–Preflight: return the price in credits and your balance WITHOUT generating and without spending anything. There is no model to pick on this path — the cut-out runs on the house image model and is bil…
layer_typestring–Which kind of element this is — it picks the isolation clause: 'cast' full-body person, 'prop' single object, 'foreground' a foreground piece, 'background' a wide backdrop plate WITHOUT people, 'crow…
metadataobject–Free-form JSON stored alongside the element (e.g. { note, parent_id }). Merged into the row's metadata next to the fields the pipeline sets itself (kind, layer_type, status) — not interpreted.
project_idstringyesProject id (from lab_list_projects) — positive integer as string. Travels in the URL; the element is filed in this project's gallery.
promptstringyesWhat the element shows — the OBJECT or the PERSON, not the scene around them. The backend appends an isolation clause (single subject, plain seamless background, even light) so the cut-out has a clea…
scene_refstring–Scene label (e.g. 'SZ 04'). Stored on the row, so the element can be matched back to a shot list and reviewed per scene with lab_review_queue. Omit it and the element is an orphan in the gallery.

No output schema declared.

No examples provided.

lab_letzter_frame ~143

Extract the LAST frame of a finished clip as a new image (returns image_id, image_url, zu_dunkel). Use it as source_image_id to continue one unbroken take, or as a still. A frame that is too dark (zu_dunkel: true) makes a bad start image — say so instead of animating from black. Free (no credits). Chains (lab_verkettung) do this themselves for uebergang=durchgehend.

NameTypeReqDescription
scene_refstring–Scene for the new image; default: the clip's
video_idstringyesA finished clip (positive integer as string)

No output schema declared.

No examples provided.

lab_list_assets ~257

List a project's media assets (image/video/audio) with their URLs. Optionally filter by asset_type. Returns up to 20 with a total count. Each row carries its address as `url` (with `type` and `key`). Project assets come back as SIGNED addresses on https://thefilmradar.com/api/lab/assets/abruf/… — valid for 24 h, loadable without a session and with any User-Agent. Only older rows may still point at media.andresmarder.com, whose CDN WAF answers some non-browser User-Agents (e.g. curl's default) with 403 — prefer a browser UA there, or hand the URL to the user.

NameTypeReqDescription
asset_typestring–Filter by asset type (optional)
previewboolean–Attach the pictures themselves, downscaled to 512px, so you can look at them without fetching anything (older media.andresmarder.com addresses answer a non-browser User-Agent with 403). The worker fe…
project_idstringyesProject id (from lab_list_projects)

No output schema declared.

No examples provided.

lab_list_audio ~285

List a project's generated audio rows, newest first — this is the POLL for lab_generate_music. Read two fields: `metadata.status` ('pending' | 'completed' | 'failed') and `audio_url`. A pending row has no url, and nothing downstream works with it: lab_bind_audio silently leaves the track empty (resolve-stems only takes rows that carry a url) and lab_beatgrid has no file to open. A failed row carries `metadata.error` and its credits were refunded. Reads only — no state changes, no credits.

NameTypeReqDescription
audio_typestring–Filter by kind. Pass 'music' when polling a lab_generate_music call — that is the kind the music track binds. The repair kinds (denoise, split, isolation) come from lab_sfx and hold cleaned-up versio…
limitinteger–How many rows to FETCH from the backend (default 50). At most 20 are SHOWN; `total` is what the fetch found, so a total of exactly `limit` means there may be more
project_idstringyesProject id (from lab_list_projects) — positive integer as string
scene_refstring–Filter by the scene label passed at generation time

No output schema declared.

No examples provided.

lab_list_characters ~299

List the character sheets in the FilmLab cast register (id, name, age, gender, project_name, prompt_prefix_en). Call this BEFORE lab_generate whenever a person must look the same across several images: pass the id you find here as `character_refs` instead of re-describing the person in every prompt. Optional `search` matches name or project name (substring, case-insensitive). It shows YOUR OWN characters plus the public catalog (sheets explicitly made public and bound to no project). Characters of other accounts' projects never appear — projects can be confidential. New characters are private. The register returns at most 50 sheets, newest first, and offers NO paging — 20 are shown here. `total` therefore counts at most 50: with more than 50 sheets it understates, and `search` is the only way to reach the older ones. Nobody there yet? Create a sheet with lab_create_character.

NameTypeReqDescription
previewboolean–Attach each sheet's reference portrait, downscaled to 512px. A cast list read as text is a list of names; seen as faces it is a cast. At most 4 per call. A sheet WITHOUT a reference image shows none…
searchstring–Substring of the character name or project name (case-insensitive)

No output schema declared.

No examples provided.

lab_list_exports ~82

List past export jobs for a project (each with job_id, status, profile). Returns up to 20 with a total count. Finished rows carry the same signed, login-free result addresses as lab_get_export (download_url, herkunft.pdf_url, …; valid 24 h).

NameTypeReqDescription
project_idstringyesProject id (from lab_list_projects)

No output schema declared.

No examples provided.

lab_list_location_scans ~138

List a project's location scans with their reconstruction state — this is the POLL for lab_location_recon and the place the scan ids come from. Read `status`: 'pending' (clip uploaded, nothing reconstructed yet), 'reconstructing', 'done' (splat_url/glb_url/board_url are filled), 'failed' (error says why). Listing is what ADVANCES a running reconstruction from the outside world into the row, so calling this is how the state moves at all. Reads only — no credits.

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

No output schema declared.

No examples provided.

lab_list_locations ~230

List location boards, newest first — START HERE to find a `location_id` for lab_generate / lab_animate. Each entry carries its `prompt_prefix_en`: that is the exact text appended to your prompt as 'Location: …', so you can judge whether the board fits BEFORE spending quota. A board with an EMPTY prefix anchors nothing — it will silently do nothing. Fix it with lab_enrich_location_prefix or pick another board. Only public boards are returned, max 50 from the backend and 20 shown here; if your place is not listed that is a limit, not a failure — create it with lab_create_location.

NameTypeReqDescription
previewboolean–Attach each board's reference picture, downscaled to 512px. A location board is a PLACE — its prefix text says what was written down, the picture says what the board actually anchors, and those two d…
searchstring–Filter by board name or project name (substring, case-insensitive)

No output schema declared.

No examples provided.

lab_list_models ~119

The model catalog: what every video or image model can do — resolutions, durations, aspect ratios, audio, reference limits, price per second or per image — grouped by capability class with a one-line explanation per group. Read this before choosing a `tool` for lab_generate/lab_animate/lab_propose; copy ids verbatim. Cached briefly; `stand` says how fresh.

NameTypeReqDescription
kindstringyesWhich catalog
klassestring–Only one capability class (e.g. the class name from a previous answer)

No output schema declared.

No examples provided.

lab_list_project_locations ~86

Location boards bound to ONE project. Narrower and more correct than lab_list_locations when you already know the project: it cannot leak boards from a different project with the same title. Boards created before the project binding existed (project_id NULL) deliberately do NOT appear here — use lab_list_locations for those.

NameTypeReqDescription
project_idstringyesProject id (from lab_list_projects)

No output schema declared.

No examples provided.

lab_list_projects ~85

List FilmLab projects (id, title, current pipeline stage). Call this first to find a project_id for the other tools. Shows up to 20 items; `total` counts your active projects (up to 200) and `truncated: true` means the list is cut off — sorted by last change, so older projects drop out of the shown window first.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

lab_list_sequences ~58

List a project's sequences, newest first. Use it to find a `seq_id` instead of creating a second sequence for the same cut.

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

No output schema declared.

No examples provided.

lab_list_voices ~182

List a project's cloned voices (lab_voice_clone results) — id, label, voice house, sample and preview URLs. This is where a `voice_id` for lab_voice_tts or lab_dub comes from, and where you look up which house a voice belongs to before pricing it. Both houses are listed unless you narrow it. Reads only — no state changes, no credits.

NameTypeReqDescription
project_idstringyesProject id (from lab_list_projects) — positive integer as string
providerstring–Narrow the list to one voice house. Omit it and both come back, which is the normal case — a project can hold voices from either. An unknown value is refused rather than answered with an empty list:…

No output schema declared.

No examples provided.

lab_location_panorama ~129

Generate a 360° equirectangular HDRI panorama of a place (costs quota). Pass loc_id to persist it on that board, so the viewer finds it again; without loc_id it is a one-off.

NameTypeReqDescription
camera_heightnumber–Camera height in metres (default 1.6, roughly eye level)
intentstringyesWhat the place is — the panorama prompt
loc_idstring–Persist the panorama on this location board (from lab_list_locations)
moodstring–Mood/atmosphere (default 'neutral')

No output schema declared.

No examples provided.

lab_location_recon ~380

Reconstruct a real place in 3D from a scan clip: keyframes are pulled from the clip server-side and turned into a point cloud / splat on the location board, so a scouted room can be looked at from angles nobody filmed. THE SCAN IS NOT MADE HERE — it is a walk-around clip uploaded by the FilmLab camera app together with the phone's lens data. This tool takes one that already exists; lab_list_location_scans gives you the ids. SLOW AND NOT A JOB ROW: the answer comes back as 'reconstructing', and the finished state is picked up ONLY by lab_list_location_scans — lab_job_status and lab_get_job will never show this one finish. If the call times out, the reconstruction normally keeps running on the server: list the scans instead of firing it again. Re-running is allowed from any state that is not done.

NameTypeReqDescription
enginestring–Which reconstruction path. Omit for the backend default. The second path is scene-scale and needs its model configured on the backend — where it is not, the answer says so instead of falling back sil…
image_idstringyesId of the SCAN row (from lab_list_location_scans) — positive integer as string. It is a row in the image gallery whose tool is the location scanner; a normal generated image with that id is rejected,…
max_photosinteger–How many keyframes are pulled from the clip and handed to the reconstruction. Omit to let the engine use its own count — more frames mean a wider parallax baseline and a slower run.
project_idstringyesProject id (from lab_list_projects) — positive integer as string. The scan must belong to it; a scan of another project is not found rather than borrowed.

No output schema declared.

No examples provided.

lab_look_match ~372

Check the colour CONTINUITY of a scene in the edit (Murnau): every shot is compared with the scene's reference shot (the first, or `referenz_clip_id`) at the SAME scene points — found by feature matching (ORB + homography) between the two frames, each rendered through its export path. Image-wide statistics would measure the framing, not the grade (measured: up to 5000 K apart with no grade change). At those points: white point (Kelvin and mired), lightness (L*), colour distance (ΔE). Over the threshold (8 mired, L* 4, ΔE 3) a shot gets a `befund` with the number (e.g. '150 K wärmer als die Szene (13 Mired)') and a `vorschlag.grade`: a clip grade fitted so the shot's source colours land on the reference colours, with the deviation expected afterwards. Pass it to lab_grade_clip, then run lab_look_match again. Shots without enough shared content (reverse shot, different subject) come back as `vergleichbar: false` with the reason — nothing is guessed. Scenes come from the sequence's shots (lab_shots); without them give the shots as `clip_ids`. At most 24 shots per call. Writes nothing, costs nothing.

NameTypeReqDescription
clip_idsarray–Compare exactly these shots instead of the scenes from lab_shots
referenz_clip_idstring–The shot the others are matched to; default the first of the scene
seq_idstringyesSequence id — positive integer as string
szenestring–Only this scene (scene_ref from lab_shots); default: every scene with two or more shots

No output schema declared.

No examples provided.

lab_mix ~305

Set the sound mix of a sequence: per track `volume_db`, `pan`, `mute`, `solo` and `effects`. Every field you send is rendered — the backend rejects what it cannot render (422 with the reason), so a saved mix is the mix you hear. Tracks are the stems `dialog`, `music`, `sfx`, `atmo`, plus `master` (effects only: eq, compressor, limiter). Only the fields you send change; `effects` replaces that track's whole effect list. Effects: gate, eq, deesser, compressor, reverb, limiter — fixed order, one of each per track; give a `preset` (with its written reasoning), a one-knob `knopf` (0–1) or explicit values. Ducking is an effect too: {type:'ducking', quelle:'dialog', amount_db, attack_ms, release_ms} lowers this track while `quelle` is active. Call with `katalog: true` (and no tracks) to get every effect, its ranges and the presets with their reasoning. Any change discards the rendered mixdown. Changes state, costs nothing. Next: lab_mix_render, then lab_mix_messen.

NameTypeReqDescription
katalogboolean–Return the effect catalogue instead of changing anything
seq_idstringyesSequence id — positive integer as string
tracksarray–Tracks to change — only the given fields are written

No output schema declared.

No examples provided.

lab_mix_messen ~217

Measure the RENDERED mix: integrated loudness (LUFS), true peak (dBTP) and loudness range (LU) of the master, measured on the mixdown file itself. Per stem the same values, speech-gated (under the dialog / in its pauses), and how many LU each stem sits under (or over) the dialog in dialog passages — exact. A stem's level inside the master is an estimate (stem plus the gain the master applied) and is labelled as such. Needs a current render whose stems are still the ones it was made from: any change with lab_mix discards it, and a newer audio file in a stem makes it stale (409 then — render first). Runs as a BACKGROUND JOB: you get a job_id at once; poll lab_get_job until done — the measurement is in job.result. Measure before and after a change to prove what it did. Writes nothing, costs nothing.

NameTypeReqDescription
seq_idstringyesSequence id — positive integer as string

No output schema declared.

No examples provided.

lab_mix_render ~317

Render the sequence's mixdown, normalised to a loudness target: `broadcast` (EBU R128), `web` or `youtube`. With `auto_preset` it runs the AUTO-MIX instead: it measures every stem speech-gated (under the dialog vs. in its pauses), sets faders, ducking and a master limiter by the preset (`spielfilm`: music clearly under the dialog; `doku_vo`: the narrator leads), renders, and measures the result. Every auto-mix decision comes back as one sentence with its number, plus missed lower loudness bounds — read them, they are the reasoning you can pass on. Runs as a BACKGROUND JOB: the answer is a job_id at once; poll lab_get_job until status is done (the result — mixdown, measured loudness, the auto-mix report — is in job.result) or failed (job.result.status and detail say why: 422 solo on / dialog muted / no speech, 409 the tracks were edited meanwhile — nothing was overwritten). If a render of the same kind is already running for this sequence, you get THAT job_id back instead of a second render. Costs nothing. Next: lab_get_job, then lab_mix_messen.

NameTypeReqDescription
auto_presetstring–Run the auto-mix with this preset instead of rendering the mix as set
seq_idstringyesSequence id — positive integer as string
targetstring–Loudness target, default broadcast

No output schema declared.

No examples provided.

lab_playbook ~140

The rules of one working surface, generated from the code: what the surface is, what an agent can trigger itself, what exists but only by hand, and what does not exist at all. Call this BEFORE answering what is possible on a surface — the three lists come from a table with a code reference per entry, checked in every PR, not from memory. Saying "that does not exist" about something the editor can do is the failure this tool prevents. Surfaces: edit, vfx, audio, idea, script, axis, location, crew, cast, pose, capture.

NameTypeReqDescription
flaechestringyesThe working surface

No output schema declared.

No examples provided.

lab_prompt_transform ~945

Turn a loose idea into a production-ready image or video prompt — the same Dreamer engine the FilmLab web UI uses (modes: beautify, storyboard, polish, format, shorten, expand, simplify, custom, stiluebernahme). beautify GENERATES (a 50-character thought comes back as a full prompt); polish/format/shorten/expand/simplify PRESERVE what is there. medium=video plus depth=skeleton yields the 15-block production prompt; depth only applies to video. anlass only applies to beautify. custom and stiluebernahme require instruction. For video the answer carries clip_duration_seconds — hand THAT number to lab_animate(duration_seconds), otherwise a prompt timed to 12s gets rendered as lab_animate's 5s default. In an Apps-capable host this opens as a form you can adjust and re-run; elsewhere it answers with the prompt as plain text. Pass `tool` (the registry key you will hand to lab_animate/lab_generate) and the finished prompt is laid out in the skeleton of that model family — location, camera, lens and light land where that family reads them, worded the way it reads them; families without a measured rule keep them appended as before, and the answer says so (prompt_skelett).

NameTypeReqDescription
anlassstring–beautify only: what the image is FOR. Default frei
depthstring–video only: sketch (5 blocks, default) or skeleton (15 blocks)
duration_secondsinteger–video only: the clip length in seconds the ACTION TIMING beats are written to. Default 5 (what lab_animate renders without an explicit duration). Rejected for medium=photo.
familiestring–Optional, instead of tool: the model family by name when no registry key is at hand. Medium decides whether the image or the video skeleton applies.
instructionstring–Required for custom (an order, e.g. 'make it darker') and stiluebernahme (a style description)
location_idinteger–Optional, only with tool or familie: the location board whose prompt prefix becomes the place block — the same board you will hand to lab_animate/lab_generate.
mediumstring–photo (default) or video — decides the section layout
modestring–Default beautify (generates). beautify: Aus der Idee einen vollständigen Prompt bauen — ergänzt Licht, Optik, Kamera, Stimmung | storyboard: Szene in 4–8 nummerierte Panels zerlegen — je Panel ein ei…
project_idinteger–Optional, only with tool or familie: the project whose Lens Lab optics, Pose Director framing and gaffer light should be laid into the prompt.
promptstringyesThe text to work on — a loose thought is enough for beautify
referenzenarray–The references the prompt may point at, IN THE ORDER you will pass them to lab_animate/lab_propose. Write @bild1, @video1, @ton1 in your prompt and they come back as the markers the model actually re…
technikenarray–Up to three directing technique keys from lab_regie_techniken. Their prompt fragments are appended verbatim after the transform, ordered angle, framing, composition, movement. One angle and one movem…
toolstring–Optional: the model you will render with, as the registry key from lab_list_models. Decides which family skeleton lays out camera, lens and light — and whether it is a measured rule or the plain appe…

No output schema declared.

No examples provided.

lab_propose ~1,003

Propose a generation for the user to confirm: validates the parameters against the catalog, computes the price, and shows a card (widget hosts) or returns the same object as text. NOTHING runs until lab_run_proposal is called with the returned vorschlag_id — by the card's button, or by you after the user said yes. Without a measured price there is no vorschlag_id and no button: the answer then says so instead of offering an estimate as if it were a quote. Free.

NameTypeReqDescription
aspect_ratiostring–Image: aspect ratio as W:H, from the model's aspect_ratios in lab_list_models.
audio_urlstring–Video: URL of an existing audio track to lay under the clip. Independent of generate_audio.
camera_motionstring–Video: 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 (from lab_list_characters) whose reference image locks the cast's identity. Counted against the model's max_references and shown on the card by name.
costume_refsarray–The costume plate of these characters goes along as an extra reference image — the outfit on an invisible mannequin, NO person. Every id must also be in character_refs. Needs a model whose max_refere…
duration_secondsnumber–Video: clip length in seconds, inside the model's duration grid from lab_list_models. The card shows the DELIVERED seconds and says so when the provider snaps.
end_image_idstring–Video: the completed image to land the clip on (last frame). Only where lab_list_models says supports_end_frame.
familiestring–Video: pick the model ('seedance-2.0', 'seedance-2.5') instead of a route — the card then names and prices the route the server takes for this account, and the run is PINNED to it (a card promises on…
generate_audioboolean–Video: ask for the model's native audio. Only meaningful where lab_list_models says audio: schaltbar.
in_secnumber–Video: start of the excerpt cut out of the reference clip, in seconds. Only together with out_sec and source_video_id.
intentstring–Video intent from the routing rules. Used to choose a model when tool is omitted and retained for Plan B; an explicit tool wins.
kindstringyesWhich kind of generation to propose
location_idstring–Location board id (from lab_list_locations) — anchors the shot in the same place.
out_secnumber–Video: end of the excerpt in the reference clip, in seconds. Must lie behind in_sec.
project_idstringyesProject id (from lab_list_projects)
promptstringyesWhat to generate. The user can edit it on the card; lab_run_proposal takes the edited text as prompt_override without a new proposal.
referenzenarray–Video, clip path (source_video_id): typed references. The position IS the address — first image @Image1, first extra clip @Video2, first sound @Audio1. Image references are measured before sending an…
resolutionstring–Resolution tier, exactly as listed for the model in lab_list_models. Omit for the model's default.
scene_refstring–Scene label (e.g. 'SZ 04'). Stored on the row, so the result can be matched back to a shot list.
seed_image_urlstring–Image: run img-to-img guided by this existing image URL. Shown on the card as the 'before'.
source_image_idstring–Video: the completed image to animate (positive integer as string). Required for a video proposal — unless source_video_id proposes a clip instead.
source_video_idstring–Video: propose a run FROM A CLIP instead of a still — a generated video id (lab_animate/lab_job_status) or an asset key (lab_list_assets). Mutually exclusive with source_image_id; only for models tha…
toolstring–Model id, copied verbatim from lab_list_models. Omit to use the default for this kind — the card names it and prices it either way.
variantsinteger–Image: how many variants (default 1). Multiplies the price — the card shows the multiplication.

No output schema declared.

No examples provided.

lab_reference_motion ~2,081

Render a new clip FROM the motion of an existing one: your reference clip leads (camera move, blocking, timing), the model restyles what happens in it. Pass the clip's URL directly — the one you already have from lab_list_assets (asset_type 'video'), lab_job_status or lab_review_queue; nothing is looked up. Reference images bind cast, place and look; in_sec/out_sec cut the reference server-side before it ever reaches the provider, so you pay for the excerpt, not the source. Same backend path as lab_animate's source_video_id, with the fields that only exist there. Costs credits when called without get_cost. WITHOUT a reference clip (leave reference_video_url out), the images and sounds in `referenzen` alone guide the run — only for models whose lab_list_models entry says referenzen_ohne_video: true, and only FACELESS references (ort, stil, bild, stimme, ton): Seedance 2.5 rejects faces as reference images, even invented characters (measured 2026-09-27), so `figur` is refused before anything is charged. For a person, build a still with them first and animate it with lab_animate. Name the references in the prompt as 'reference only, never shown on screen', and avoid the word 'static' for short shots — it tends to return frozen frames.

NameTypeReqDescription
aspect_ratiostring–Output aspect ratio on this path, written as width:height or 'auto'. Only models whose lab_list_models entry takes it on the reference path accept it; for any other model the backend refuses it befor…
character_ref_urlsarray–Ready image URLs that bind the cast's identity. The name says URLs on purpose: lab_animate's `character_refs` takes character sheet IDS, this path takes ADDRESSES, and the two are not interchangeable…
duration_secondsnumber–Length of the NEW clip. Must lie inside the chosen model's duration grid from lab_list_models — the per-model ceiling is enforced by the backend and rejected rather than silently clamped.
first_frame_urlstring–Guiding frame for the START of the new clip (image URL). Only the wan_vace path binds guiding frames to the provider — with any other model the backend REJECTS this field instead of swallowing it, be…
generate_audioboolean–Let the model generate sound with the clip — only models whose lab_list_models entry can output audio take it on this path. Omitted = no generated sound. Generated audio REPLACES any voice in the ref…
get_costboolean–Preflight: return the price in credits and your balance WITHOUT generating and without spending anything, reading the same catalog as lab_list_models. Do this before a long take or when the user shou…
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.
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…
last_frame_urlstring–Guiding frame for the END of the new clip (image URL). Same rule as first_frame_url: wan_vace only, rejected elsewhere rather than dropped.
out_secnumber–End of the excerpt in the reference clip, in seconds. Must lie behind in_sec; both are set together or neither.
project_idstringyesProject id (from lab_list_projects) — positive integer as string. On this path it travels in the request BODY, not in the URL, but it is just as required: the new clip is filed under this project.
promptstringyesWhat the new clip should show. Describe it — do NOT phrase it as an instruction to edit or extend the reference; some models classify the run by the verb and then reject the aspect ratio and duration…
reference_video_urlstring–URL of the clip whose motion is taken. Use the url/video_url a previous answer gave you (lab_list_assets with asset_type 'video', lab_job_status, lab_review_queue) — never a hand-built address: the b…
referenzenarray–The typed successor of character_ref_urls: each reference says WHAT it is, so a place or a look no longer has to travel disguised as a character. Since 2026-09-03 it carries all three channels, not j…
resolutionstring–Render resolution on this path, copied verbatim from the model's resolutions in lab_list_models. The run is priced at the resolution you choose — the low tier costs a fraction of the default — so pas…
taskstring–reference (default): the references guide a new clip. editing: the picture of the reference clip stays and only what the prompt names changes — e.g. 'keep the picture, generate matching sound effects…
tonstring–Which sound the result carries. quelle: the reference clip's own audio is laid back under the new picture after generation — the way to keep a spoken take, since models that regenerate audio replace…
toolstring–Video model id — copy it verbatim from lab_list_models (kind: video), and only models the catalog marks v2v take a reference clip at all. Omit to let the backend use its own default for this path. Du…
use_depthboolean–Condition the run on a depth pass of the reference clip. Defaults to ON in the backend; pass false to opt out. Models that do not have a depth stage ignore it — the answer says so rather than pretend…
wechsel_vonstring–The model id this call switches AWAY from (as listed in lab_list_models), with the same references as before. The answer then carries `wechsel`: which references the switch cuts off and why, and whic…

No output schema declared.

No examples provided.

lab_regie_techniken ~178

Directing techniques: camera angle, framing, composition, movement and lighting, each with the emotional effect it creates (wirkung), when to use it (zweck_de), when it backfires (vermeiden_de) and a model-neutral prompt fragment (prompt_en). Search by effect (e.g. wirkung=bedrohung, isolation, sehnsucht) to find the ways to get there, then pass up to three `schluessel` to lab_prompt_transform(techniken) — the fragments are appended verbatim, not rewritten. One angle, one movement and one lighting setup per shot; framing and composition stack. Read-only, free.

NameTypeReqDescription
gruppestring–Only one group
wirkungstring–Only techniques with this effect key — the answer lists all keys under `wirkungen`

No output schema declared.

No examples provided.

lab_render_frames ~305

See the DELIVERED film: up to 12 frames from the finished export (lab_start_export → lab_get_export status done), tiled into one image and shown. This is the rendered picture WITH everything the render adds — lens/grade, lower thirds, title cards and the AI badge — so use it to check the result, e.g. 'is the lower third readable at 7 s, does the badge cover anything'. lab_capture shows the cut BEFORE rendering (computed from the timeline, without those layers); this tool shows what was actually delivered. Give `sekunden` (seconds into the exported film) or `verteilt` (n frames spread evenly; default 6 when both are missing). A second past the end is an error with the film's length, not a silently clipped frame. Only finished exports with a video (not archive/PNG-sequence profiles). Free (no credits).

NameTypeReqDescription
job_idstringyesExport job id from lab_start_export / lab_list_exports — positive integer as string
kachel_breiteinteger–Width of one frame in px (default 480)
previewboolean–Show the image inline (default true)
sekundenarray–Seconds into the exported film, e.g. [0.5, 7.0]. Order is kept (4 per row)
verteiltinteger–Instead of sekunden: this many frames spread evenly over the film

No output schema declared.

No examples provided.

lab_restyle_location ~129

Restyle an existing board towards a wish (costs quota) — same place, different look, e.g. 'the same flat, twenty years later'. Changes the board itself, so images generated afterwards follow the new style. Also the repair path for a board whose prompt_prefix_en is a raw field dump (lab_create_location returned prefix_generated: false): restyle it with a wish like 'keep the place, write a proper image prompt'.

NameTypeReqDescription
loc_idstringyesLocation board id (from lab_list_locations)
wishstringyesThe desired change, in prose

No output schema declared.

No examples provided.

lab_review_asset ~247

Review generated assets: set verdict (accepted|rejected|pending) and/or selected. Pass ONE id, or `ids` for a bulk review — after a generation run there are usually dozens to sort, and clicking through them one by one is why the review fields went unused. Rejected assets drop out of the default listings and become prunable. Note: single-id calls make `selected` exclusive per scene (one chosen variant per scene_ref); bulk calls do NOT, because a bulk over one scene would keep resetting itself and only the last id would stay selected.

NameTypeReqDescription
idstring–Single asset id (positive integer as string). Use this for the per-scene selection
idsarray–Many asset ids for a bulk review (max 200). Mutually exclusive with `id`
reasonstring–Why — stored as verdict_reason, useful when reviewing a rejection later
reference_typestringyesWhat kind of asset these ids refer to
selectedboolean–Mark as the chosen variant
verdictstring–Acceptance verdict. Feeds the acceptance telemetry (which provider/mode/price actually produced usable shots)

No output schema declared.

No examples provided.

lab_review_queue ~558

Browse GENERATED rows (images or videos) — newest first, each with the INPUTS it ran on. Every row carries `inputs[]` (start/reference images, reference videos, character refs — role + url) and `params` (model, mode, resolution, seed…). Read those before comparing two runs: a run without its inputs is a claim with a picture attached, and a comparison described as one-variable has more than once turned out to differ in three. An input whose URL was never recorded appears as `origin: 'unrecorded'` — that is a gap in the write path, NOT a text-to-* run. Two modes. PER PROJECT (pass project_id + type): adds the review filters — verdict, selected_only, scene_ref — and carries `selected`. ACROSS PROJECTS (omit project_id, or pass since/until/tool_used/cursor): the time-range view for 'what ran on August 3rd?'. The review filters do not exist there and are rejected rather than silently dropped. Page with `next_cursor`.

NameTypeReqDescription
cursorstring–ACROSS PROJECTS. The next_cursor of the previous page. Opaque — do not build one by hand
include_rejectedboolean–PER PROJECT ONLY. Include rejected in the default listing
limitinteger–Max rows (per project default 50). Across projects the page is capped at 20 so next_cursor stays exact
previewboolean–Attach the pictures themselves, downscaled to 512px, so a generation run can be SORTED by looking instead of by reading prompts. At most 4 per call — narrow the list with scene_ref/limit rather than…
project_idstring–Project id (from lab_list_projects). Omit to search across all projects
scene_refstring–PER PROJECT ONLY. Only this scene
selected_onlyboolean–PER PROJECT ONLY. Only the chosen variants
sincestring–ACROSS PROJECTS. created_at >= this ISO-8601 timestamp (e.g. 2026-08-03T00:00:00Z)
tool_usedstring–ACROSS PROJECTS. Exact tool/provider name, e.g. seedance-2.5
typestring–Which generated rows. Required per project; across projects, omit for both
untilstring–ACROSS PROJECTS. created_at <= this ISO-8601 timestamp
verdictstring–PER PROJECT ONLY. Exact verdict filter. Omit to get everything except rejected

No output schema declared.

No examples provided.

lab_run_module ~154

Run ONE pipeline module for a project (context is injected from upstream modules + crew agents). SYNCHRONOUS and LLM-heavy: light modules return in seconds; heavy ones can exceed ~55s and then time out (504) — run those in the FilmLab web app instead. Pass an invalid module name to get the list of valid module keys. Returns the module output.

NameTypeReqDescription
messagestringyesYour instruction/prompt for this module (the user turn in the module chat)
modulestringyesPipeline module/stage key, e.g. mod_concept, mod_storyboard, mod_shotlist, mod_script
project_idstringyesProject id (from lab_list_projects)

No output schema declared.

No examples provided.

lab_run_proposal ~310

Run a proposal exactly as shown — same model, same parameters, same price. Called by the card's button, or by you after the user confirmed. Single use: the proposal is consumed BEFORE the run, so a second call is refused instead of paying twice. Valid 15 minutes, for the account that created it. Costs credits. The run is checked against what you confirmed only when it FINISHES; poll lab_job_status and read review there. This answer carries review only if the run completed synchronously.

NameTypeReqDescription
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…
prompt_overridestring–Replace ONLY the prompt text of the stored proposal. Every other parameter — model, resolution, duration, references — and the price stay exactly as shown. This is the path for a prompt the user edit…
vorschlag_idstringyesThe id from lab_propose or plan_b in lab_job_status. Do not construct one — an unknown id answers 'vorschlag_abgelaufen', not an error you can work around.

No output schema declared.

No examples provided.

lab_scopes ~295

Measure ONE clip of the edit as numbers instead of a picture: a frame is rendered through the clip's export path (input profile, grade LUT, secondary correction) and measured — luma percentiles (P1/P50/P99, Rec.709), mean R/G/B, green excess (G minus the mean of R and B: >0 green cast, <0 magenta), vectorscope centroid (Cb, Cr), clipped highlights and crushed shadows. `befund` says what is off in words with the number; `vorschlag.grade` is a correction computed on a sample of the source through the clip's full grade (gamma wheel master first, then exposure, temperature, tint, gain wheel) towards median luma 0.42 and no cast WITHOUT pushing highlights into clipping, with the values it expects — pass it to lab_grade_clip, then measure again. When nothing more is gained, `vorschlag.grade` is null and `grund` says why. Give clip_id (from lab_grade_clip without grade) or zeit_s (seconds on the timeline); default is the middle of the clip. Writes nothing, costs nothing.

NameTypeReqDescription
clip_idstring–Clip to measure
seq_idstringyesSequence id — positive integer as string
zeit_snumber–Timeline position in seconds (picks the clip there; within a clip_id: the frame)

No output schema declared.

No examples provided.

lab_search_catalog ~57

Search the FilmLab universe catalog of AI tools, news and companies. Query must be at least 2 characters. Returns up to 20 matches with a total count.

NameTypeReqDescription
qstringyesSearch query, min 2 characters

No output schema declared.

No examples provided.

lab_sfx ~1,097

Generate or CLEAN UP a SOUND track other than music — sound effects, ambience/atmosphere, dialog, a voiceover, FOLEY scored to an existing clip, or the repair kinds that take an EXISTING recording apart instead of inventing one: denoise (take the noise out), split (separate it into stems), isolation (keep the voice, drop the rest). All of it goes through the same audio pipeline as lab_generate_music. ASYNCHRONOUS: the call returns immediately with a row whose `audio_url` is null and `metadata.status` is 'pending'. Nothing is playable yet. Poll lab_list_audio (matching audio_type) until that row's status is 'completed' and audio_url is set; a failed row refunds its credits and carries metadata.error. The backend picks the provider for the chosen `art` on its own — there is no `tool` parameter here.

NameTypeReqDescription
artstringyesKind of track — sfx (a single sound effect), ambience (a continuous atmosphere/soundscape), dialog (a spoken line), voiceover (narration), foley (sound derived FROM an existing clip and synced to wha…
audio_idstring–REPAIR KINDS ONLY, and the best of the three ways to name a source: an existing audio row of this project (from lab_list_audio), which has an owner and an address that belongs to us. Chain it — denoi…
audio_urlstring–REPAIR KINDS ONLY, and the last resort: a bare address of a sound file. It carries no owner, so nothing can be checked against the project — prefer `audio_id` or `video_id`. A provider address is cop…
duration_secondsnumber–Desired length in seconds. The backend clamps this to what the chosen provider actually supports for this `art` — dialog/voiceover ignore it entirely, the length follows the text, and foley ignores i…
get_costboolean–`true` reports the price and your balance WITHOUT generating anything and without spending quota. Not drawn from the lab_list_models catalog (that covers image/video models only) — audio pricing foll…
project_idstringyesProject id (from lab_list_projects) — positive integer as string
promptstring–What the sound should be. For sfx/ambience: name the source and character of the sound. For dialog/voiceover: the line or text to speak. Required for every art EXCEPT foley — foley watches the clip,…
scene_refstring–Optional scene label, stored on the row. Useful to tell several tracks of one project apart
stemsarray–SPLIT ONLY: which parts to separate out. Left out, you get the voice and the rest of the recording, each part as its own audio row. Asking for a subset drops what you leave out — there is no combined…
video_idstring–The clip to work from. For FOLEY it is required to RUN one; for the repair kinds it is one of the three ways to name a source, and the backend extracts the audio track from it. From lab_list_assets o…

No output schema declared.

No examples provided.

lab_shots ~297

Read the SHOT layer of a sequence — which clips form one shot, which scene it plays in, who is in it, and what the continuity pass found. This is the layer above the timeline: lab_get_sequence gives you clips in a row, this one gives you the cut. Costs nothing, writes nothing. Use it before changing a cut: a shot binds clip_ids, so the times come out of the timeline and a shot whose clips you shorten simply gets shorter. Read `clips_ohne_shot` as well — it says how far the meaning lags behind the timeline, and an empty `shots` list usually means nobody has derived them yet (lab_shots_ableiten does that, for free). Every shot reports `clips_verwaist` (clip_ids that no longer exist in the timeline) and `zusammenhaengend` (false when another shot's clip sits between this one's): a torn shot is allowed — one location cut into twice — but it says so, instead of showing a duration longer than the sum of its clips.

NameTypeReqDescription
rungstring–Which level to read. 'shot' (the default) is one take; 'movement' groups shots into arcs. They are independent layers over the same clips — reading one never shows the other
seq_idstringyesSequence id (from lab_create_sequence/lab_list_sequences) — positive integer as string

No output schema declared.

No examples provided.

lab_shots_ableiten ~232

Derive the shot layer from what the clips already say about themselves — consecutive clips of the same scene become one shot, and a scene that returns later becomes a second one (one location cut into twice is two shots). Costs nothing: it groups rows and reads titles, it generates nothing. Titles come from the project's shotlist where the scene is in there, so this is more than a regrouping — it fetches meaning the pipeline already produced. SHOTS YOU SET BY HAND SURVIVE. Only derived ones are replaced, and clips already held by a manual shot are left out of the grouping entirely — a derivation does not take handwork's material away. Read `clips_ohne_szene` in the answer: those clips say nothing about where they belong, so each became its own shot. That number is a job for the pipeline, not a fault of this call — and grouping two nameless clips would be a claim about connection that nobody made.

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

No output schema declared.

No examples provided.

lab_shots_setzen ~376

State the shot cut yourself: which clips form one shot, what it is called, which scene it plays in. This is the counterpart to lab_shots_ableiten — that one groups by the scene the clips already name, this one is for the judgement no field carries. Costs nothing. Use it where derivation cannot reach: ingested footage has no shotlist by nature, and a sequence whose clips name no scene would come out of a derivation as one shot per clip — the timeline under another name. It is also the ONLY way to build the 'movement' layer (arcs over shots); the derivation only ever writes 'shot'. REPLACES the whole level in one go: every shot of this `rung` that you do not list is gone. The other level is untouched — recutting shots does not throw the arcs away. Refusals happen BEFORE anything is written: an unknown clip_id, or the same clip in two shots of one level. A half-set shot list looks like a result and is none. Read lab_shots first and send its clip_ids back — a shot binds clip identities, not time ranges, so shortening a clip later simply shortens the shot. What you set here counts as handwork: a later lab_shots_ableiten leaves these shots alone and does not touch their clips.

NameTypeReqDescription
rungstring–Which level to replace. 'shot' (the default) is one take; 'movement' groups shots into arcs. Independent layers over the same clips — writing one never touches the other
seq_idstringyesSequence id (from lab_create_sequence/lab_list_sequences) — positive integer as string
shotsarrayyesThe whole level, in order. The order here IS the order of the shots

No output schema declared.

No examples provided.

lab_start_export ~733

Start an ASYNC export render of a project sequence. Returns a job_id immediately (status 'queued') — does NOT block. Then poll lab_get_export with that job_id until status is done|failed. Needs the sequence_id to render (an integer from the project's sequences). `derivatives` asks for extra cut-downs of the SAME render (portrait for social) alongside the main file — their URLs come back in the finished job's `derivatives`. The finished job also carries `zielmarkt_checkliste` (delivery checklist per target market, set with lab_zielgruppe).

NameTypeReqDescription
derivative_regionstring–Which part of the wide frame the portrait crop keeps. Default 'center' — pick 'left' or 'right' when the subject stands off to one side, otherwise the crop cuts it in half.
derivativesarray–Extra cut-downs rendered from the FINISHED export, on top of the main file. '9x16' is a deterministic crop of the wide render into portrait — what falls outside the portrait frame is gone, not filled…
include_stemsboolean–Also export audio stems separately (default false)
kennzeichnung_umfangstring–For a film that mixes people-made material ('eigen', see lab_herkunft) with AI material: 'film' (default) marks the whole film; 'abschnitte' shows the mark only while an AI or undeclared clip is on s…
ki_kennzeichnungstring–How the visible AI disclosure (EU AI Act Art. 50(4)) appears when the sequence contains AI material. Default 'minimal': a small 'KI' mark in the corner for the whole film. 'durchgehend': the larger '…
profilestring–Delivery profile (default 'web'). See lab_export_profiles. 'alpha_prores4444' and 'alpha_png_sequence' keep transparency and are refused with an explanation unless a clip in the sequence really carri…
project_idstringyesProject id (from lab_list_projects)
qualitystring–Quality preset (default 'standard')
sequence_idstringyesSequence id to render (positive integer as string, e.g. '27')
werk_kuenstlerischboolean–Confirm the work is artistic, fictional or satirical — only then may the disclosure be limited to the opening or the end card. Set it only when that is true; the choice is recorded with the export.

No output schema declared.

No examples provided.

lab_suggest_durations ~193

Ask what clip durations the project's cutting preset WOULD give a sequence — and change nothing (`angewendet: false`). Use it to see the consequence before lab_apply_rhythm writes it, or to size a sequence that has no clips yet (pass `anzahl`). It knows nothing about the measured beat grid: the tempo it uses is the text from the preset's music brief ('mittel bis schnell, 100–128'), which is a promise, not a measurement. Only lab_apply_rhythm reaches for the grid that lab_beatgrid measured. Reads only — no state, no credits.

NameTypeReqDescription
anzahlinteger–How many shots to distribute. Omit to use the sequence's existing clip count — required if the timeline is still empty, which otherwise answers 400
seq_idstringyesSequence id (from lab_create_sequence/lab_list_sequences) — positive integer as string

No output schema declared.

No examples provided.

lab_timeline_apply ~589

Write a WHOLE cut into a sequence in one call — clips in order with their lengths, an optional dissolve between them, an optional bed underneath. This is the counterpart to lab_get_sequence: that one reads the timeline, this one writes it. Prefer it over a chain of lab_add_clip calls whenever you already know the whole cut: a chain that breaks in the middle leaves half a sequence behind, this either applies or refuses. Costs nothing — it validates and writes rows, it generates nothing. Every video_id is checked against the project BEFORE anything is written, so a wrong id is a refusal here and not a gap in the cut nobody notices. Pass `sequence_id` to write into THAT sequence; omit it and a new one is created. Pass `sequence_id` WITHOUT a manifest to read back the stored cut as a manifest — for an agent that already has the sequence_id and wants to see what is in there before changing it. (The Resolve bridge does NOT go through here: it talks to the FilmLab server directly with its own bridge key and does not know this MCP.) Reworking a cut you read back? Keep each clip's `clip_id`. A clip that comes back with its identity keeps its track, its in-point in the source and its scene, and the shots bound to it stay bound; a clip without one is treated as new and gets a fresh identity, which orphans whatever pointed at the old one. Two honest limits: the Resolve bridge applies the clips but reports `uebergang` and the bed's level/fade as not applied (its scripting API has neither a transition call nor a clip volume property). The FilmLab sequence render applies the bed with its level and fade, but NOT `uebergang` yet — dissolves are stored and render as hard cuts (checked 2026-10-03).

NameTypeReqDescription
erwartete_revisionstring–The `revision` you read (from lab_get_sequence or this tool's read-back). The cut is written only if the sequence still has exactly that content — otherwise nothing is written and you get `revision_v…
manifestobject–The cut as one object. Omit it only together with a `sequence_id`, to read back what is stored
project_idstringyesProject id (from lab_list_projects) — positive integer as string
sequence_idstring–Sequence to write into (from lab_create_sequence/lab_list_sequences). Omit to create a new one. Given WITHOUT a manifest, the stored manifest is read back instead of written
titlestring–Title for the sequence created when `sequence_id` is omitted

No output schema declared.

No examples provided.

lab_ton_durchlauf ~388

Generate SOUND EFFECTS for a whole sequence, shot by shot — Simon Meyer's pass: every shot is muted, padded with black frames up to the model's minimum length, re-rendered by Seedance 2.5 in editing mode at its low resolution with sound on, and only the generated sound is kept, stretched back to the original timing (the black padding is the sync marker) and laid at the shot's position. The result is ONE sfx track in sequence length, bound to the sequence's sfx stem; the other stems stay as they are. Each piece and its offset are listed in the audio row's metadata (stuecke). Shots come from the sequence itself, in export order and export length — no cut detection. Costs credits, priced per shot over the seconds actually sent (the padding counts); call with get_cost first. ASYNCHRONOUS: returns a job_id; poll the job until done. A shot that fails is refunded on its own and named in fehlende_einstellungen; if the whole run fails, all of it is refunded. The model is told: keep the picture, diegetic sound only, no music, no dialogue, no voices — `hinweis` adds a setting line for every shot.

NameTypeReqDescription
get_costboolean–Return the price in credits WITHOUT starting anything — per shot over the seconds actually sent, at the rate lab_list_models lists for the model. Do this first; long sequences add up.
hinweisstring–One line about the setting that applies to every shot, e.g. 'kitchen, wooden floor, rain on the window'. Helps the model pick the right room sound. Leave it out if the shots differ too much.
seq_idstringyesSequence id (from lab_create_sequence/lab_list_sequences) — positive integer as string

No output schema declared.

No examples provided.

lab_transform ~550

Relight and restyle an EXISTING clip while the performance stays untouched (Beeble Switch X): lighting, background and props change, the subject and its motion do not. The source is the clip of a generated-video row — or, with asset_id, an uploaded file that stands in for it. in_sec/out_sec cut the source server-side first, so a long take can be transformed in pieces. ASYNCHRONOUS: a new video row comes back as pending; poll it with lab_job_status. Costs credits when called without get_cost.

NameTypeReqDescription
alpha_modestring–How the subject is cut out from its background. Omit to let the backend decide ('auto'); the other modes fill, take a supplied matte, or work on a selection.
asset_idstring–R2 asset key of an uploaded video (the `key` from lab_list_assets, asset_type 'video') to transform INSTEAD of the row's own clip. The row from video_id still supplies project and scene; only the pix…
get_costboolean–`true` returns the published rate per unit and your balance WITHOUT transforming and without spending anything — NOT a total. Switch X charges by the MEASURED length of the source, which only the ser…
in_secnumber–Cut the source server-side before it reaches the provider: start of the excerpt, in seconds. Only together with out_sec. What is billed is the MEASURED length of the cut, not out_sec minus in_sec.
out_secnumber–End of the excerpt, in seconds. Must lie behind in_sec; both are set together or neither.
resolutionstring–Output tier of the transform. This is Switch X's OWN tier list, not one of the video-model resolutions in lab_list_models — that catalog covers generation models and has no entry for this path. The t…
transformation_promptstringyesWhat the clip should look like afterwards — light, place, props. The subject and its performance are preserved by the model; describing them again does not help.
video_idstringyesGenerated-video id (from lab_animate/lab_job_status/lab_review_queue) — positive integer as string. ALWAYS required, also together with asset_id: this row anchors the run (project, scene, billing) an…

No output schema declared.

No examples provided.

lab_upscale ~419

Enlarge an EXISTING clip (Topaz, passed through fal): same shot, same length, same sound — more pixels. There is no prompt here; nothing is re-imagined, the frames are scaled. The source is the clip of a generated-video row. Both the length and the source height are measured server-side before anything is charged, and a source too tall for the larger factor is refused rather than run. ASYNCHRONOUS: a new video row comes back as pending; poll it with lab_job_status. Costs credits when called without get_cost.

NameTypeReqDescription
faktorstring–How many times larger, per side. Omit for the smaller one. Whichever you pick, the RESULT has to stay inside the published rate tiers — a source too tall for the factor you asked for is refused by na…
get_costboolean–`true` returns what upscaling THIS clip costs (`cost_generations`, measured server-side from its length and the height of the RESULT, exactly what the run would charge) plus the published rate per ou…
max_creditsinteger–The most you agree to pay — pass the amount from get_cost that the person confirmed. If the measured price is higher when the run starts, it is refused before anything is charged.
video_idstringyesGenerated-video id (from lab_animate/lab_job_status/lab_review_queue) — positive integer as string. The row must already have its clip; a run still pending is refused, and nothing is charged for aski…

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.