FilmLab
REMOTE · MCP-LAB.THEFILMRADAR.COM · SCANNED OCT 5
AI film lab for filmmakers: generate and review images/clips with input provenance, cost preflight
Available components
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
- The endpoint's TLS certificate is valid, in date, and uses a strong key. View diagnostics → Pass
- 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. View diagnostics → Pass
- HTTPS is enforced; there's no plaintext access path. View diagnostics → Pass
- HSTS check failed: the Strict-Transport-Security header is absent. See how to fix → View diagnostics → Fail
- DNSSEC check failed: this domain isn't protected by DNSSEC. See how to fix → View diagnostics → Fail
- The authorisation server offers only Dynamic Client Registration (RFC 7591), which MCP 2026-07-28 deprecated in favour of Client ID Metadata Documents. View diagnostics → Partial
Transport & Reachability100
- Verified streamable-http transport via a live MCP handshake. View diagnostics → Pass
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
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
claude mcp add --transport http com-thefilmradar-filmlab 'https://mcp-lab.thefilmradar.com/mcp'
{
"mcpServers": {
"com-thefilmradar-filmlab": {
"url": "https://mcp-lab.thefilmradar.com/mcp"
}
}
} {
"servers": {
"com-thefilmradar-filmlab": {
"type": "http",
"url": "https://mcp-lab.thefilmradar.com/mcp"
}
}
} [mcp_servers.com-thefilmradar-filmlab] url = "https://mcp-lab.thefilmradar.com/mcp"
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"com-thefilmradar-filmlab": {
"type": "remote",
"url": "https://mcp-lab.thefilmradar.com/mcp",
"enabled": true
}
}
} openclaw mcp add com-thefilmradar-filmlab --url 'https://mcp-lab.thefilmradar.com/mcp' --transport streamable-http
mcp_servers:
com-thefilmradar-filmlab:
url: "https://mcp-lab.thefilmradar.com/mcp" {
"McpServers": {
"com-thefilmradar-filmlab": {
"Transport": "http",
"Url": "https://mcp-lab.thefilmradar.com/mcp"
}
}
} assistant mcp add com-thefilmradar-filmlab -t streamable-http -u 'https://mcp-lab.thefilmradar.com/mcp'
{
"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.
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.
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 |
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 →
lab_get_state 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.
| Name | Type | Req | Description |
|---|---|---|---|
| project_id | string | – | Add a project view |
No output schema declared.
No examples provided.
lab_grade Grade Image ~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.
| Name | Type | Req | Description |
|---|---|---|---|
| contrast | string | – | Contrast curve: high is an S-curve, low flattens it |
| exposure | number | – | Exposure in stops; positive brightens, zero is neutral |
| from_colorist | boolean | – | Start from the project's colorist crew brief (look/contrast/grain), then apply the sliders on top |
| grain | number | – | Film grain amount; zero is none, monochrome |
| hue | number | – | Hue rotation in degrees; zero neutral |
| image_id | string | yes | Id of the source image in the project gallery (from lab_list_assets / lab_generate) |
| lightness | number | – | Lightness; negative darkens, zero neutral |
| look | string | – | 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_opacity | number | – | Blend of the named look, 0..1 (default 1) |
| project_id | string | yes | Project id (from lab_list_projects) |
| saturation | number | – | Colour saturation; minimum is greyscale, zero neutral |
No output schema declared.
No examples provided.
lab_grade_clip Grade a Clip in the Edit ~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…
| Name | Type | Req | Description |
|---|---|---|---|
| clip_id | string | – | The clip to grade (from the listing); omit with programm:true |
| grade | object | – | Fields to set — see description; omit to list clips and grades |
| programm | boolean | – | Grade the whole programme instead of one clip |
| seq_id | string | yes | Sequence id — positive integer as string (lab_list_sequences) |
| zuruecksetzen | boolean | – | Start from a neutral grade before applying `grade` |
No output schema declared.
No examples provided.
lab_grade_from_resolve Suggest Grade Look from Resolve LUT ~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.
| Name | Type | Req | Description |
|---|---|---|---|
| lut | string | yes | LUT 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 Suggest Grade Look ~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.
| Name | Type | Req | Description |
|---|---|---|---|
| image_id | integer | – | Generated image id belonging to the project; includes its prompt in the suggestion |
| project_id | string | yes | Project id (from lab_list_projects) |
No output schema declared.
No examples provided.
lab_herkunft Material Origin ~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`).
| Name | Type | Req | Description |
|---|---|---|---|
| asset_key | string | – | Storage key of the file (from lab_add_media or lab_list_assets). Omit to list |
| herkunft | string | – | Required together with asset_key |
| project_id | string | yes | Project id — positive integer as string |
No output schema declared.
No examples provided.
lab_job_status Generation 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…
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | The id returned by lab_generate (image) or lab_animate (video) |
| preview | boolean | – | 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_id | string | yes | Project id — required, since there is no global id lookup |
| type | string | yes | Whether the id refers to a generated image or a generated video |
No output schema declared.
No examples provided.
lab_jobs_inflight Jobs In Flight ~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.
| Name | Type | Req | Description |
|---|---|---|---|
| job_type | string | – | 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_seconds | integer | – | 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 Generate Cut-Out Layer Element ~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.
| Name | Type | Req | Description |
|---|---|---|---|
| get_cost | boolean | – | 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_type | string | – | 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… |
| metadata | object | – | 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_id | string | yes | Project id (from lab_list_projects) — positive integer as string. Travels in the URL; the element is filed in this project's gallery. |
| prompt | string | yes | What 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_ref | string | – | 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 Last Frame of a Clip ~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.
| Name | Type | Req | Description |
|---|---|---|---|
| scene_ref | string | – | Scene for the new image; default: the clip's |
| video_id | string | yes | A finished clip (positive integer as string) |
No output schema declared.
No examples provided.
lab_list_assets 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.
| Name | Type | Req | Description |
|---|---|---|---|
| asset_type | string | – | Filter by asset type (optional) |
| preview | boolean | – | 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_id | string | yes | Project id (from lab_list_projects) |
No output schema declared.
No examples provided.
lab_list_audio List Generated 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.
| Name | Type | Req | Description |
|---|---|---|---|
| audio_type | string | – | 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… |
| limit | integer | – | 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_id | string | yes | Project id (from lab_list_projects) — positive integer as string |
| scene_ref | string | – | Filter by the scene label passed at generation time |
No output schema declared.
No examples provided.
lab_list_characters 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.
| Name | Type | Req | Description |
|---|---|---|---|
| preview | boolean | – | 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… |
| search | string | – | Substring of the character name or project name (case-insensitive) |
No output schema declared.
No examples provided.
lab_list_exports 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).
| Name | Type | Req | Description |
|---|---|---|---|
| project_id | string | yes | Project id (from lab_list_projects) |
No output schema declared.
No examples provided.
lab_list_location_scans 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.
| Name | Type | Req | Description |
|---|---|---|---|
| project_id | string | yes | Project id (from lab_list_projects) — positive integer as string |
No output schema declared.
No examples provided.
lab_list_locations 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.
| Name | Type | Req | Description |
|---|---|---|---|
| preview | boolean | – | 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… |
| search | string | – | Filter by board name or project name (substring, case-insensitive) |
No output schema declared.
No examples provided.
lab_list_models Model Catalog ~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.
| Name | Type | Req | Description |
|---|---|---|---|
| kind | string | yes | Which catalog |
| klasse | string | – | Only one capability class (e.g. the class name from a previous answer) |
No output schema declared.
No examples provided.
lab_list_project_locations 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.
| Name | Type | Req | Description |
|---|---|---|---|
| project_id | string | yes | Project id (from lab_list_projects) |
No output schema declared.
No examples provided.
lab_list_projects 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 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.
| Name | Type | Req | Description |
|---|---|---|---|
| project_id | string | yes | Project id (from lab_list_projects) — positive integer as string |
No output schema declared.
No examples provided.
lab_list_voices List Cloned 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.
| Name | Type | Req | Description |
|---|---|---|---|
| project_id | string | yes | Project id (from lab_list_projects) — positive integer as string |
| provider | string | – | 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 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.
| Name | Type | Req | Description |
|---|---|---|---|
| camera_height | number | – | Camera height in metres (default 1.6, roughly eye level) |
| intent | string | yes | What the place is — the panorama prompt |
| loc_id | string | – | Persist the panorama on this location board (from lab_list_locations) |
| mood | string | – | Mood/atmosphere (default 'neutral') |
No output schema declared.
No examples provided.
lab_location_recon Reconstruct Location in 3D ~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.
| Name | Type | Req | Description |
|---|---|---|---|
| engine | string | – | 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_id | string | yes | Id 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_photos | integer | – | 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_id | string | yes | Project 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 Match the Look of a Scene ~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.
| Name | Type | Req | Description |
|---|---|---|---|
| clip_ids | array | – | Compare exactly these shots instead of the scenes from lab_shots |
| referenz_clip_id | string | – | The shot the others are matched to; default the first of the scene |
| seq_id | string | yes | Sequence id — positive integer as string |
| szene | string | – | 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 Set the Sound 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.
| Name | Type | Req | Description |
|---|---|---|---|
| katalog | boolean | – | Return the effect catalogue instead of changing anything |
| seq_id | string | yes | Sequence id — positive integer as string |
| tracks | array | – | Tracks to change — only the given fields are written |
No output schema declared.
No examples provided.
lab_mix_messen Measure the Rendered Mix ~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.
| Name | Type | Req | Description |
|---|---|---|---|
| seq_id | string | yes | Sequence id — positive integer as string |
No output schema declared.
No examples provided.
lab_mix_render Render the Sound Mix ~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.
| Name | Type | Req | Description |
|---|---|---|---|
| auto_preset | string | – | Run the auto-mix with this preset instead of rendering the mix as set |
| seq_id | string | yes | Sequence id — positive integer as string |
| target | string | – | Loudness target, default broadcast |
No output schema declared.
No examples provided.
lab_playbook Surface 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.
| Name | Type | Req | Description |
|---|---|---|---|
| flaeche | string | yes | The working surface |
No output schema declared.
No examples provided.
lab_prompt_transform 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).
| Name | Type | Req | Description |
|---|---|---|---|
| anlass | string | – | beautify only: what the image is FOR. Default frei |
| depth | string | – | video only: sketch (5 blocks, default) or skeleton (15 blocks) |
| duration_seconds | integer | – | 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. |
| familie | string | – | 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. |
| instruction | string | – | Required for custom (an order, e.g. 'make it darker') and stiluebernahme (a style description) |
| location_id | integer | – | 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. |
| medium | string | – | photo (default) or video — decides the section layout |
| mode | string | – | 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_id | integer | – | Optional, only with tool or familie: the project whose Lens Lab optics, Pose Director framing and gaffer light should be laid into the prompt. |
| prompt | string | yes | The text to work on — a loose thought is enough for beautify |
| referenzen | array | – | 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… |
| techniken | array | – | 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… |
| tool | string | – | 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 Propose Generation ~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.
| Name | Type | Req | Description |
|---|---|---|---|
| aspect_ratio | string | – | Image: aspect ratio as W:H, from the model's aspect_ratios in lab_list_models. |
| audio_url | string | – | Video: URL of an existing audio track to lay under the clip. Independent of generate_audio. |
| camera_motion | string | – | 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_refs | array | – | 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_refs | array | – | 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_seconds | number | – | 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_id | string | – | Video: the completed image to land the clip on (last frame). Only where lab_list_models says supports_end_frame. |
| familie | string | – | 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_audio | boolean | – | Video: ask for the model's native audio. Only meaningful where lab_list_models says audio: schaltbar. |
| in_sec | number | – | Video: start of the excerpt cut out of the reference clip, in seconds. Only together with out_sec and source_video_id. |
| intent | string | – | Video intent from the routing rules. Used to choose a model when tool is omitted and retained for Plan B; an explicit tool wins. |
| kind | string | yes | Which kind of generation to propose |
| location_id | string | – | Location board id (from lab_list_locations) — anchors the shot in the same place. |
| out_sec | number | – | Video: end of the excerpt in the reference clip, in seconds. Must lie behind in_sec. |
| project_id | string | yes | Project id (from lab_list_projects) |
| prompt | string | yes | What to generate. The user can edit it on the card; lab_run_proposal takes the edited text as prompt_override without a new proposal. |
| referenzen | array | – | 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… |
| resolution | string | – | Resolution tier, exactly as listed for the model in lab_list_models. Omit for the model's default. |
| scene_ref | string | – | Scene label (e.g. 'SZ 04'). Stored on the row, so the result can be matched back to a shot list. |
| seed_image_url | string | – | Image: run img-to-img guided by this existing image URL. Shown on the card as the 'before'. |
| source_image_id | string | – | 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_id | string | – | 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… |
| tool | string | – | 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. |
| variants | integer | – | Image: how many variants (default 1). Multiplies the price — the card shows the multiplication. |
No output schema declared.
No examples provided.
lab_reference_motion Motion from a Clip ~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.
| Name | Type | Req | Description |
|---|---|---|---|
| aspect_ratio | string | – | 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_urls | array | – | 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_seconds | number | – | 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_url | string | – | 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_audio | boolean | – | 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_cost | boolean | – | 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_sec | number | – | 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. |
| kamerapfad | object | – | 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_url | string | – | 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_url | string | – | 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_sec | number | – | End of the excerpt in the reference clip, in seconds. Must lie behind in_sec; both are set together or neither. |
| project_id | string | yes | Project 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. |
| prompt | string | yes | What 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_url | string | – | 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… |
| referenzen | array | – | 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… |
| resolution | string | – | 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… |
| task | string | – | 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… |
| ton | string | – | 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… |
| tool | string | – | 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_depth | boolean | – | 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_von | string | – | 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 Directing Techniques ~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.
| Name | Type | Req | Description |
|---|---|---|---|
| gruppe | string | – | Only one group |
| wirkung | string | – | Only techniques with this effect key — the answer lists all keys under `wirkungen` |
No output schema declared.
No examples provided.
lab_render_frames Frames of the Export ~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).
| Name | Type | Req | Description |
|---|---|---|---|
| job_id | string | yes | Export job id from lab_start_export / lab_list_exports — positive integer as string |
| kachel_breite | integer | – | Width of one frame in px (default 480) |
| preview | boolean | – | Show the image inline (default true) |
| sekunden | array | – | Seconds into the exported film, e.g. [0.5, 7.0]. Order is kept (4 per row) |
| verteilt | integer | – | Instead of sekunden: this many frames spread evenly over the film |
No output schema declared.
No examples provided.
lab_restyle_location 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'.
| Name | Type | Req | Description |
|---|---|---|---|
| loc_id | string | yes | Location board id (from lab_list_locations) |
| wish | string | yes | The desired change, in prose |
No output schema declared.
No examples provided.
lab_review_asset 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.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | – | Single asset id (positive integer as string). Use this for the per-scene selection |
| ids | array | – | Many asset ids for a bulk review (max 200). Mutually exclusive with `id` |
| reason | string | – | Why — stored as verdict_reason, useful when reviewing a rejection later |
| reference_type | string | yes | What kind of asset these ids refer to |
| selected | boolean | – | Mark as the chosen variant |
| verdict | string | – | Acceptance verdict. Feeds the acceptance telemetry (which provider/mode/price actually produced usable shots) |
No output schema declared.
No examples provided.
lab_review_queue 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`.
| Name | Type | Req | Description |
|---|---|---|---|
| cursor | string | – | ACROSS PROJECTS. The next_cursor of the previous page. Opaque — do not build one by hand |
| include_rejected | boolean | – | PER PROJECT ONLY. Include rejected in the default listing |
| limit | integer | – | Max rows (per project default 50). Across projects the page is capped at 20 so next_cursor stays exact |
| preview | boolean | – | 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_id | string | – | Project id (from lab_list_projects). Omit to search across all projects |
| scene_ref | string | – | PER PROJECT ONLY. Only this scene |
| selected_only | boolean | – | PER PROJECT ONLY. Only the chosen variants |
| since | string | – | ACROSS PROJECTS. created_at >= this ISO-8601 timestamp (e.g. 2026-08-03T00:00:00Z) |
| tool_used | string | – | ACROSS PROJECTS. Exact tool/provider name, e.g. seedance-2.5 |
| type | string | – | Which generated rows. Required per project; across projects, omit for both |
| until | string | – | ACROSS PROJECTS. created_at <= this ISO-8601 timestamp |
| verdict | string | – | PER PROJECT ONLY. Exact verdict filter. Omit to get everything except rejected |
No output schema declared.
No examples provided.
lab_run_module Run Pipeline 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.
| Name | Type | Req | Description |
|---|---|---|---|
| message | string | yes | Your instruction/prompt for this module (the user turn in the module chat) |
| module | string | yes | Pipeline module/stage key, e.g. mod_concept, mod_storyboard, mod_shotlist, mod_script |
| project_id | string | yes | Project id (from lab_list_projects) |
No output schema declared.
No examples provided.
lab_run_proposal 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.
| Name | Type | Req | Description |
|---|---|---|---|
| ohne_keyframe | boolean | – | 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_override | string | – | 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_id | string | yes | The 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 Measure a Clip (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.
| Name | Type | Req | Description |
|---|---|---|---|
| clip_id | string | – | Clip to measure |
| seq_id | string | yes | Sequence id — positive integer as string |
| zeit_s | number | – | Timeline position in seconds (picks the clip there; within a clip_id: the frame) |
No output schema declared.
No examples provided.
lab_search_catalog Search Knowledge 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.
| Name | Type | Req | Description |
|---|---|---|---|
| q | string | yes | Search query, min 2 characters |
No output schema declared.
No examples provided.
lab_sfx Generate Sound ~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.
| Name | Type | Req | Description |
|---|---|---|---|
| art | string | yes | Kind 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_id | string | – | 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_url | string | – | 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_seconds | number | – | 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_cost | boolean | – | `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_id | string | yes | Project id (from lab_list_projects) — positive integer as string |
| prompt | string | – | 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_ref | string | – | Optional scene label, stored on the row. Useful to tell several tracks of one project apart |
| stems | array | – | 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_id | string | – | 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 Read Shot Layer ~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.
| Name | Type | Req | Description |
|---|---|---|---|
| rung | string | – | 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_id | string | yes | Sequence id (from lab_create_sequence/lab_list_sequences) — positive integer as string |
No output schema declared.
No examples provided.
lab_shots_ableiten Derive Shots From Scenes ~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.
| Name | Type | Req | Description |
|---|---|---|---|
| seq_id | string | yes | Sequence id (from lab_create_sequence/lab_list_sequences) — positive integer as string |
No output schema declared.
No examples provided.
lab_shots_setzen Set Shot Cut ~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.
| Name | Type | Req | Description |
|---|---|---|---|
| rung | string | – | 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_id | string | yes | Sequence id (from lab_create_sequence/lab_list_sequences) — positive integer as string |
| shots | array | yes | The whole level, in order. The order here IS the order of the shots |
No output schema declared.
No examples provided.
lab_start_export 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).
| Name | Type | Req | Description |
|---|---|---|---|
| derivative_region | string | – | 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. |
| derivatives | array | – | 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_stems | boolean | – | Also export audio stems separately (default false) |
| kennzeichnung_umfang | string | – | 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_kennzeichnung | string | – | 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 '… |
| profile | string | – | 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_id | string | yes | Project id (from lab_list_projects) |
| quality | string | – | Quality preset (default 'standard') |
| sequence_id | string | yes | Sequence id to render (positive integer as string, e.g. '27') |
| werk_kuenstlerisch | boolean | – | 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 Suggest Clip 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.
| Name | Type | Req | Description |
|---|---|---|---|
| anzahl | integer | – | 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_id | string | yes | Sequence id (from lab_create_sequence/lab_list_sequences) — positive integer as string |
No output schema declared.
No examples provided.
lab_timeline_apply Apply Timeline Manifest ~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).
| Name | Type | Req | Description |
|---|---|---|---|
| erwartete_revision | string | – | 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… |
| manifest | object | – | The cut as one object. Omit it only together with a `sequence_id`, to read back what is stored |
| project_id | string | yes | Project id (from lab_list_projects) — positive integer as string |
| sequence_id | string | – | 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 |
| title | string | – | Title for the sequence created when `sequence_id` is omitted |
No output schema declared.
No examples provided.
lab_ton_durchlauf Sound Pass per Shot ~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.
| Name | Type | Req | Description |
|---|---|---|---|
| get_cost | boolean | – | 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. |
| hinweis | string | – | 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_id | string | yes | Sequence id (from lab_create_sequence/lab_list_sequences) — positive integer as string |
No output schema declared.
No examples provided.
lab_transform Transform Clip ~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.
| Name | Type | Req | Description |
|---|---|---|---|
| alpha_mode | string | – | 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_id | string | – | 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_cost | boolean | – | `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_sec | number | – | 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_sec | number | – | End of the excerpt, in seconds. Must lie behind in_sec; both are set together or neither. |
| resolution | string | – | 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_prompt | string | yes | What 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_id | string | yes | Generated-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 Upscale Clip ~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.
| Name | Type | Req | Description |
|---|---|---|---|
| faktor | string | – | 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_cost | boolean | – | `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_credits | integer | – | 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_id | string | yes | Generated-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.
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.