Shorz MCP Server Agent Skill
Before any Shorz MCP tool call, confirm Shorz is running and the MCP server is connected. For panel-level or project-type-specific work, load the matching reference file from references/ (paths in the tables below) before changing settings or triggering renders.
This skill is the entry point (SKILL.md). Detailed workflows live under references/panel-workflows/ (cross-project panels), references/project-workflows/ (per-projectType end-to-end flows), references/headless-workflows/ (project-independent file operations), and references/creative-strategy/ (viral formats, hooks, and content brainstorming). The routing tables tell you which file to open.
Operating Model
- Treat Shorz as a stateful desktop runtime. Always read current state before writes.
- Most menu/panel option changes map to
read_project_settings + update_project_settings (targeted deep-merge patches).
- Generation and long-running workflows are asynchronous. For project video creation, poll
get_video_generation_status as the default way to know running vs done vs error. Use fetch_app_events only if the user asks for live logs/progress, or when you are diagnosing a failed or stuck render (see Event stream).
- Prefer deterministic/headless arguments (override paths) over dialog-driven behavior.
- Live UI vs MCP write races — when the Shorz Electron app has the target project open, certain fields (notably
UI_SETTINGS.user_input_instructions / PromptBar) can be reactively rewritten by the renderer shortly after an MCP write, because the input box owns its own in-memory state. If a configure-only patch on PromptBar appears to "revert," it is the live UI overwriting disk. Workarounds: write again after a moment, ask the user to close the project, or accept the renderer's value as the new truth. This is not a tool failure — the set_user_instructions write itself succeeded.
Workflow routing
Pick the matching workflow file before editing a project or panel. Don't improvise — the per-file skills lock in tool names, enums, persistence keys, and known clamps/rejects.
Guided creation (wizard) — vague idea, no concrete inputs
When the user expresses intent to make a video or asset without the concrete inputs it needs (no file path/URL, no format, no counts, no script — e.g. "i want to clip a youtube video", "make me an avatar video", "I need a thumbnail", "an animated intro"), do NOT improvise questions and do NOT start configuring. Open references/guided-creation/README.md first (trigger rules, question protocol, the 11 design rules, summary + confirmation contract), then run the matching flow:
| Intent sounds like |
Guided flow file |
| clip/cut a long video into shorts |
references/guided-creation/clipping.md |
| edit my own footage/photos into one video |
references/guided-creation/auto-edit.md |
| make a video about X / from a script / faceless |
references/guided-creation/text-to-video.md |
| talking head / AI presenter |
references/guided-creation/avatar.md |
| two-person dialogue / AI podcast |
references/guided-creation/podcast.md |
| ad / promo for my product |
references/guided-creation/advertisement.md |
| thumbnail / cover image |
references/guided-creation/thumbnail-creator.md |
| animated intro, logo reveal, kinetic text, title card |
references/guided-creation/animation-studio.md |
Each flow asks a short option-driven sequence (interactive question tool when available; ≤4 preset options, recommended default first, custom input always possible, never re-asking anything already given), ends with a readable summary + an explicit confirmation, and only then executes via the matching references/project-workflows/*.md or panel workflow. If the user already gave a complete spec, skip the wizard and confirm the gaps in one question.
Project workflows (one per projectType)
projectType |
Workflow file |
Primary MCP tools |
auto-edit |
references/project-workflows/auto-edit.md |
Panel set_*_settings (subtitle, title, border, audio, overlay, broll, general video) + switch_project_aspect_ratio |
text-to-video |
references/project-workflows/text-to-video.md |
set_text_to_video_settings, save_text_to_video_speech_audio, save_text_to_video_reference_images |
avatar |
references/project-workflows/avatar.md |
set_avatar_settings, select_avatar_image, select_avatar_angle_image, select_avatar_audio, save_avatar_image, save_avatar_audio |
podcast |
references/project-workflows/podcast.md |
set_podcast_settings, select_podcast_avatar_image, list_elevenlabs_voices |
advertisement |
references/project-workflows/advertisement.md |
set_advertisement_settings, select_advertisement_image, remove_advertisement_image |
clipping |
references/project-workflows/clipping.md |
update_project_settings (CLIPING, ASSET_PATHS), download_social_video, switch_project_aspect_ratio |
Headless workflows (no project, no projectType)
These MCP tools work on local files only. They do not use projects, settings.json, PromptBar, Create Video, or any projectType. Do not call create_project or read_project_settings before using them.
| Workflow |
File |
Primary MCP tools |
| Single-file deterministic edits |
references/headless-workflows/single-asset-edit.md |
trim_video, crop_media, change_video_speed, remove_audio, set_audio_volume, rotate_media, flip_media, reverse_video, loop_video, fade_video, freeze_frame, set_image_duration, audio_fade, remove_silence, edit_image_with_ai, get_media_info, resize_media, fit_to_aspect, extract_audio, replace_audio, concat_media, extract_video_frames |
| Pexels stock media search |
references/headless-workflows/pexels-stock-media.md |
pexels_search_photos, pexels_search_videos, pexels_curated_photos, pexels_popular_videos, pexels_get_photo, pexels_get_video |
| X (Twitter) live search |
references/headless-workflows/x-search.md |
x_search (natural-language X search with citations; spends Shorz credits) |
| Free Nano Banana 2 images (own Google key) |
references/headless-workflows/nano-banana-free-images.md |
generate_images_nano_banana_free (no Shorz credits — runs on the user's Google AI Studio free-tier quota) |
See references/headless-workflows/README.md for when to use headless edits vs a full project workflow. To put an edited file into a project afterward, that is a separate import step (import_frontend_assets, save_file_as, or project-specific path patches).
Companion skills
| Skill |
Use it for |
shorz-ui-automation |
Driving the app through its actual UI with a real, visible cursor — tutorial footage, feature demos, screenshots for the website or docs, onboarding walkthroughs. It owns the get_ui_map → ui_click → get_ui_map loop and the six UI tools (get_ui_map, scroll_ui_element_into_view, ui_click, ui_type, ui_press_keys, ui_scroll), which are not covered anywhere else in this skill. Load it whenever the deliverable is a visual of the UI. For changing a setting or rendering without filming it, stay here — the tools in this skill are faster and need no UI. |
shorz-motion-graphics |
Generating a green-screen motion graphics overlay and chroma-keying it onto an existing video, any length, in 16:9 / 9:16 / 1:1. Covers every style — explainer graphics, infographics and data callouts, kinetic typography, broadcast lower-thirds, annotation arrows, chapter cards, and high-energy short-form. Load it instead of improvising from the Animation Studio panel workflow whenever the goal is graphics on top of existing footage — it carries the source-analysis, safe-zone, segmentation, chroma-key and compositing rules that panel reference does not. |
Creative and strategy workflows
| Strategy area |
Workflow file |
Primary purpose |
| Content brainstorming & viral playbooks |
references/creative-strategy/content-brainstorming.md |
Designing high-retention hooks, formats, and CTAs mapped to Shorz tools |
Open references/creative-strategy/content-brainstorming.md when the user asks for content ideas, viral formats, organic growth playbooks, or hook/CTA variants — then switch to the matching references/project-workflows/*.md (or headless workflow) to execute.
Panel workflows (cross-project; usable on matching sidebar panels)
| Sidebar panel |
Workflow file |
Primary MCP tool |
| General Video / Auto Zoom |
references/panel-workflows/settings.md |
set_general_video_settings |
| B-roll (Assets / Web / GIF / AI / Emoji) |
references/panel-workflows/broll.md |
set_broll_settings |
| Audio (mix, dubbing, reverb, visualization) |
references/panel-workflows/audio.md |
set_audio_settings + set_audio_visualization_settings |
| Overlay |
references/panel-workflows/overlay.md |
set_overlay_settings + get_overlay_effects lifecycle |
| Border |
references/panel-workflows/border.md |
set_border_settings |
| Text → captions / subtitles |
references/panel-workflows/subtitle.md |
set_subtitle_settings |
| Text → headline / banner |
references/panel-workflows/title.md |
set_title_settings |
| Thumbnail Creator (modal) |
references/panel-workflows/thumbnail-creator.md |
open_thumbnail_creator, set_thumbnail_creator_settings, thumbnail_creator_generate, get_thumbnail_creator_generation_status |
| Animation Studio (modal) |
references/panel-workflows/animation-studio.md |
animation_studio_*, compile_remotion_preview, remotion_render |
| Your Library (VIDEO / BROLL / SOUND / MUSIC) |
references/panel-workflows/your-library-assets.md |
update_project_settings (ASSET_PATHS); delete_asset only when deleting files on disk |
The Text sidebar shows subtitles and titles together but uses two tools with two key families (subtitle* vs title*). Never send subtitle keys to set_title_settings or vice versa — for both kinds, call each tool once with a minimal patch.
Main VIDEO import (“Import Main Assets”) vs project type
In the Electron app, import_frontend_assets with assetType: "video" mirrors the UI Import Main Assets lane (fills the main timeline / assets.VIDEOS, which persists to ASSET_PATHS.main_video_asset_paths on save alongside other library categories). The single source of truth is isMainAssetsLaneEnabled (frontend/src/utils/mediaAssetUtils.ts): the main VIDEOS lane is disabled for podcast, avatar, advertisement, and for text-to-video unless textToVideoSourceMedia === "imported". That rule gates the UI (import button, Your Library → VIDEOS tab, timeline strip) and is enforced main-process-side: a headless import_frontend_assets call with overridePaths and assetType: "video" into a lane-disabled open project is rejected with an error (redirecting to "broll") instead of persisting main_video_asset_paths. Match this in guidance: never tell users they can “add main timeline videos” in templates that hide or disable main-video import.
projectType |
Main VIDEO import in UI (timeline / PromptBar gateway) |
Your Library shows VIDEOS tab |
auto-edit |
Yes |
Yes |
clipping |
Yes (typically one long source patched to ASSET_PATHS.main_video_asset_paths) |
Yes |
text-to-video |
Only when Source Media is imported |
Only then |
avatar |
No (canImportMainAssets false) |
No |
podcast |
No (canImportMainAssets false) |
No |
advertisement |
No (main lane disabled) — workflow is reference stills, not a main VIDEO lane — use select_advertisement_image / import_frontend_assets with image |
No (tab hidden) |
Agents: Use avatar, podcast, advertisement, text-to-video (unless imported) workflows for their typed inputs (still images, avatars, product/person images, script/audio, generated sources). import_frontend_assets with video into these projects is rejected with an error (headless overridePaths path) — import supporting footage as broll, which every project type keeps.
One asset per file name (every library lane)
A lane (VIDEO / BROLL / SOUND / MUSIC) holds at most one asset per file name — compared case-insensitively, folder ignored, and per lane (the same file may legitimately sit in both VIDEO and BROLL) — because the backend addresses assets by basename: PromptBar @mentions, the Python render maps, and music/SFX name lookups. The UI and MCP enforce the same rule: import_frontend_assets skips a file whose name the lane already holds and lists it in skipped (reason duplicate-name), and an update_project_settings patch of a lane collapses repeated names and reports duplicateAssetNamesDropped. Nothing errors and nothing is overwritten — so always check skippedCount before telling the user an import is done, especially after a paid generation. Need both files? Rename one. Full contract and result shapes: references/panel-workflows/your-library-assets.md → One asset per file name.
PromptBar semantics by project type
The PromptBar (set_user_instructions → UI_SETTINGS.user_input_instructions) does not mean the same thing for every project type. Source: frontend/src/data/projects.ts (projectTypePromptPlaceholderMap).
| Type |
PromptBar role |
Spoken/script content lives in |
auto-edit |
Primary creative brief (required for Create Video). Can also direct per-clip editing with no panel toggle: transitions between clips, camera motion, speed/volume/reverse/loop/flip/rotate, fill-the-frame framing, beat-synced cuts to imported music, and the imported-music bus itself (MUSIC lane holds any number of tracks, played back to back — the brief can reorder tracks, trim each one, and place/fade/mix the music) — full vocabulary in references/project-workflows/auto-edit.md → What the PromptBar can direct |
n/a |
text-to-video |
Optional look and mood guidance |
textToVideoScript (or saved speech audio in audio input mode) |
avatar |
Optional guidance for enabled auto-edit features (captions, B-roll, music, etc.) — not the spoken script. Can also arrange imported music (order, sections, placement, volume, fades, mix) |
avatarScript (script mode) or avatarAudioUrl (audio mode) |
podcast |
Optional B-roll / music / SFX guidance — not the dialogue. Can also arrange imported music (order, sections, placement, volume, fades, mix) |
podcastScript with [Interviewer] / [Interviewee] line tags |
advertisement |
Ad creative brief |
Product/person images via set_advertisement_settings |
clipping |
Optional — only when steering topics, clip length, platform, or hooks |
Source video at ASSET_PATHS.main_video_asset_paths |
Rule: Never overwrite PromptBar with a script for avatar, podcast, or text-to-video. Put the spoken text in the panel field listed above.
Referencing a specific asset: to point the brief at one file in the project library, write its filename in double quotes — use "intro.mp4" as the opener. That is exactly what the desktop app's @ picker and its drag-from-timeline shortcut insert, and the app renders any such reference as a pill. Get the real filenames from read_project_settings (ASSET_PATHS) or get_video_assets / get_audio_assets first — a name that isn't in the library is just prose to the analyzers.
Output framing (all project types): PromptBar / set_user_instructions text is never the place for export geometry. Do not include aspect-ratio tokens (9:16, 16:9, 1:1), pixel dimensions (1080×1920, 1920×1080, 1280×720), video_width / video_height, or output fps in the creative brief — the project already has VIDEO_SIZE from the UI or switch_project_aspect_ratio. Platform or delivery names for creative intent (TikTok, Reels, Shorts, “vertical short”) are fine; technical sizing belongs in the aspect tool, not PromptBar. When the user asks for a format change, call switch_project_aspect_ratio and strip sizing lines from any PromptBar text you persist.
PromptBar main AI model
The PromptBar model dropdown (all project types) selects which AIML chat model Create Video and backend LLM calls use. It is not the same as panel-specific models (textToVideoImageModel, thumbnail imageGenerator, etc.).
| MCP tool |
Persistence |
Allowed values |
set_main_ai_model |
AI_MODEL.main_ai_model_name |
Server-driven — call list_main_ai_models for the live lineup and pass an id from its response. At time of writing: anthropic/claude-opus-5 (Opus 5, default), anthropic/claude-fable-5 (Fable 5), anthropic/claude-sonnet-5 (Sonnet 5, re-enabled 2026-08-10 — 1 / 2 credits per 1k, the cheapest Claude), openai/gpt-5-6-terra (GPT 5.6 Terra), openai/gpt-5-6-sol (GPT 5.6 Sol, frontier tier), google/gemini-3.7-flash (Gemini 3.7 Flash, ~0.2 / 1 credits per 1k tokens — much cheaper than Opus 5; a normal paid-selectable model billed like any other, and the only id a free run zero-rates) — six models; treat that as a snapshot, not an allowlist. This model also drives image / video-frame asset analysis, including key-subject localization. On a free-tier run (auto-edit / clipping, zero-balance user) only google/gemini-3.7-flash is zero-rated — the in-app picker locks itself to it, but the MCP path does not, so you must set_main_ai_model (or pass mainAiModelName) with that id or the render bills and 402s |
- Read current model:
read_project_settings → AI_MODEL.main_ai_model_name.
- Before Create Video: When the user names Opus, Fable, GPT 5.6 Terra, GPT 5.6 Sol, Gemini 3.7 Flash, or a specific model id, call
set_main_ai_model before trigger_create_video / generate_video, or pass mainAiModelName on trigger_create_video for a one-shot run (persists to disk first, matching the UI dropdown at generate time).
- Live UI: Patches go through
update-project-settings; the open app reloads the dropdown from disk (unlike PromptBar text, the model selector rarely races with in-memory UI state).
Animation Studio chat model
The Animation Studio modal has its own model picker (labels like claude-opus-5). It does not read AI_MODEL.main_ai_model_name.
| MCP |
Role |
animation_studio_list_models |
Supported chat model ids for this build |
animation_studio_send_* optional model |
Per-call override; default anthropic/claude-opus-5 |
Allowed ids: server-driven — animation_studio_list_models returns the live lineup (same main_ai catalog category as the PromptBar picker; at time of writing six: Opus 5, Fable 5, Sonnet 5, GPT 5.6 Terra, GPT 5.6 Sol, Gemini 3.7 Flash). Call it and pass an id from the response rather than one from this page. anthropic/claude-opus-4-6, anthropic/claude-opus-4-7 and anthropic/claude-opus-4-8 are retired from the selector — use anthropic/claude-opus-5 instead. (anthropic/claude-sonnet-5 was retired by 0017 but re-enabled by 0033 on 2026-08-10 — it is selectable again.) (The proxy still resolves anthropic/claude-opus-4-8 via a disabled legacy-alias catalog row so older saved projects keep working, but do not pass it for new work.) Full workflow: references/panel-workflows/animation-studio.md → Model selection.
Project targeting rules (apply to every project workflow)
Skip this section for headless single-asset edit tools (trim_video, crop_media, etc.) — they only need inputPath and Shorz running. See references/headless-workflows/single-asset-edit.md.
- If the user names a project, resolve it with
list_projects and use it. If not found, follow rule 5.
- If the user says "current / open / this project", use
get_current_open_project.
- If the user gives no project identity, prefer
get_current_open_project; otherwise ask whether to use existing or create new. Never auto-pick when multiple candidates match.
- If the requested workflow conflicts with the current
projectType, do not silently repurpose — ask whether to continue in the current project or create/select a matching type.
- Create a new project only when the user explicitly asks, when a named target is missing and they approve creation, or when they ask for clean separation.
- Never run destructive project actions (
delete_project) without explicit confirmation. Same for delete_asset, delete_overlay_effect, remove_animation_studio_export, clear_animation_studio_exports.
Asset verification: project main media vs My Assets library
Two different things — agents mix them up. Pick the right one.
- Project main / timeline media (the path(s) synced from the main VIDEO lane — only workflows that expose main VIDEO import, see Main VIDEO import above — e.g.
auto-edit montage clips, clipping’s long source, text-to-video with imported source media): read read_project_settings → ASSET_PATHS.main_video_asset_paths, verify with file_exists. avatar / podcast templates do not use this lane in the shipped UI — do not treat main_video_asset_paths as required for Create Video there. advertisement center on ADVERTISEMENT.* image paths, not timeline video. There is no MCP tool that lists "the project's VIDEOS tab"; for clipping do not verify the source via get_video_assets.
- My Assets library tabs (cross-project inventory; AI-generated outputs, imports, downloads): use the per-tab
get_*_assets tools or filtered query_my_assets as described in references/panel-workflows/README.md → Library and cross-cutting MCP tools.
Removing imported project assets (Your Library)
When the user asks to remove, clear, or delete something from the project Your Library lanes (VIDEO, BROLL, SOUND, MUSIC), they usually mean drop it from the project, not erase the file from disk. Full tab mapping and steps: references/panel-workflows/your-library-assets.md.
| UI tab |
ASSET_PATHS field |
Clear entire lane |
| VIDEO (Import Main Assets) |
main_video_asset_paths |
update_project_settings → { ASSET_PATHS: { main_video_asset_paths: "" } } |
| BROLL |
broll_video_asset_paths |
… { broll_video_asset_paths: "" } |
| SOUND (sound effects) |
audio_fx_asset_paths |
… { audio_fx_asset_paths: "" } |
| MUSIC |
music_asset_paths |
… { music_asset_paths: "" } |
- Default tool:
update_project_settings on the matching field. Paths are comma-separated; to remove one file, read settings, split/filter/rejoin, then patch. Do not use delete_asset unless the user explicitly wants the file deleted from disk (destructive; confirm first).
- UI parity: In-app trash on a library card only updates project paths (same as clearing via MCP); it does not unlink the source file.
- Not the same as:
get_*_assets / My Assets modal inventory (use delete_asset there only when user wants the library file gone). Playback outputs (last_generated_final_video_for_playback_mode, playback_history_video_paths) stay until changed separately.
- VIDEO tab availability depends on
projectType — see Main VIDEO import above before clearing main video on avatar / podcast / etc.
Required Workflow Rules
Pre-flight: the app's requirements guard does NOT protect you
Since 2026-08-19 the desktop UI blocks Create Video and names what is missing when a
project cannot possibly render. That check lives in the PromptBar's submit handler
(frontend/src/utils/generationRequirements.ts) — trigger_create_video and
generate_video bypass it entirely. Over MCP you get the old behaviour: the render starts,
burns time, and fails (or silently returns the user's own file). Verify these yourself before
triggering a render:
| Project type |
Must be true before you trigger |
auto-edit |
≥1 file in the main VIDEOS lane and PromptBar instructions > 10 chars (below that the auto-editor is skipped and the source is re-exported untouched) |
clipping |
exactly one video in the main lane — zero or two+ both fail |
avatar |
avatar image set and (script > 10 chars or saved audio). Either input alone is enough; the mode toggle does not invalidate the other |
podcast |
script > 10 chars in [Interviewer]/[Interviewee] form and BOTH avatar images set |
text-to-video |
script ≥ 50 chars or saved speech audio; plus ≥1 imported main asset when textToVideoSourceMedia is imported |
advertisement |
at least one of product image / character image (either alone is fine) |
These mirror the renderer's own guards, so treat them as hard preconditions rather than
advice. Re-read a setting after writing it when the render depends on it (read_project_settings).
Project targeting first
- Prefer
get_current_open_project first (active UI project source of truth).
- If no active project is set, call
list_projects and ask user to choose existing vs approve creating new.
- Use absolute paths from
get_projects_path and returned project metadata.
Safe setting edits
- Call
read_project_settings when you need the full picture or before non-trivial decisions.
- Persist nested changes with
update_project_settings: pass only the updates object for keys/sections to change (objects merge recursively; scalars and arrays replace). Optional unsetPaths deletes keys by dot notation. The main process reads the file, merges, validates, and writes atomically—do not reintroduce a manual read→edit full blob→write loop for ordinary edits.
- For
set_*_settings tools, MCP now performs strict validation:
- unknown keys are rejected
- invalid enum/color values are rejected
- numeric values are range-validated; out-of-bounds values are rejected or clamped per tool (for example
set_border_settings clamps borderWidth to 1–100 and borderAnimationDuration to 1–5)
Asynchronous operations
- Video generation (
generate_video / Create Video) — Poll get_video_generation_status until lastStatus is terminal (completed, completed_no_output, error, stopped, etc.). That is the main tool for project renders.
fetch_app_events — Use sparingly: when the user explicitly wants the raw event/log stream, or when get_video_generation_status is unclear (stuck, unexpected state) and you need the IPC log lines to see what the UI would have seen. Not the default loop for “wait for video.”
- Social video downloads (
download_social_video) — async by default; poll get_social_video_download_status until lastStatus is completed or error. YouTube extraction alone regularly takes minutes, so the blocking awaitCompletion: true form is only safe for short clips.
- Social publishing (
social_publish) — async by default; the tool starts the job and returns immediately. Poll get_social_publish_status until lastStatus is terminal (completed | error); its result carries the same per-platform payload as the blocking form. Media upload alone routinely runs for minutes, so pass awaitCompletion: true only when the MCP client's tool-call timeout exceeds ~8 minutes. A per-platform status: "publishing" is NOT final — PostPeer pushes to the platform asynchronously and it can still fail (e.g. X video-length limits); keep polling social_get_post_status with the returned id until it reports published (success) or failed (carries lastError, credits auto-refunded).
- All other long-running tools — async by default, poll
get_job_status. generate_scene_image, generate_image_to_video, generate_images, edit_image_with_ai, remove_silence, transcribe_video_file, remotion_render, x_search, youtube_upload_video, youtube_upload_from_local_file, download_generated_video, download_generated_music, and animation_studio_send_message / _send_and_compile / _send_compile_export each return { started, jobId } immediately. Poll get_job_status { jobId } every ~10–20s until lastStatus is completed (the result field holds the tool's full payload and outputPaths lists the absolute output files) or error (real error message in error). Pass awaitCompletion: true only when your tool-call timeout comfortably exceeds the tool's documented blocking window. If a call or poll times out, the job is still running — NEVER blindly re-call the tool; paid generation would charge credits twice. Jobs survive client-side timeouts but not an app restart.
- Other long-running work (thumbnail creator UI flow) — follow each workflow; use
fetch_app_events when those flows rely on IPC progress and the user cares about step-by-step output, or when debugging problems (see Event stream).
- Report final completion/error to the user; use
fetch_app_events for detail only when requested or when troubleshooting.
Destructive actions
- Confirm user intent before
delete_project, delete_asset, delete_overlay_effect,
remove_animation_studio_export, or clear_animation_studio_exports.
- Removing a project library asset (VIDEO/BROLL/SOUND/MUSIC) is usually
update_project_settings, not delete_asset — see Removing imported project assets above.
- For overlays, only imported/user overlays are deletable; default bundled overlays are protected.
Keys and auth dependencies
- If provider features fail, check
read_api_keys, balances, and auth status tools first.
- For social posting, ensure account auth is active before upload.
- Paid generation runs on Shorz account credits — use
get_shorz_credits to confirm the user is
signed in and has balance. If not signed in, sign them in with shorz_sign_in_send_code then
shorz_sign_in_verify_code (ask the user for the emailed code).
- Zero-balance exception — the free tier. A signed-in user whose balance is effectively empty
(under 10 credits) still gets 4 free renders per week (resets Monday 00:00 UTC, no rollover)
on
auto-edit and clipping only. So a low balance is not automatically a blocker for those
two types — but it is for text-to-video, avatar, podcast and advertisement, which are
paid only. The lease is opened and settled by the Electron main process around every render,
so an MCP-triggered trigger_create_video / generate_video is covered exactly like the in-app
Create Video button. A failed, stopped, or empty render does not consume one of the 4.
(Unrelated to generate_images_nano_banana_free, which is credit-free for any user via their
own Google key. Also unrelated to a desktop build that predates the tier: there the lease simply
never opens and every call bills as before — a 402 on a zero-balance auto-edit render means
this build, or the kill switch, not a mistake on your side.)
- Two things the app does for its own UI but NOT for you — do them yourself before a free render:
- Pin the model. A free run zero-rates chat on
google/gemini-3.7-flash and nothing else;
any other model bills and 402s part-way through the render. The PromptBar pins it for
button-started renders, but nothing pins it on the MCP path — call set_main_ai_model (or
pass mainAiModelName on trigger_create_video) with google/gemini-3.7-flash first.
- Check the source length. Free runs cap the source at 30 minutes. The renderer sends the
probed duration so the proxy can refuse before the render starts; the MCP bridge does not send
it, so an over-long source is not refused up front — probe with
get_media_info and honour
the cap yourself. Per-run abuse ceilings still apply server-side (6h lease, 400 LLM calls, 3M
tokens, 5400 transcription seconds); tripping one ends the zero-rating mid-render, and the
render then bills — i.e. 402s — from that point on.
- What a free run covers — the allowlist IS the paid boundary (there is no second enforcement
path): main-AI chat on the pinned model (plus a cheap analysis-tier Gemini id that a few pipeline
steps hardcode — nothing for you to set), ElevenLabs transcription, and web-image search
(the WEB B-roll source). Everything else bills normally inside a free run and therefore 402s at
zero balance. Free in a render: the LLM edit itself, local effects (cuts, filler-word/silence
removal, zooms, face tracking, freeze frame, video colors), subtitles, titles, borders, overlays,
Auto SoundFX (it places bundled sound files, no provider call), four of the five B-roll
sources — Assets, WEB, GIF and EMOJI — and saving or exporting the finished file.
Not free (do not enable or queue these for a zero-balance user):
AI B-roll (
set_broll_settings.automaticAiBroll, image or video), dubbing and auto-music and
noise removal (set_audio_settings), thumbnail generation (thumbnail_creator_generate),
Animation Studio chat (animation_studio_send_* — compiling/exporting an already-built animation
is local and stays free), every standalone generation tool (generate_images,
generate_scene_image, generate_image_to_video, edit_image_with_ai,
proxy_aiml_video_generation, generate_tts_preview), x_search, and publishing
(social_publish, youtube_upload_* — connecting an account is not itself billed, but the
in-app Connect buttons are gated for these users, so don't promise a publish they can't pay for).
No silent-degradation cases: everything on the free list above works in full on a free run —
the only paid B-roll source is the AI tab, and every other lock above fails loudly with a 402
rather than quietly dropping content from the finished video.
- Out of runs or out of credits? There is no MCP purchase tool. Tell the user to buy credits in
the app (Buy Credits opens Stripe Checkout in their default browser; the wallet is
credited server-side and the app polls the balance), or to wait for the Monday 00:00 UTC reset.
Tool Families
Media always comes back as a file path, never base64. No Shorz tool returns a data URL or a raw
base64 blob: generated and rendered media is written to disk and the response carries the absolute
path (savedLocalFilePaths, pngFilePath, audioFilePath, outputPath, filePath). Read that path
to inspect the file, or pass it straight to any tool that takes a local path. If a payload ever does
arrive inline, the server writes it to %TEMP%\shorz-mcp-media\ and substitutes the path, appending a
note that names the extracted files — so a path is always what you act on.
App and Configuration
check_for_update
get_resource_path
open_file_directory, file_exists, get_local_file_size
read_api_keys, validate_elevenlabs_api_key
get_elevenlabs_balance (BYO ElevenLabs key balance; AIMLAPI key/license tools retired — paid generation runs on Shorz credits via the proxy)
Shorz Account (credits + sign-in)
get_shorz_credits — Shorz credit balance + entitlement for the signed-in user. Errors if no one is
signed in or the credit server is unreachable. Check this before running paid generation tools. A
balance under 10 credits means the free tier may apply — see Keys and auth dependencies below.
The reply still carries a legacy watermark_free field: it is a deprecated alias for
has_purchased and says nothing about exports. Shorz watermarks nothing, at any tier — never
report that field to the user or treat it as an entitlement.
get_shorz_usage_and_pricing — current model costs + recent usage for the signed-in user (same data
as the in-app Usage & Pricing window): balance, recent calls, and per-model credit pricing. All
amounts are in the credits the user pays (markup already included; never exposes our cost or markup).
Free-tier renders appear in recent_calls as their own rows — operation reads
"Free run · Auto edit" / "Free run · Clipping", units shows the token spend, and credits
is 0 (the in-app Usage tab renders those rows as "Free"). They carry type: "addition" as a
quirk of the shared mapping — nothing was added; report them as free runs, not as credit grants.
shorz_sign_in_send_code (email) → shorz_sign_in_verify_code (email + code) — email-OTP sign-in,
identical to the in-app Sign-in button. Step 1 emails a one-time code; ask the user for it, then
pass it (the 6–10 digit, usually 8-digit, value) to step 2. The Shorz desktop app must be running.
Projects and Settings
create_project, list_projects, delete_project, get_current_open_project
read_project_settings, update_project_settings
set_user_instructions (PromptBar creative brief), set_main_ai_model (PromptBar main LLM)
switch_project_aspect_ratio (directly updates VIDEO_SIZE width/height + optional fps)
- Direct panel settings tools:
set_subtitle_settings
set_title_settings
set_border_settings
set_overlay_settings
set_audio_settings
set_audio_visualization_settings
set_broll_settings
set_text_to_video_settings
set_avatar_settings
set_podcast_settings
set_advertisement_settings
set_general_video_settings
- Panel styling and “looks” are applied only via granular
set_*_settings (and project settings read/update); there are no MCP preset shortcut tools.
Generation and Rendering
generate_video, stop_video_generation, get_video_generation_status (primary status for project renders), fetch_app_events (IPC log stream; optional since cursor), render_text_preview
compile_remotion_preview, remotion_render
proxy_aiml_video_generation
generate_images (standalone AIML image generation to library paths; no Thumbnail Creator modal). Optional referenceImages (up to 3 face/subject photos) preserve the same face/identity — the headless equivalent of the Avatar Creator modal's face-reference picker; use it to generate an avatar or podcast host that must look like a specific person.
- Standalone generation assets (no project / no Create Video):
generate_scene_image — Python text-to-video image stack (Nano Banana 2, GPT Image 2, optional reference paths). Explicit aspectRatio or width/height. Does not read or write SCRTIPT_TO_VIDEO.
generate_image_to_video — Python i2v stack; requires imagePath, prompt, and explicit videoModel (same ids as textToVideoVideoModel). Optional durationSec (rejected with an error if outside the per-model range — Gemini Omni 1–10, Seedance 2.5 4–30, Seedance 2.0 family 4–15, Kling/Happy Horse 3–15; omitted → 8), aspectRatio (16:9 or 9:16 ONLY, default 9:16 — 1:1 is retired for video generation and is rejected, even though standalone image generation still accepts it) or explicit dimensions, generateAudio. Does not run a project timeline.
- Use these to produce library assets; use
import_frontend_assets / project workflows when assembling a f
…(truncated)
1---2name: shorz-mcp3description: Control Shorz via MCP to create and edit projects, configure panels, import assets, generate videos and thumbnails, publish to YouTube or TikTok, and run headless single-file video/image edits (no project required).4---56# Shorz MCP Server Agent Skill78Before any Shorz MCP tool call, confirm **Shorz is running** and the **MCP server is connected**. For panel-level or project-type-specific work, **load the matching reference file** from `references/` (paths in the tables below) before changing settings or triggering renders.910This skill is the entry point (`SKILL.md`). Detailed workflows live under `references/panel-workflows/` (cross-project panels), `references/project-workflows/` (per-`projectType` end-to-end flows), `references/headless-workflows/` (**project-independent** file operations), and `references/creative-strategy/` (viral formats, hooks, and content brainstorming). The routing tables tell you which file to open.1112## Operating Model1314- Treat Shorz as a stateful desktop runtime. Always read current state before writes.15- Most menu/panel option changes map to `read_project_settings` + `update_project_settings` (targeted deep-merge patches).16- Generation and long-running workflows are asynchronous. For **project video creation**, poll **`get_video_generation_status`** as the default way to know running vs done vs error. Use **`fetch_app_events`** only if the user asks for live logs/progress, or when you are **diagnosing** a failed or stuck render (see **Event stream**).17- Prefer deterministic/headless arguments (override paths) over dialog-driven behavior.18- **Live UI vs MCP write races** — when the Shorz Electron app has the target project open, certain fields (notably `UI_SETTINGS.user_input_instructions` / PromptBar) can be reactively rewritten by the renderer shortly after an MCP write, because the input box owns its own in-memory state. If a configure-only patch on PromptBar appears to "revert," it is the live UI overwriting disk. Workarounds: write again after a moment, ask the user to close the project, or accept the renderer's value as the new truth. This is not a tool failure — the `set_user_instructions` write itself succeeded.1920## Workflow routing2122Pick the matching workflow file before editing a project or panel. Don't improvise — the per-file skills lock in tool names, enums, persistence keys, and known clamps/rejects.2324### Guided creation (wizard) — vague idea, no concrete inputs2526When the user expresses **intent to make a video or asset without the concrete inputs** it needs (no file path/URL, no format, no counts, no script — e.g. "i want to clip a youtube video", "make me an avatar video", "I need a thumbnail", "an animated intro"), do **NOT** improvise questions and do **NOT** start configuring. Open **`references/guided-creation/README.md`** first (trigger rules, question protocol, the 11 design rules, summary + confirmation contract), then run the matching flow:2728| Intent sounds like | Guided flow file |29|---|---|30| clip/cut a long video into shorts | `references/guided-creation/clipping.md` |31| edit my own footage/photos into one video | `references/guided-creation/auto-edit.md` |32| make a video about X / from a script / faceless | `references/guided-creation/text-to-video.md` |33| talking head / AI presenter | `references/guided-creation/avatar.md` |34| two-person dialogue / AI podcast | `references/guided-creation/podcast.md` |35| ad / promo for my product | `references/guided-creation/advertisement.md` |36| thumbnail / cover image | `references/guided-creation/thumbnail-creator.md` |37| animated intro, logo reveal, kinetic text, title card | `references/guided-creation/animation-studio.md` |3839Each flow asks a short option-driven sequence (interactive question tool when available; ≤4 preset options, recommended default first, custom input always possible, never re-asking anything already given), ends with a readable summary + an explicit confirmation, and only then executes via the matching `references/project-workflows/*.md` or panel workflow. If the user already gave a complete spec, skip the wizard and confirm the gaps in one question.4041### Project workflows (one per `projectType`)4243| `projectType` | Workflow file | Primary MCP tools |44|---|---|---|45| `auto-edit` | `references/project-workflows/auto-edit.md` | Panel `set_*_settings` (subtitle, title, border, audio, overlay, broll, general video) + `switch_project_aspect_ratio` |46| `text-to-video` | `references/project-workflows/text-to-video.md` | `set_text_to_video_settings`, `save_text_to_video_speech_audio`, `save_text_to_video_reference_images` |47| `avatar` | `references/project-workflows/avatar.md` | `set_avatar_settings`, `select_avatar_image`, `select_avatar_angle_image`, `select_avatar_audio`, `save_avatar_image`, `save_avatar_audio` |48| `podcast` | `references/project-workflows/podcast.md` | `set_podcast_settings`, `select_podcast_avatar_image`, `list_elevenlabs_voices` |49| `advertisement` | `references/project-workflows/advertisement.md` | `set_advertisement_settings`, `select_advertisement_image`, `remove_advertisement_image` |50| `clipping` | `references/project-workflows/clipping.md` | `update_project_settings` (`CLIPING`, `ASSET_PATHS`), `download_social_video`, `switch_project_aspect_ratio` |5152### Headless workflows (no project, no `projectType`)5354These MCP tools work on **local files only**. They do **not** use projects, `settings.json`, PromptBar, Create Video, or any `projectType`. Do **not** call `create_project` or `read_project_settings` before using them.5556| Workflow | File | Primary MCP tools |57|---|---|---|58| Single-file deterministic edits | `references/headless-workflows/single-asset-edit.md` | `trim_video`, `crop_media`, `change_video_speed`, `remove_audio`, `set_audio_volume`, `rotate_media`, `flip_media`, `reverse_video`, `loop_video`, `fade_video`, `freeze_frame`, `set_image_duration`, `audio_fade`, `remove_silence`, `edit_image_with_ai`, `get_media_info`, `resize_media`, `fit_to_aspect`, `extract_audio`, `replace_audio`, `concat_media`, `extract_video_frames` |59| Pexels stock media search | `references/headless-workflows/pexels-stock-media.md` | `pexels_search_photos`, `pexels_search_videos`, `pexels_curated_photos`, `pexels_popular_videos`, `pexels_get_photo`, `pexels_get_video` |60| X (Twitter) live search | `references/headless-workflows/x-search.md` | `x_search` (natural-language X search with citations; **spends Shorz credits**) |61| Free Nano Banana 2 images (own Google key) | `references/headless-workflows/nano-banana-free-images.md` | `generate_images_nano_banana_free` (**no Shorz credits** — runs on the user's Google AI Studio free-tier quota) |6263See **`references/headless-workflows/README.md`** for when to use headless edits vs a full project workflow. To put an edited file into a project afterward, that is a **separate** import step (`import_frontend_assets`, `save_file_as`, or project-specific path patches).6465### Companion skills6667| Skill | Use it for |68|---|---|69| **`shorz-ui-automation`** | Driving the app through its **actual UI** with a real, visible cursor — tutorial footage, feature demos, screenshots for the website or docs, onboarding walkthroughs. It owns the `get_ui_map` → `ui_click` → `get_ui_map` loop and the six UI tools (`get_ui_map`, `scroll_ui_element_into_view`, `ui_click`, `ui_type`, `ui_press_keys`, `ui_scroll`), which are **not** covered anywhere else in this skill. Load it whenever the deliverable is a *visual of the UI*. For changing a setting or rendering **without filming it**, stay here — the tools in this skill are faster and need no UI. |70| **`shorz-motion-graphics`** | Generating a green-screen motion graphics overlay and chroma-keying it onto an existing video, any length, in `16:9` / `9:16` / `1:1`. Covers every style — explainer graphics, infographics and data callouts, kinetic typography, broadcast lower-thirds, annotation arrows, chapter cards, and high-energy short-form. Load it instead of improvising from the Animation Studio panel workflow whenever the goal is graphics **on top of existing footage** — it carries the source-analysis, safe-zone, segmentation, chroma-key and compositing rules that panel reference does not. |7172### Creative and strategy workflows7374| Strategy area | Workflow file | Primary purpose |75|---|---|---|76| Content brainstorming & viral playbooks | `references/creative-strategy/content-brainstorming.md` | Designing high-retention hooks, formats, and CTAs mapped to Shorz tools |7778Open **`references/creative-strategy/content-brainstorming.md`** when the user asks for content ideas, viral formats, organic growth playbooks, or hook/CTA variants — then switch to the matching **`references/project-workflows/*.md`** (or headless workflow) to execute.7980### Panel workflows (cross-project; usable on matching sidebar panels)8182| Sidebar panel | Workflow file | Primary MCP tool |83|---|---|---|84| General Video / Auto Zoom | `references/panel-workflows/settings.md` | `set_general_video_settings` |85| B-roll (Assets / Web / GIF / AI / Emoji) | `references/panel-workflows/broll.md` | `set_broll_settings` |86| Audio (mix, dubbing, reverb, visualization) | `references/panel-workflows/audio.md` | `set_audio_settings` + `set_audio_visualization_settings` |87| Overlay | `references/panel-workflows/overlay.md` | `set_overlay_settings` + `get_overlay_effects` lifecycle |88| Border | `references/panel-workflows/border.md` | `set_border_settings` |89| Text → captions / subtitles | `references/panel-workflows/subtitle.md` | `set_subtitle_settings` |90| Text → headline / banner | `references/panel-workflows/title.md` | `set_title_settings` |91| Thumbnail Creator (modal) | `references/panel-workflows/thumbnail-creator.md` | `open_thumbnail_creator`, `set_thumbnail_creator_settings`, `thumbnail_creator_generate`, `get_thumbnail_creator_generation_status` |92| Animation Studio (modal) | `references/panel-workflows/animation-studio.md` | `animation_studio_*`, `compile_remotion_preview`, `remotion_render` |93| Your Library (VIDEO / BROLL / SOUND / MUSIC) | `references/panel-workflows/your-library-assets.md` | `update_project_settings` (`ASSET_PATHS`); `delete_asset` only when deleting files on disk |9495The **Text** sidebar shows subtitles and titles together but uses **two** tools with **two** key families (`subtitle*` vs `title*`). Never send subtitle keys to `set_title_settings` or vice versa — for both kinds, call each tool once with a minimal patch.9697### Main VIDEO import (“Import Main Assets”) vs project type9899In the Electron app, **`import_frontend_assets`** with `assetType: "video"` mirrors the UI **Import Main Assets** lane (fills the main timeline / `assets.VIDEOS`, which persists to **`ASSET_PATHS.main_video_asset_paths`** on save alongside other library categories). The single source of truth is **`isMainAssetsLaneEnabled`** (`frontend/src/utils/mediaAssetUtils.ts`): the main VIDEOS lane is **disabled** for **`podcast`**, **`avatar`**, **`advertisement`**, and for **`text-to-video`** unless **`textToVideoSourceMedia === "imported"`**. That rule gates the UI (import button, Your Library → VIDEOS tab, timeline strip) **and is enforced main-process-side**: a headless `import_frontend_assets` call with `overridePaths` and `assetType: "video"` into a lane-disabled open project is **rejected with an error** (redirecting to `"broll"`) instead of persisting `main_video_asset_paths`. Match this in guidance: never tell users they can “add main timeline videos” in templates that hide or disable main-video import.100101| `projectType` | Main VIDEO import in UI (timeline / PromptBar gateway) | Your Library shows VIDEOS tab |102|---|---|---|103| `auto-edit` | Yes | Yes |104| `clipping` | Yes (typically one long source patched to **`ASSET_PATHS.main_video_asset_paths`**) | Yes |105| `text-to-video` | **Only when** Source Media is **`imported`** | **Only then** |106| `avatar` | **No** (`canImportMainAssets` false) | **No** |107| `podcast` | **No** (`canImportMainAssets` false) | **No** |108| `advertisement` | **No** (main lane disabled) — **workflow is reference stills**, not a main VIDEO lane — use **`select_advertisement_image`** / **`import_frontend_assets`** with **`image`** | **No** (tab hidden) |109110**Agents:** Use **`avatar`**, **`podcast`**, **`advertisement`**, **`text-to-video`** (unless `imported`) workflows for their **typed** inputs (still images, avatars, product/person images, script/audio, generated sources). `import_frontend_assets` with **`video`** into these projects is **rejected with an error** (headless `overridePaths` path) — import supporting footage as **`broll`**, which every project type keeps.111112### One asset per file name (every library lane)113114A lane (VIDEO / BROLL / SOUND / MUSIC) holds **at most one asset per file name** — compared case-insensitively, folder ignored, and **per lane** (the same file may legitimately sit in both VIDEO and BROLL) — because the backend addresses assets by basename: PromptBar `@mentions`, the Python render maps, and music/SFX name lookups. The **UI and MCP enforce the same rule**: `import_frontend_assets` **skips** a file whose name the lane already holds and lists it in **`skipped`** (reason `duplicate-name`), and an `update_project_settings` patch of a lane collapses repeated names and reports **`duplicateAssetNamesDropped`**. Nothing errors and nothing is overwritten — so **always check `skippedCount` before telling the user an import is done**, especially after a paid generation. Need both files? Rename one. Full contract and result shapes: **`references/panel-workflows/your-library-assets.md`** → *One asset per file name*.115116### PromptBar semantics by project type117118The PromptBar (`set_user_instructions` → `UI_SETTINGS.user_input_instructions`) does **not** mean the same thing for every project type. Source: `frontend/src/data/projects.ts` (`projectTypePromptPlaceholderMap`).119120| Type | PromptBar role | Spoken/script content lives in |121|---|---|---|122| `auto-edit` | Primary creative brief (required for Create Video). Can also direct per-clip editing with no panel toggle: transitions between clips, camera motion, speed/volume/reverse/loop/flip/rotate, fill-the-frame framing, beat-synced cuts to imported music, and the imported-music bus itself (MUSIC lane holds any number of tracks, played back to back — the brief can reorder tracks, trim each one, and place/fade/mix the music) — full vocabulary in `references/project-workflows/auto-edit.md` → *What the PromptBar can direct* | n/a |123| `text-to-video` | Optional **look and mood** guidance | `textToVideoScript` (or saved speech audio in `audio` input mode) |124| `avatar` | Optional guidance for **enabled auto-edit features** (captions, B-roll, music, etc.) — **not the spoken script**. Can also arrange imported music (order, sections, placement, volume, fades, mix) | `avatarScript` (script mode) or `avatarAudioUrl` (audio mode) |125| `podcast` | Optional B-roll / music / SFX guidance — **not the dialogue**. Can also arrange imported music (order, sections, placement, volume, fades, mix) | `podcastScript` with `[Interviewer]` / `[Interviewee]` line tags |126| `advertisement` | Ad creative brief | Product/person images via `set_advertisement_settings` |127| `clipping` | **Optional** — only when steering topics, clip length, platform, or hooks | Source video at `ASSET_PATHS.main_video_asset_paths` |128129**Rule:** Never overwrite PromptBar with a script for `avatar`, `podcast`, or `text-to-video`. Put the spoken text in the panel field listed above.130131**Referencing a specific asset:** to point the brief at one file in the project library, write its **filename in double quotes** — `use "intro.mp4" as the opener`. That is exactly what the desktop app's `@` picker and its drag-from-timeline shortcut insert, and the app renders any such reference as a pill. Get the real filenames from `read_project_settings` (`ASSET_PATHS`) or `get_video_assets` / `get_audio_assets` first — a name that isn't in the library is just prose to the analyzers.132133**Output framing (all project types):** PromptBar / `set_user_instructions` text is **never** the place for export geometry. Do **not** include aspect-ratio tokens (`9:16`, `16:9`, `1:1`), pixel dimensions (`1080×1920`, `1920×1080`, `1280×720`), `video_width` / `video_height`, or output **fps** in the creative brief — the project already has **`VIDEO_SIZE`** from the UI or **`switch_project_aspect_ratio`**. Platform or delivery names for creative intent (`TikTok`, `Reels`, `Shorts`, “vertical short”) are fine; technical sizing belongs in the aspect tool, not PromptBar. When the user asks for a format change, call **`switch_project_aspect_ratio`** and strip sizing lines from any PromptBar text you persist.134135### PromptBar main AI model136137The PromptBar **model dropdown** (all project types) selects which AIML chat model Create Video and backend LLM calls use. It is **not** the same as panel-specific models (`textToVideoImageModel`, thumbnail `imageGenerator`, etc.).138139| MCP tool | Persistence | Allowed values |140|---|---|---|141| `set_main_ai_model` | `AI_MODEL.main_ai_model_name` | Server-driven — call **`list_main_ai_models`** for the live lineup and pass an id from its response. At time of writing: `anthropic/claude-opus-5` (Opus 5, default), `anthropic/claude-fable-5` (Fable 5), `anthropic/claude-sonnet-5` (Sonnet 5, re-enabled 2026-08-10 — 1 / 2 credits per 1k, the cheapest Claude), `openai/gpt-5-6-terra` (GPT 5.6 Terra), `openai/gpt-5-6-sol` (GPT 5.6 Sol, frontier tier), `google/gemini-3.7-flash` (Gemini 3.7 Flash, ~0.2 / 1 credits per 1k tokens — much cheaper than Opus 5; a normal paid-selectable model billed like any other, **and** the only id a free run zero-rates) — six models; treat that as a snapshot, not an allowlist. This model also drives image / video-frame asset analysis, including key-subject localization. **On a free-tier run** (`auto-edit` / `clipping`, zero-balance user) only `google/gemini-3.7-flash` is zero-rated — the in-app picker locks itself to it, but the MCP path does not, so **you** must `set_main_ai_model` (or pass `mainAiModelName`) with that id or the render bills and 402s |142143- **Read current model:** `read_project_settings` → `AI_MODEL.main_ai_model_name`.144- **Before Create Video:** When the user names Opus, Fable, GPT 5.6 Terra, GPT 5.6 Sol, Gemini 3.7 Flash, or a specific model id, call **`set_main_ai_model`** before **`trigger_create_video`** / **`generate_video`**, or pass **`mainAiModelName`** on **`trigger_create_video`** for a one-shot run (persists to disk first, matching the UI dropdown at generate time).145- **Live UI:** Patches go through `update-project-settings`; the open app reloads the dropdown from disk (unlike PromptBar text, the model selector rarely races with in-memory UI state).146147### Animation Studio chat model148149The Animation Studio modal has its **own** model picker (labels like `claude-opus-5`). It does **not** read `AI_MODEL.main_ai_model_name`.150151| MCP | Role |152|---|---|153| `animation_studio_list_models` | Supported chat **`model`** ids for this build |154| `animation_studio_send_*` optional **`model`** | Per-call override; default **`anthropic/claude-opus-5`** |155156**Allowed ids:** server-driven — `animation_studio_list_models` returns the live lineup (same `main_ai` catalog category as the PromptBar picker; at time of writing six: Opus 5, Fable 5, Sonnet 5, GPT 5.6 Terra, GPT 5.6 Sol, Gemini 3.7 Flash). Call it and pass an id from the response rather than one from this page. **`anthropic/claude-opus-4-6`**, **`anthropic/claude-opus-4-7`** and **`anthropic/claude-opus-4-8`** are retired from the selector — use **`anthropic/claude-opus-5`** instead. (**`anthropic/claude-sonnet-5`** was retired by `0017` but **re-enabled by `0033`** on 2026-08-10 — it is selectable again.) (The proxy still resolves `anthropic/claude-opus-4-8` via a disabled legacy-alias catalog row so older saved projects keep working, but do not pass it for new work.) Full workflow: **`references/panel-workflows/animation-studio.md`** → *Model selection*.157158### Project targeting rules (apply to every **project** workflow)159160**Skip this section for headless single-asset edit tools** (`trim_video`, `crop_media`, etc.) — they only need `inputPath` and Shorz running. See **`references/headless-workflows/single-asset-edit.md`**.1611621. If the user names a project, resolve it with `list_projects` and use it. If not found, follow rule 5.1632. If the user says "current / open / this project", use `get_current_open_project`.1643. If the user gives no project identity, prefer `get_current_open_project`; otherwise ask whether to use existing or create new. **Never auto-pick** when multiple candidates match.1654. If the requested workflow conflicts with the current `projectType`, **do not silently repurpose** — ask whether to continue in the current project or create/select a matching type.1665. Create a new project only when the user explicitly asks, when a named target is missing and they approve creation, or when they ask for clean separation.1676. Never run destructive project actions (`delete_project`) without explicit confirmation. Same for `delete_asset`, `delete_overlay_effect`, `remove_animation_studio_export`, `clear_animation_studio_exports`.168169### Asset verification: project main media vs My Assets library170171Two different things — agents mix them up. Pick the right one.172173- **Project main / timeline media** (the path(s) synced from the main VIDEO lane — **only workflows that expose main VIDEO import**, see **Main VIDEO import** above — e.g. `auto-edit` montage clips, clipping’s long source, `text-to-video` with **`imported`** source media): read `read_project_settings` → `ASSET_PATHS.main_video_asset_paths`, verify with **`file_exists`**. **`avatar`** / **`podcast`** templates do **not** use this lane in the shipped UI — do not treat `main_video_asset_paths` as required for Create Video there. **`advertisement`** center on **`ADVERTISEMENT.*` image paths**, not timeline video. There is **no** MCP tool that lists "the project's VIDEOS tab"; for clipping do not verify the source via `get_video_assets`.174- **My Assets library tabs** (cross-project inventory; AI-generated outputs, imports, downloads): use the per-tab `get_*_assets` tools or filtered **`query_my_assets`** as described in `references/panel-workflows/README.md` → *Library and cross-cutting MCP tools*.175176### Removing imported project assets (Your Library)177178When the user asks to **remove**, **clear**, or **delete** something from the project **Your Library** lanes (**VIDEO**, **BROLL**, **SOUND**, **MUSIC**), they usually mean **drop it from the project**, not erase the file from disk. Full tab mapping and steps: **`references/panel-workflows/your-library-assets.md`**.179180| UI tab | `ASSET_PATHS` field | Clear entire lane |181|---|---|---|182| VIDEO (Import Main Assets) | `main_video_asset_paths` | `update_project_settings` → `{ ASSET_PATHS: { main_video_asset_paths: "" } }` |183| BROLL | `broll_video_asset_paths` | `… { broll_video_asset_paths: "" }` |184| SOUND (sound effects) | `audio_fx_asset_paths` | `… { audio_fx_asset_paths: "" }` |185| MUSIC | `music_asset_paths` | `… { music_asset_paths: "" }` |186187- **Default tool:** **`update_project_settings`** on the matching field. Paths are **comma-separated**; to remove one file, read settings, split/filter/rejoin, then patch. **Do not** use `delete_asset` unless the user explicitly wants the **file deleted from disk** (destructive; confirm first).188- **UI parity:** In-app trash on a library card only updates project paths (same as clearing via MCP); it does not unlink the source file.189- **Not the same as:** `get_*_assets` / My Assets modal inventory (use `delete_asset` there only when user wants the library file gone). Playback outputs (`last_generated_final_video_for_playback_mode`, `playback_history_video_paths`) stay until changed separately.190- **VIDEO tab availability** depends on `projectType` — see *Main VIDEO import* above before clearing main video on `avatar` / `podcast` / etc.191192## Required Workflow Rules1931940. **Pre-flight: the app's requirements guard does NOT protect you**195 - Since 2026-08-19 the desktop UI blocks **Create Video** and names what is missing when a196 project cannot possibly render. That check lives in the PromptBar's submit handler197 (`frontend/src/utils/generationRequirements.ts`) — **`trigger_create_video` and198 `generate_video` bypass it entirely.** Over MCP you get the old behaviour: the render starts,199 burns time, and fails (or silently returns the user's own file). Verify these yourself before200 triggering a render:201202 | Project type | Must be true before you trigger |203 |---|---|204 | `auto-edit` | ≥1 file in the main VIDEOS lane **and** PromptBar instructions **> 10 chars** (below that the auto-editor is skipped and the source is re-exported untouched) |205 | `clipping` | **exactly one** video in the main lane — zero or two+ both fail |206 | `avatar` | avatar image set **and** (script **> 10 chars** **or** saved audio). Either input alone is enough; the mode toggle does not invalidate the other |207 | `podcast` | script **> 10 chars** in `[Interviewer]`/`[Interviewee]` form **and BOTH** avatar images set |208 | `text-to-video` | script **≥ 50 chars** **or** saved speech audio; plus ≥1 imported main asset when `textToVideoSourceMedia` is `imported` |209 | `advertisement` | **at least one** of product image / character image (either alone is fine) |210211 - These mirror the renderer's own guards, so treat them as hard preconditions rather than212 advice. Re-read a setting after writing it when the render depends on it (`read_project_settings`).2132141. **Project targeting first**215 - Prefer `get_current_open_project` first (active UI project source of truth).216 - If no active project is set, call `list_projects` and ask user to choose existing vs approve creating new.217 - Use absolute paths from `get_projects_path` and returned project metadata.2182192. **Safe setting edits**220 - Call `read_project_settings` when you need the full picture or before non-trivial decisions.221 - Persist nested changes with `update_project_settings`: pass only the `updates` object for keys/sections to change (objects merge recursively; scalars and arrays replace). Optional `unsetPaths` deletes keys by dot notation. The main process reads the file, merges, validates, and writes atomically—**do not** reintroduce a manual read→edit full blob→write loop for ordinary edits.222 - For `set_*_settings` tools, MCP now performs strict validation:223 - unknown keys are rejected224 - invalid enum/color values are rejected225 - numeric values are range-validated; out-of-bounds values are **rejected or clamped per tool** (for example `set_border_settings` **clamps** `borderWidth` to 1–100 and `borderAnimationDuration` to 1–5)2262273. **Asynchronous operations**228 - **Video generation (`generate_video` / Create Video)** — Poll **`get_video_generation_status`** until `lastStatus` is terminal (`completed`, `completed_no_output`, `error`, `stopped`, etc.). That is the main tool for project renders.229 - **`fetch_app_events`** — Use **sparingly**: when the user **explicitly** wants the raw event/log stream, or when **`get_video_generation_status` is unclear** (stuck, unexpected state) and you need the IPC log lines to see what the UI would have seen. Not the default loop for “wait for video.”230 - **Social video downloads (`download_social_video`)** — async by default; poll **`get_social_video_download_status`** until `lastStatus` is `completed` or `error`. YouTube extraction alone regularly takes minutes, so the blocking `awaitCompletion: true` form is only safe for short clips.231 - **Social publishing (`social_publish`)** — async by default; the tool starts the job and returns immediately. Poll **`get_social_publish_status`** until `lastStatus` is terminal (`completed` | `error`); its `result` carries the same per-platform payload as the blocking form. Media upload alone routinely runs for minutes, so pass `awaitCompletion: true` only when the MCP client's tool-call timeout exceeds ~8 minutes. A per-platform `status: "publishing"` is NOT final — PostPeer pushes to the platform asynchronously and it can still fail (e.g. X video-length limits); keep polling **`social_get_post_status`** with the returned `id` until it reports `published` (success) or `failed` (carries `lastError`, credits auto-refunded).232 - **All other long-running tools — async by default, poll `get_job_status`.** `generate_scene_image`, `generate_image_to_video`, `generate_images`, `edit_image_with_ai`, `remove_silence`, `transcribe_video_file`, `remotion_render`, `x_search`, `youtube_upload_video`, `youtube_upload_from_local_file`, `download_generated_video`, `download_generated_music`, and `animation_studio_send_message` / `_send_and_compile` / `_send_compile_export` each return `{ started, jobId }` immediately. Poll **`get_job_status { jobId }`** every ~10–20s until `lastStatus` is `completed` (the `result` field holds the tool's full payload and `outputPaths` lists the absolute output files) or `error` (real error message in `error`). Pass `awaitCompletion: true` only when your tool-call timeout comfortably exceeds the tool's documented blocking window. **If a call or poll times out, the job is still running — NEVER blindly re-call the tool; paid generation would charge credits twice.** Jobs survive client-side timeouts but not an app restart.233 - **Other long-running work** (thumbnail creator UI flow) — follow each workflow; use `fetch_app_events` when those flows rely on IPC progress **and** the user cares about step-by-step output, or when debugging problems (see **Event stream**).234 - Report final completion/error to the user; use `fetch_app_events` for detail only when requested or when troubleshooting.2352364. **Destructive actions**237 - Confirm user intent before `delete_project`, `delete_asset`, `delete_overlay_effect`,238 `remove_animation_studio_export`, or `clear_animation_studio_exports`.239 - **Removing a project library asset** (VIDEO/BROLL/SOUND/MUSIC) is usually **`update_project_settings`**, not `delete_asset` — see *Removing imported project assets* above.240 - For overlays, only imported/user overlays are deletable; default bundled overlays are protected.2412425. **Keys and auth dependencies**243 - If provider features fail, check `read_api_keys`, balances, and auth status tools first.244 - For social posting, ensure account auth is active before upload.245 - Paid generation runs on Shorz account credits — use `get_shorz_credits` to confirm the user is246 signed in and has balance. If not signed in, sign them in with `shorz_sign_in_send_code` then247 `shorz_sign_in_verify_code` (ask the user for the emailed code).248 - **Zero-balance exception — the free tier.** A signed-in user whose balance is effectively empty249 (under 10 credits) still gets **4 free renders per week** (resets Monday 00:00 UTC, no rollover)250 on **`auto-edit` and `clipping` only**. So a low balance is not automatically a blocker for those251 two types — but it *is* for `text-to-video`, `avatar`, `podcast` and `advertisement`, which are252 paid only. The lease is opened and settled by the Electron **main** process around every render,253 so an MCP-triggered `trigger_create_video` / `generate_video` is covered exactly like the in-app254 Create Video button. A failed, stopped, or empty render does **not** consume one of the 4.255 (Unrelated to `generate_images_nano_banana_free`, which is credit-free for *any* user via their256 own Google key. Also unrelated to a desktop build that predates the tier: there the lease simply257 never opens and every call bills as before — a 402 on a zero-balance `auto-edit` render means258 this build, or the kill switch, not a mistake on your side.)259 - **Two things the app does for its own UI but NOT for you — do them yourself before a free render:**260 1. **Pin the model.** A free run zero-rates chat on **`google/gemini-3.7-flash`** and nothing else;261 any other model bills and 402s part-way through the render. The PromptBar pins it for262 button-started renders, but nothing pins it on the MCP path — call **`set_main_ai_model`** (or263 pass `mainAiModelName` on `trigger_create_video`) with `google/gemini-3.7-flash` first.264 2. **Check the source length.** Free runs cap the source at **30 minutes**. The renderer sends the265 probed duration so the proxy can refuse before the render starts; the MCP bridge does not send266 it, so an over-long source is **not** refused up front — probe with `get_media_info` and honour267 the cap yourself. Per-run abuse ceilings still apply server-side (6h lease, 400 LLM calls, 3M268 tokens, 5400 transcription seconds); tripping one ends the zero-rating mid-render, and the269 render then bills — i.e. 402s — from that point on.270 - **What a free run covers — the allowlist IS the paid boundary** (there is no second enforcement271 path): main-AI chat on the pinned model (plus a cheap analysis-tier Gemini id that a few pipeline272 steps hardcode — nothing for you to set), ElevenLabs **transcription**, and **web-image search**273 (the WEB B-roll source). Everything else bills normally inside a free run and therefore **402s at274 zero balance**. Free in a render: the LLM edit itself, local effects (cuts, filler-word/silence275 removal, zooms, face tracking, freeze frame, video colors), subtitles, titles, borders, overlays,276 **Auto SoundFX** (it places bundled sound files, no provider call), **four of the five B-roll277 sources — Assets, WEB, GIF and EMOJI** — and saving or exporting the finished file.278 Not free (do **not** enable or queue these for a zero-balance user):279 AI B-roll (`set_broll_settings.automaticAiBroll`, image *or* video), dubbing and auto-music and280 noise removal (`set_audio_settings`), thumbnail generation (`thumbnail_creator_generate`),281 Animation Studio chat (`animation_studio_send_*` — compiling/exporting an already-built animation282 is local and stays free), every standalone generation tool (`generate_images`,283 `generate_scene_image`, `generate_image_to_video`, `edit_image_with_ai`,284 `proxy_aiml_video_generation`, `generate_tts_preview`), `x_search`, and publishing285 (`social_publish`, `youtube_upload_*` — connecting an account is not itself billed, but the286 in-app Connect buttons are gated for these users, so don't promise a publish they can't pay for).287 **No silent-degradation cases:** everything on the free list above works in full on a free run —288 the only paid B-roll source is the **AI** tab, and every other lock above fails loudly with a 402289 rather than quietly dropping content from the finished video.290 - **Out of runs or out of credits?** There is no MCP purchase tool. Tell the user to buy credits in291 the app (**Buy Credits** opens Stripe Checkout in their **default browser**; the wallet is292 credited server-side and the app polls the balance), or to wait for the Monday 00:00 UTC reset.293294## Tool Families295296**Media always comes back as a file path, never base64.** No Shorz tool returns a data URL or a raw297base64 blob: generated and rendered media is written to disk and the response carries the absolute298path (`savedLocalFilePaths`, `pngFilePath`, `audioFilePath`, `outputPath`, `filePath`). Read that path299to inspect the file, or pass it straight to any tool that takes a local path. If a payload ever does300arrive inline, the server writes it to `%TEMP%\shorz-mcp-media\` and substitutes the path, appending a301note that names the extracted files — so a path is always what you act on.302303### App and Configuration304- `check_for_update`305- `get_resource_path`306- `open_file_directory`, `file_exists`, `get_local_file_size`307- `read_api_keys`, `validate_elevenlabs_api_key`308- `get_elevenlabs_balance` (BYO ElevenLabs key balance; AIMLAPI key/license tools retired — paid generation runs on Shorz credits via the proxy)309310### Shorz Account (credits + sign-in)311- `get_shorz_credits` — Shorz credit balance + entitlement for the signed-in user. Errors if no one is312 signed in or the credit server is unreachable. Check this before running paid generation tools. A313 balance under 10 credits means the free tier may apply — see *Keys and auth dependencies* below.314 The reply still carries a legacy **`watermark_free`** field: it is a deprecated alias for315 `has_purchased` and says nothing about exports. **Shorz watermarks nothing, at any tier** — never316 report that field to the user or treat it as an entitlement.317- `get_shorz_usage_and_pricing` — current model costs + recent usage for the signed-in user (same data318 as the in-app Usage & Pricing window): balance, recent calls, and per-model credit pricing. All319 amounts are in the credits the user pays (markup already included; never exposes our cost or markup).320 Free-tier renders appear in `recent_calls` as their own rows — `operation` reads321 **"Free run · Auto edit"** / **"Free run · Clipping"**, `units` shows the token spend, and `credits`322 is **0** (the in-app Usage tab renders those rows as "Free"). They carry `type: "addition"` as a323 quirk of the shared mapping — nothing was added; report them as free runs, not as credit grants.324- `shorz_sign_in_send_code` (email) → `shorz_sign_in_verify_code` (email + code) — email-OTP sign-in,325 identical to the in-app Sign-in button. Step 1 emails a one-time code; ask the user for it, then326 pass it (the 6–10 digit, usually 8-digit, value) to step 2. The Shorz desktop app must be running.327328### Projects and Settings329- `create_project`, `list_projects`, `delete_project`, `get_current_open_project`330- `read_project_settings`, `update_project_settings`331- `set_user_instructions` (PromptBar creative brief), `set_main_ai_model` (PromptBar main LLM)332- `switch_project_aspect_ratio` (directly updates `VIDEO_SIZE` width/height + optional fps)333- Direct panel settings tools:334 - `set_subtitle_settings`335 - `set_title_settings`336 - `set_border_settings`337 - `set_overlay_settings`338 - `set_audio_settings`339 - `set_audio_visualization_settings`340 - `set_broll_settings`341 - `set_text_to_video_settings`342 - `set_avatar_settings`343 - `set_podcast_settings`344 - `set_advertisement_settings`345 - `set_general_video_settings`346- Panel styling and “looks” are applied only via granular `set_*_settings` (and project settings read/update); there are no MCP preset shortcut tools.347348### Generation and Rendering349- `generate_video`, `stop_video_generation`, `get_video_generation_status` (primary status for project renders), `fetch_app_events` (IPC log stream; optional `since` cursor), `render_text_preview`350- `compile_remotion_preview`, `remotion_render`351- `proxy_aiml_video_generation`352- `generate_images` (standalone AIML image generation to library paths; no Thumbnail Creator modal). Optional `referenceImages` (up to 3 face/subject photos) preserve the **same face/identity** — the headless equivalent of the Avatar Creator modal's face-reference picker; use it to generate an avatar or podcast host that must look like a specific person.353- **Standalone generation assets (no project / no Create Video):**354 - `generate_scene_image` — Python text-to-video image stack (`Nano Banana 2`, `GPT Image 2`, optional reference paths). Explicit `aspectRatio` or `width`/`height`. Does **not** read or write `SCRTIPT_TO_VIDEO`.355 - `generate_image_to_video` — Python i2v stack; requires `imagePath`, `prompt`, and explicit `videoModel` (same ids as `textToVideoVideoModel`). Optional `durationSec` (**rejected with an error if outside the per-model range** — Gemini Omni 1–10, Seedance 2.5 4–30, Seedance 2.0 family 4–15, Kling/Happy Horse 3–15; omitted → 8), `aspectRatio` (**`16:9` or `9:16` ONLY, default `9:16`** — **1:1 is retired for video generation** and is rejected, even though standalone *image* generation still accepts it) or explicit dimensions, `generateAudio`. Does **not** run a project timeline.356 - Use these to produce library assets; use `import_frontend_assets` / project workflows when assembling a f357358…(truncated)