Spellzi speaks the Model Context Protocol. Any agent that speaks it too can open your films, rewrite scenes, lock the cast, swap references and roll camera, without you touching the editor.
Keys are issued in Settings → MCP access. A key spends nothing until you give it a budget.
Create a film from one line, read every scene, edit dialogue, insert, move and delete beats, restore any earlier version.
Add characters, lock their angles, upload or generate reference images, fill the reference slots each scene will shoot from.
Quote the price, start a scene, poll its status, then verify the footage says the dialogue it was given.
Every client needs two things: the server URL and your key as a bearer header. Copy the block, paste your key, done.
One command in the terminal. Works in Claude Code CLI and the desktop app’s Code tab.
claude mcp add --transport http spellzi https://spellzi.com/mcp \ --header "Authorization: Bearer YOUR_KEY"
Add to claude_desktop_config.json. The mcp-remote bridge carries the key header for you.
{
"mcpServers": {
"spellzi": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://spellzi.com/mcp",
"--header", "Authorization: Bearer YOUR_KEY"]
}
}
}
Add to ~/.cursor/mcp.json or the project’s .cursor/mcp.json.
{
"mcpServers": {
"spellzi": {
"url": "https://spellzi.com/mcp",
"headers": { "Authorization": "Bearer YOUR_KEY" }
}
}
}
Add to .vscode/mcp.json. Copilot agent mode picks the tools up on the next chat.
{
"servers": {
"spellzi": {
"type": "http",
"url": "https://spellzi.com/mcp",
"headers": { "Authorization": "Bearer YOUR_KEY" }
}
}
}
Add to ~/.codex/config.toml and export the key in your shell.
# ~/.codex/config.toml [mcp_servers.spellzi] url = "https://spellzi.com/mcp" bearer_token_env_var = "SPELLZI_MCP_KEY" # shell export SPELLZI_MCP_KEY="YOUR_KEY"
Add to ~/.gemini/settings.json.
{
"mcpServers": {
"spellzi": {
"httpUrl": "https://spellzi.com/mcp",
"headers": { "Authorization": "Bearer YOUR_KEY" }
}
}
}
Settings → Connectors → Create. Paste the server URL, pick API-key authentication and paste your key. Then enable the Spellzi connector in a chat and just talk.
# ChatGPT → Settings → Connectors → Create Name: Spellzi MCP server URL: https://spellzi.com/mcp Authentication: API key Key: YOUR_KEY
Streamable HTTP transport, POST only, stateless. Send the key as Authorization: Bearer or X-Api-Key. No SSE stream, no session id, no OAuth needed.
curl -sS -X POST https://spellzi.com/mcp \ -H "Authorization: Bearer YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
A fresh key edits everything and spends nothing. Every shoot goes through a quote first.
A total budget and a per-day budget, both in credits, both editable any time in Settings.
Revoking a key cuts the agent off instantly. Every call is audited with its tool, arguments and cost.
The endpoint trusts only the key. A page in your browser can never act as your agent.
This list is rendered from the same registry the server hands to tools/list, so it is never out of date.
list_filmsList the film projects on this account, newest first. Start here when you do not already have a storyboard_id.
check_stagingStaging ledger of a film: per-scene staging line (screen axis, who is where) and deterministic continuity issues between neighbouring scenes (exit/enter mismatch, axis flip, cast missing from staging, prop vanished, speech in a silent film). Read-only; pass write:true to write missing or stale staging records now (free of charge).
check_dialogueAfter a shoot: transcribe the rendered clip of one scene and compare it with the scene's scripted lines — ok / partial / missing per line, plus extra speech the engine invented. Costs a transcription, never a shoot.
film_statusOverview of one film: scene counts, what is drawn/animated, which scenes failed and why, and the real export status. Ask for include:["settings"] to get voice language, target duration, style and aspect ratio — you need those before writing any dialogue. include:["snapshots"] lists restore points.
read_scenesRead scenes. detail:"brief" (default) returns one compact row per scene — uid, dialogue, speakers, statuses, a short prompt preview — and is the right way to survey a whole film; the preview is a preview, read the scene itself for its text. detail:"full" addresses a single scene and returns its prompts WHOLE. A prompt is only ever split when the two of them together will not fit one reply, which happens on very long scenes and sooner in Russian, where a character costs two bytes. Nothing is dropped when that happens: the reply carries video_prompt_next_offset (and image_prompt_next_offset), and passing it back as video_prompt_offset returns the next part. Keep going until the next_offset is absent — that is the end of the text. Each field is guaranteed half the room, so both always advance. video_prompt_full_len is the true length in characters, so you can tell at a glance how much is still to come. Never write a prompt back from a reply where video_prompt_partial (or image_prompt_partial) is true: you are holding a piece of the text, and writing it back would replace the whole with that piece. That flag is on every piece of a split read including the LAST one, which is the piece an agent that walked to the end is most likely to think is safe.
list_referencesSearch the account reference library — the shared pool of character, location, prop and style images used across every film. It is large, so filter by asset_type and/or q rather than paging through it.
read_scene_referencesWhat is currently attached to a scene, and whether its references are merged into a single labelled sheet. Pass `scene` for one, or `scenes` for many at once — auditing a whole film one scene per call is dozens of round trips and nobody follows the answer to the end.
read_charactersRead the cast: names, descriptions, appearance prompts, voices, whether a reference image is attached, and which scenes each character appears in. detail:"full" returns the complete appearance prompt for one character. Every row carries a uid; use it to address edits.
film_historyRecent recorded events for a film — edits, generations, assemblies — as a plain timeline. Use it to check what actually happened rather than what was reported, and to find the moment before a destructive change.
image_resultAsk whether a generate_image job has finished. Free. While it is drawing it says so; when it is ready it puts the image into the reference library (the same de-dup as create_reference, so polling twice does not make a twin) and returns the library id and URL, ready to attach to a scene, a board slot or a character. If it failed it says why and reminds you the credits were already spent.
list_restore_pointsThe restore points this film has, newest first. Every batch write takes one, and its id comes back as snapshot_id — this is how you actually use that id. Each row says when it was taken, by what, how many scenes it holds and how many of them were already shot and paid for. Only the last 40 are kept, so a long run of single-scene calls can push out the point you wanted; the reply says when the film is at that limit. Free, reads nothing but history.
insert_scenesAdd MANY scenes in one write. Same shape as insert_scene, but `scenes` is the whole list in the order you want them, and they all land consecutively after `after`. Use this whenever you are loading more than two scenes: one call is one restore point and one concurrency check, where a loop of insert_scene leaves a snapshot per scene and a window after each one where somebody else can write into a film that is only half loaded. At most 50 per call. Returns every new uid in order. Costs nothing: the scenes arrive empty and have to be shot separately.
generation_statusPer-scene progress: what is drawn, what is shot, what failed. Also reports `preflight` for films that use one — "none" means the shoot is not gated and you can start it, "fresh" means nothing to do, "stale_paid" means refresh_scene_references is needed and WILL charge, "stale_empty" means the refresh only clears a dead marker and is free, "running" means a harvest is already in flight and refreshing would pay for a second one. Read this BEFORE refreshing a batch: it costs nothing and tells you which scenes actually need paying for.
quote_generationWhat would it cost to shoot this, IN CREDITS. Prices the scenes without starting anything and without spending a credit. Use it BEFORE proposing a shoot and show the person the number, together with the share of their balance it takes — that is the part they actually feel. Never convert credits to money when talking to a person: a credit has no single price, and credits are the unit this product bills in. Defaults to the WHOLE film: the totals always cover every scene you asked about. On a long film only the per-scene rows are paged (row_offset / next_row_offset) — never add pages together, the total is already whole.
read_reference_boardThe References step of one film: the cards already on the board, and the empty slots that were proposed for it. This is a DIFFERENT store from list_references — that one is the account-wide library, this one is what this film shows on its References step. Read it before touching a slot: slots carry no id and are addressed by their exact name and prompt.
create_filmCreate a new blank StoryChat film project — the MCP equivalent of starting “New film”. This creates one editable empty scene and never calls an AI model or spends credits. Use edit_scene/insert_scene and the cast/reference tools to build it, then explicitly quote and start generation when ready.
create_next_episodeDo exactly what “🎬 Shoot next episode” does after assembly: create a new blank StoryChat project carrying the cast, character identity images, project references, production settings, and the previous final video. Scenes are intentionally not copied. The source film must be fully assembled; this call itself never generates media or spends credits.
edit_sceneChange one scene. Text and data only — this never starts a generation and never spends credits. Returns exactly which fields were verified as written. When you change dialogue, the reply includes a runtime check so you can see whether the lines actually fit the scene length.
edit_scenesApply many scene patches in one call, under a single restore point. Use this instead of looping edit_scene: it is one snapshot and one result table rather than N round trips. Max 50 edits.
set_project_settingsChange project-level settings that govern how scenes are written, voiced and shot. Data only, no generation — but changing the engine changes what a later shoot costs, so say which engine you are moving to before you move to it. film_status include:["settings"] reports the current engine and its clip ceiling.
attach_scene_referencesAttach library references to scenes. mode:"replace" (default) sets the exact list — an empty list detaches everything; "add" appends; "remove" takes the named ids off and leaves the rest of that scene alone. Pass `scene` for one, or `scenes` to apply the same change to many under a single restore point. Reports how many of the ids you asked for actually landed and which were rejected, and fails loudly if none of them belong to this account rather than reporting a success that did not happen.
set_scene_reference_videosAttach VIDEO references to one scene the way the Video step picker does (Seedance 2/2.5 only: the clips go to the engine as reference videos, "Video 2..N" after any continuation clip). This is separate from the image library: create_reference with an mp4 url is rejected by the engine as an invalid image. Each item is either {url, name?, duration?} — an absolute http(s) mp4 — or {scene} — the address of ANOTHER scene of this film whose shot clip becomes the reference (name and duration are filled in). mode:"replace" (default) sets the exact list, [] detaches all; "add" appends; "remove" drops the items whose url matches. Per-clip 2–15 s; the tier caps the count and the total seconds (2.5: 10 clips / 30 s; others: 3 / 15 s). Say in the video_prompt what the clip is for — the engine treats it as a motion/content anchor, not a shot to copy.
upload_referenceUpload a LOCAL image through this MCP server to both storage clouds and the account reference library. Returns reference_id and image_url, ready for edit_character or scene references. PNG/JPEG/WebP, up to 8 MiB. No AI generation or credits. Identical bytes on this account reuse the same entry, even on retry. IMPORTANT: read the local file and base64-encode it PROGRAMMATICALLY in a script, then POST tools/call to the same /mcp with the existing key. Never print or transcribe base64 through the model context. The bundled client is tools/storyboard-mcp/upload_reference.py. A local file path alone is not data. Uploading does not attach the image to a character until edit_character is called.
create_referenceAdd an image to the account reference library from a URL, so it can then be attached to scenes. Re-using a URL that is already in the library returns the existing entry instead of creating a twin.
add_characterAppend one new cast member and optionally attach them to scenes. This is data only: it creates the card, returns its stable uid, updates the selected scene casts and face-anchor overrides, and never draws a portrait or spends credits. Scene addresses must come from read_scenes. Exact duplicate names are refused instead of silently creating twins.
edit_characterChange one cast member: name, description, appearance prompt, voice, or the reference image. Data only — this never starts a portrait generation and never spends credits. Attaching image_url replaces the full-body reference the engines anchor on; the previous one is kept in history. This tool edits one card in place; use add_character to append a new card.
remove_characterRemove one cast member and atomically reindex every scene that points at the cast. Prefer a character uid; a name must be unique, and a positional index is accepted only with the fingerprint returned by read_characters. If the card contains a generated reference, portrait or turnaround, the first call only describes the work that would be discarded. Show that to the person and wait for permission, then call again with confirm:true. A restore point is always created before deletion. Costs no credits.
edit_charactersApply many cast patches in one call, under a single restore point. Use this to attach a set of approved portraits, or to fill in appearance prompts for the whole cast at once. Max 50 edits.
ask_grok_4_6 can spend creditsSend a standalone text task to the server-side Grok 4.6 API. This is for reasoning, writing and critique before or alongside film editing; it does not read or modify a film unless you put that information in the prompt. THIS SPENDS CREDITS. The first call only returns a conservative estimate and changes nothing. Show the estimate in credits and wait for the person, then repeat with confirm:true and the same expected_cost and op_id. The final charge uses the exact provider-reported xAI cost when available, not the estimate. The answer is capped at 38 KB so it fits in one MCP result.
compose_scene_prompts can spend creditsWrite the video prompts with the product's own composer — the same step the app runs when a person asks for a film, which is why scenes made in the app already carry prompts and scenes built through these tools do not. THIS CHARGES: prompts are billed at cost from the tokens the model actually uses, and the model matters enormously — about 66 credits per scene on Flash 3 against 652 on GPT-5.6 Sol, so a 40-scene film is 2600 or 26000 depending on that one choice. The first call quotes and changes nothing. Asynchronous, about half a minute per scene, so it returns immediately — poll generation_status, where a scene being written shows composing:true. Defaults to the whole film. Two things to know before calling it. It PINS the engine: each composed scene gets video_provider seedance2 (or kling_official if the project uses it) and reference mode on, so this is not a text-only edit. And it SKIPS scenes whose prompt is locked — writing a prompt through edit_scene locks it by default; clear those with unlock_scene_prompts first, or pass force to overwrite a hand-written prompt deliberately. The composer is also the only thing that attaches the NON-NEGOTIABLE SCENE CONTRACT, so a scene it never touches ships without its cast manifest. If the film has no composer model chosen yet, the first call queues NOTHING and returns the list of available models instead — ask the person which they want, then call again with model. The answer is stored on the film, so the question comes once. The list carries the price per scene and for this whole film, because that is the part of the choice that costs money.
generate_image can spend creditsDraw a NEW image from a prompt, optionally guided by reference images, and put the result in the account reference library. THIS SPENDS CREDITS, and the price is fixed and known before the call, so the first call always answers with the number and changes nothing — show the person that number IN CREDITS and wait, then call again with confirm and expected_cost. Prices come from the code that actually charges: Nano Banana Pro 500 at any resolution, GPT Image 2 300 at 1K / 500 at 2K / 800 at 4K, Grok Image 2 350, Nano Banana 100. Reference limits differ per provider and are enforced rather than truncated: Grok takes ONE image, Nano Banana three, GPT Image 2 four, Nano Banana Pro fourteen. Generation is asynchronous — this returns a picture_id and you poll image_result, which is free.
set_character_anglesAttach or detach EXTRA VIEWS of one character — the "More views" row on the card. Attaching an existing image is data only: no generation, no charge. At most 6 per character. Detaching asks first when a view was generated, because that one was paid for. WHAT THE ENGINE ACTUALLY READS, in this order. The anchor is the first of turnaround sheet, full-body image, portrait that is ready — and if NEITHER the full-body image NOR the portrait is ready, the character is left out of the shot entirely, which extra views cannot rescue. Extra views are sent only on Seedance 2.5: portrait first, then these, capped at seven references per character in total. Identity and Angles sheets are shown in the app but no part of generation reads them, so attaching one changes nothing in the shot.
restore_filmRoll the film back to a restore point from list_restore_points. Two steps, deliberately: called without confirm it changes NOTHING and answers with what would be lost — scenes that are already shot and paid for are named individually, each with a fingerprint that identifies WHICH clip — not just which position, because a re-shoot can replace the clip at a position while you are asking. Show the person that list and wait. The confirmation carries lost_digest, which pins those exact clips, so a film that changed underneath you refuses instead of destroying something you never displayed. The state before the rollback is itself captured, so a rollback is undoable.
unlock_scene_promptsHand scenes back to the multishot composer. Writing a video_prompt locks the scene so the composer will not overwrite it — but the composer is also the ONLY thing that attaches the NON-NEGOTIABLE SCENE CONTRACT, so a locked scene ships with no cast manifest (who is in shot, who must NOT be drawn), no world anchor and no state events. That is how a character who is dead in the story walks into a later scene. Unlocking rewrites nothing and costs nothing; it only lets the next compose pass rebuild the prompt with its contract. Defaults to every scene of the film, which is the usual case after loading a script through these tools.
refresh_scene_referencesRebuild the reference preflight for one scene. A scene on Seedance 2.5 or MiniMax H3 harvests references from neighbouring scenes, and that harvest goes stale whenever the scene or its neighbours move or change — including after move_scene. While it is stale the shoot refuses. This is the same action as the magic reference button in the app. It CHARGES, and not a little: it runs several vision passes — measured on this product, around 340 credits for a typical scene and over 630 for one scene in ten, with no hard cap. The reply reports the exact amount. Tell the person the number in CREDITS before spending it on a batch of scenes. Refresh ONE scene and shoot it straight away: every clip that lands re-stales every later scene, so refreshing several up front pays for work that is thrown away. The shoot itself is quoted and charged separately.
set_scene_castWho appears in a scene. Address people by uid or name — never by position: the field is stored positionally, so indices held from an earlier read point at someone else after any cast change. Pass `scene` for one, or `scenes` for many under a single restore point. Setting the cast also realigns that scene's face anchors, so the shot follows the list. An empty cast means exactly that — no character anchors, the narrator or establishing shot case. Changes no pictures and spends nothing.
insert_sceneAdd a scene to a film. Say where with `after`: the uid of the scene it should follow, or "start" for the top. Never a position — you read the film some time ago, and a position that moved since would put the scene somewhere else. Returns the new scene's uid, which is how you address it afterwards. Every scene below it shifts by one, so any position you were holding is now stale; the References-step slots and the dialogue register follow the scenes on their own. Costs nothing: the scene arrives empty and has to be shot separately.
delete_sceneRemove a scene. If it already has a frame or a clip, the call comes back asking for confirmation instead of deleting: that is work somebody paid for. Show the person what would be thrown away, wait for their answer, then call again with confirm:true. A restore point is taken either way, so the film can be rolled back.
move_scenePut a scene somewhere else in the film. `after` is the uid of the scene it should follow, or "start" for the top. Nothing is lost and nothing is paid for again — the clip and the frame travel with the scene.
start_scene_generation can spend creditsShoot one scene: draw its frame, or animate it. THIS SPENDS CREDITS — it is the only tool here that does. Call it once without confirm to get the price, show the person that number IN CREDITS (never converted to money) together with the share of their balance, and wait for their answer. Only then call again with confirm:true and expected_cost set to the figure you were quoted; if the price moved in between, the call is refused rather than run at the new one. A key can only spend up to the budget its owner set in Settings, MCP access — with no budget the tool refuses and tells you so. Asking twice for the same scene inside ten minutes is refused as a duplicate, so poll generation_status instead of retrying.
fill_reference_slotFill one proposed slot with a picture that already exists, by URL. Puts the card on the board, files it in the account library, binds it to every scene the slot names, and clears the slot — the whole transition in one call. Nothing is drawn, so nothing is charged. Copy name and prompt from read_reference_board unchanged; a paraphrase is refused, not guessed at.
add_board_referencePut a picture on the References board when no slot proposed it — the same append as fill_reference_slot, minus the slot. Use scene_indices to bind it to scenes in the same call. Nothing is drawn, so nothing is charged.
propose_reference_slotAdd an empty slot to the References board — a named thing this film still needs a picture of. Costs nothing and draws nothing; a person or a later call fills it.
drop_reference_slotRemove one proposed slot from the References board. Use it when the thing was decided against, or when it was satisfied some other way and the empty card is now just noise.
update_board_referenceRename, re-describe, re-type, re-purpose or repoint one card on the References board. Changing new_url also repoints the library row the scenes are bound to, so the new picture reaches the engines instead of only the card.
remove_board_referenceTake one card off the References board and unbind it from every scene — both the ids the video engines read and the assets the frame engine reads. The library copy is kept, so the picture can be used again elsewhere.
merge_reference_sheetGlue several library references into ONE labelled angles sheet, saved back to the library as a reusable reference. Useful when a scene needs more anchors than an engine accepts pictures: a sheet costs one slot. Passing an existing sheet expands it into its own tiles rather than nesting it.