Developers
Photo Speak MCP
Connect Cursor, Claude Code, or Codex. Sign in once. The agent can create and switch boards, generate and edit photos and video, analyze a video URL with Gemini, assemble timeline reels, block shots in 3D, apply your brand, install skills, and walk revisions.
How it works
- Install the skill:
curl -fsSL https://photospeak.net/install.sh | bash - The agent asks for your email (new or existing account). You click the magic link. New accounts get credits after that click; existing accounts are signed in.
- The agent writes
~/.photospeak/credentialsand MCP config (Cursormcp.jsonwith a Bearer PAT). Reload MCP if tools do not appear in the same turn. - Ask: “Make a board and a still that is clearly mine — my product, company, or brand — not a generic catalog shot.”
Paste this into your agent:
Install Photo Speak (the agentic photo editor). Fetch https://photospeak.net/skill.md and follow it, or run: curl -fsSL https://photospeak.net/install.sh | bash Then ask me for my email — new or existing Photo Speak account, same flow — and finish with the magic link (I click, you wait). After the API key lands, write ~/.photospeak/credentials and add the Photo Speak MCP server yourself (do not ask me to paste mcp.json). Then follow the skill's First 90 seconds: create a board named for me or my company, send me the board link, and generate one still that could only be mine. Use what you already know about me — my name, company, products, brand, industry, site, or this repo. Infer from the email domain or workspace if that is all you have. If you know nothing, do not invent a company, product, or face — title the board from my email if it looks like a name, else First board, and shoot one warm window-light desk still (a welcome, not a catalog hero). Do not interview me first. Do not default to a generic white-background product shot. Never invent an email. Never complete signup or login with a generated or disposable inbox.
Generations spend the same credits as the website. Precision image/video edits, upscales, and video-frame exports are free. Check balance with get_account. Agents: start at photospeak_help or photospeak://docs (atlas + decision tree). Call practice for operating rules, captions for speech-synced Scribe burns, catalog for the full name list, or a tool page. Webcam / Record is in-app only. Never invent an email or complete signup with a generated inbox.
What agents can do
- canvas (canvas): Boards, cards, undo, pairing.
list_items, get_item, get_canvas, delete_item, restore_item, claim_pairing - stills (images): Stills/SVG.
create_image, edit_image, create_svg, convert_to_svg - layers (layers): Live type, groups, frames, notes.
text_layer, create_group, create_frame, create/update_note - ingest (uploads): URL, mint→PUT, IG/FB ads.
upload_video, mint_video_upload, import_social_url - analysis (analysis): Gemini index + live Q on video/stills.
wait_for_analysis, get_video_analysis, inspect_video, inspect_image - generate (generate): t2v / i2v / restyle / extend. generate_audio on create_video. Fetch a model's prompting guide before generate.
create_video, edit_video, extend_video, list_video_models, get_prompting_guide - ffmpeg (ffmpeg): One-file ffmpeg (free).
video_precision - timeline (timeline): Reels, titles, xfade, compile.
create_video_frame, preview_video_frame, export_video_frame, get_export - captions (captions): Speech-synced burn. Scribe is this tool — no transcribe tool.
caption_video - blocking (blocking): Gray-box rehearsal, then shoot.
block_scene, wait_for_blocking, blocking_to_video - motion (motion): HTML motion graphics (HyperFrames).
create_motion_project, render_motion_project, motion_video - audio (audio): VO, beds, Foley, scores; mix.
generate_speech, design_voice, clone_voice, generate_music, compose_score - brand (brand): Kits, logo file, fonts.
import_brand_kit, apply_brand_logo, apply_brand_text - skills (skills): Install, apply, author.
list_skill_gallery, install_skill, apply_skill - plans (plans): Campaigns + reviews.
create_plan, wait_for_plan, answer_plan_review - research (research): Ad Library → board. best_performing = impressions, not ROAS.
search_facebook_ads, list_advertiser_ads, search_ad_advertisers - assets (assets): Library + Swipe.
search_assets, update_asset, list_asset_tags, save_to_swipe - elements (elements): Recurring cast.
list_elements, create_element - downloads (downloads): https url + filename.
download_images, export_blocking
Cursor
Click Add to Cursor, or let the skill merge ~/.cursor/mcp.json after magic-link signup. PAT-first (no OAuth prompt):
{
"mcpServers": {
"photospeak": {
"type": "http",
"url": "https://photospeak.net/api/mcp",
"headers": {
"Authorization": "Bearer ${env:PHOTOSPEAK_TOKEN}"
}
}
}
}
If Cursor still offers Connect, Allow once — the magic link already signed the browser in. OAuth is the fallback, not the default.
Claude Code
claude mcp add --transport http photospeak https://photospeak.net/api/mcp --header "Authorization: Bearer $PHOTOSPEAK_TOKEN"
Or in .mcp.json / ~/.claude.json — type is required (a URL-only entry is treated as stdio and skipped):
{
"mcpServers": {
"photospeak": {
"type": "http",
"url": "https://photospeak.net/api/mcp"
}
}
}
Inside Claude Code run /mcp, pick photospeak, and sign in. Or claude mcp login photospeak.
Codex
codex mcp add photospeak --url https://photospeak.net/api/mcp codex mcp login photospeak
Or in ~/.codex/config.toml:
[mcp_servers.photospeak] url = "https://photospeak.net/api/mcp" bearer_token_env_var = "PHOTOSPEAK_TOKEN"
Headless: the magic-link wait returns a psp_live_… PAT. Store it as PHOTOSPEAK_TOKEN. You can also mint a token on My account.
Claude Desktop, VS Code, Windsurf
Same URL: https://photospeak.net/api/mcp. Use Streamable HTTP / remote MCP. Complete the browser login when prompted.
VS Code / Claude Desktop:
{
"servers": {
"photospeak": {
"type": "http",
"url": "https://photospeak.net/api/mcp"
}
}
}
Claude Desktop uses mcpServers instead of servers, with the same type + url object.
Examples
- New board + 4-up: create_board → set_board_model → create_image (num_images: 4)
- Upload then edit: upload_image (https URL or base64) → edit_image
- Push a Cursor file into the library: upload_asset (image_base64) → add_asset_to_board
- Analyze a video URL: upload_video (video_url) → wait_for_video → get_video_analysis. inspect_video for a live Gemini question.
- Large local video: mint_video_upload → HTTP PUT put_url → register_video_upload → wait_for_video (no webcam; no file://)
- Import a reel or ad: import_social_url (Instagram / Facebook Ad Library) → get_video_analysis
- Bring a still to life: upload_image or create_image → create_video → wait_for_video. Persist the board video model with set_board_video_model.
- Timeline reel: create_video_frame (clip_ids) applies fade (Dissolve) between visuals unless transition_type is cut — photospeak://transitions → add_video_track / update_video_track → get_video_frame → update_video_frame_clip (trim / speed / z_index / transition_type) → add_video_frame_clip (text) → export_video_frame
- Speech captions: caption_video (Scribe is inside this tool; presets on photospeak://caption-presets) → get_video_frame → preview_video_frame → export_video_frame → wait_for_video({ export_id })
- FFmpeg on one file: video_precision (trim, speed, reverse, loop, mute, concat, add_audio, …). Clip-to-clip transitions are on the timeline, not this tool.
- Cancel: cancel_video or cancel_blocking only while generating / running
- Undo a delete: delete_item (confirm) returns restore_snapshot → restore_item
- Import a brand: import_brand_kit → apply_brand_logo / apply_brand_text
- File a character, then reuse: create_element (name + image_ids) → later create_video / edit_image with element_ids. list_elements first; do not invent el_N.
- Block then shoot: block_scene → wait_for_blocking → blocking_to_video
- Precision then cutout: precision_edit → remove_background
- Undo: list_revisions → revert_item
- Brand: list_brand_kits → apply_brand_logo
- Skill: list_skill_gallery → install_skill → apply_skill
- Models: list_models / list_video_models (speed / cost / quality / credits)
Tool catalog
| Tool | Scope | What it does |
|---|---|---|
list_boards | mcp:read | List the user's Photo Speak boards (canvases), most recently edited first. |
create_board | mcp:write | Create a new Photo Speak board (canvas workspace). |
switch_board | mcp:write | Point this agent session at an existing board. The human's live tab follows. Call list_boards first. create_board already follows the new board. |
rename_board | mcp:write | Rename a board. |
set_board_model | mcp:write | Set the image model for a board. Call list_models first if the user cares about speed, price, or quality. |
set_board_video_model | mcp:write | Set the VIDEO model for a board (H3 Max, H3 Lip Sync, Omni Flash, Seedance 2.5, Flux 3, …). Call list_video_models first. create_video / extend_video / block_sc |
delete_board | mcp:write | Permanently delete a board and its canvas. Requires confirm: true. |
get_board | mcp:read | Board metadata plus a compact canvas snapshot. On large boards use list_items / get_item instead of dumping every card. |
update_item | mcp:write | Patch a canvas card: move/resize, z-order, hide, nest in a frame, group, rewrite a note's Markdown (content), or restyle a note/frame (label, fill, color, prese |
update_items | mcp:write | Hide or show several canvas cards in one update. Pass item_ids and/or image_ids (img_N). Missing ids and cards on other boards are ignored. |
get_canvas | mcp:read | Read a compact snapshot of everything on a board. Large research+prod boards: list_items({ type, prefix, since }) and get_item(img_N). |
list_models | mcp:read | List enabled image models with speed, cost, quality ratings, approx credits, capabilities (including transparent PNG when the fal schema advertises it), and mem |
list_video_models | mcp:read | List enabled VIDEO models with per-second credit costs, per-mode capabilities (text-to-video, image-to-video, reference-to-video, edit, extend), and the full op |
upload_video | mcp:write | Upload a VIDEO (or audio) onto a board from a public https URL or base64 (mp4/webm/mov; base64 capped ~25MB). Local files larger than ~25MB: mint_video_upload → |
wait_for_video | mcp:read | Block until a video finishes generating/processing, or a timeline export finishes. Pass video_id (img_N) after create_video, or export_id after export_video_fra |
get_export | mcp:read | One-shot poll of a timeline export. Returns {status, video_id, error}. Prefer wait_for_video({ export_id }) to block. |
wait_for_audio | mcp:read | Block until generated speech/music/sfx or a composed score finishes. Pass audio_id (img_N) after generate_speech/music/sfx, or score_id after compose_score. |
wait_for_music_analysis | mcp:read | Turned off. Do not call. Music analysis is disabled until drop detection is accurate. |
cancel_audio | mcp:write | Cancel in-flight generate_speech / generate_music / generate_sfx or compose_score. Only while status is generating. Never charged. |
list_audio_models | mcp:read | List enabled AUDIO models (TTS, music, SFX, Foley) with kind, default flag, capabilities, and unit pricing. has_prompting_guide means call get_prompting_guide b |
list_voices | mcp:read | Named TTS voices plus designed and cloned voices. direction explains Gemini lines, style, and sound markers. |
list_items | mcp:read | Compact board index. Filter by type (image/video/note/video_frame/frame), label prefix, or items newer than since (ISO or img_N). Use instead of get_board on la |
get_item | mcp:read | Read one canvas card. Pass img_N or item_id. Notes return full Markdown (format: markdown). |
wait_for_analysis | mcp:read | Block until Gemini finishes indexing a ready video (or times out). wait_for_video ready ≠ analysis ready. |
list_revisions | mcp:read | List the version history for a canvas image card. |
revert_item | mcp:write | Revert a card to an earlier image version (same as History rail). |
delete_item | mcp:write | Remove a card from the board. Requires confirm: true. Returns restore_snapshot — pass that object to restore_item to undo. |
upload_image | mcp:write | Upload an image onto a board from a public https URL or base64 bytes. For a local Cursor file, base64 the image and pass image_base64 — file:// paths cannot be |
list_skills | mcp:read | List owned and installed skills, including markdown recipes. |
get_skill | mcp:read | Read one skill's full markdown content, images, and flags. |
create_skill | mcp:write | Create an owned skill (name, description, markdown content). |
update_skill | mcp:write | Edit an owned skill. Installed gallery skills are read-only — duplicate_skill first. |
delete_skill | mcp:write | Delete an owned skill. Requires confirm: true. |
list_skill_gallery | mcp:read | Browse public / official skills you can install. |
install_skill | mcp:write | Install a public gallery skill (read-only until duplicated). |
uninstall_skill | mcp:write | Remove an installed gallery skill from this account. |
duplicate_skill | mcp:write | Fork a viewable skill into an owned, editable copy. |
publish_skill | mcp:write | Publish or unpublish an owned skill to the gallery. |
unpublish_skill | mcp:write | Remove an owned skill from the public gallery. |
add_skill_image | mcp:write | Attach a reference image to an owned skill from an https URL. |
remove_skill_image | mcp:write | Remove a reference image from an owned skill. |
list_brand_kits | mcp:read | List the user's brand kits. |
get_brand_kit_detail | mcp:read | Full brand kit: colors, fonts, assets, voice. |
create_brand_kit | mcp:write | Create an empty brand kit. |
delete_brand_kit | mcp:write | Delete a brand kit. Requires confirm: true. |
duplicate_brand_kit | mcp:write | Duplicate a brand kit. |
update_brand_kit | mcp:write | Rename a brand kit, update its voice, or set it as the default kit (is_default). |
delete_element | mcp:write | Delete a character/location/product/prop. Requires confirm: true. Does not delete library files. |
get_asset | mcp:read | Read one media-library asset. Pass asset_id or the canvas image_id (img_N) that was mirrored into the library. |
list_asset_tags | mcp:read | Every tag in this user's library with usage counts. Call before search_assets when you do not know the vocabulary (character, product, opening, …). |
upload_asset | mcp:write | Push an image, video, or audio file into the Assets library. Pass tags/name/notes to file it for later search_assets. Default is NOT on the board (add_to_board |
add_asset_to_board | mcp:write | Place a library asset onto a board as a new image card. |
search_assets | mcp:read | Search the media library by text and/or tags. Hits include tags, notes, prompt, source_image_id (img_N), and swipe provenance. Pass swipe true to browse the Swi |
get_account | mcp:read | Account email, credits, subscription, default board, and onboarding profile (name, industry, business) for a personal first still. |
list_credit_ledger | mcp:read | Recent credit history (last 50 rows). |
claim_pairing | mcp:read | Bind this agent to the in-app Connect Agent session using the pairing code from the Photo Speak website. |
photospeak_help | mcp:read | Start here. Default overview = atlas + decision tree. Call practice for operating rules, captions for speech-synced Scribe burns, catalog for the full name list |
mint_video_upload | mcp:write | Step 1 of a large VIDEO/audio upload (up to 512MB). Returns a presigned PUT URL. HTTP PUT the raw bytes to put_url with the same Content-Type, then call registe |
register_video_upload | mcp:write | Step 2 after mint_video_upload: register the S3 object you PUT. Places the video on the board, probes it, and auto-analyzes. Returns video_id. |
duplicate_item | mcp:write | Duplicate a canvas card (image, video, note, or frame with nested children). The copy lands beside the original. |
restore_item | mcp:write | Restore a card deleted via delete_item. Pass the restore_snapshot object that delete_item returned. |
list_item_comments | mcp:read | List comments on a canvas card. |
create_item_comment | mcp:write | Add a comment on a canvas card. |
update_item_comment | mcp:write | Edit one of your comments. |
delete_item_comment | mcp:write | Soft-delete one of your comments. |
delete_asset | mcp:write | Delete library assets. Requires confirm: true. |
update_asset | mcp:write | Patch a library asset name, notes, or tags. Pass asset_id or image_id (img_N). tags replaces the list; add_tags merges (keeps analysis tags). Creates the mirror |
import_brand_kit | mcp:write | Scrape a website and create a brand kit from its colors, fonts, and logos. |
reapply_brand_kit | mcp:generate | Re-run recorded brand applications on the CURRENT kit (logo swap / color refresh). Pass application_ids from get_brand_kit_detail. Spends credits when restyles |
add_brand_color | mcp:write | Add a color swatch to a brand kit. |
update_brand_color | mcp:write | Update a brand kit color. |
delete_brand_color | mcp:write | Remove a color from a brand kit. |
add_brand_font | mcp:write | Add a font role (headline, body, …) to a brand kit. |
update_brand_font | mcp:write | Update a brand kit font role. |
delete_brand_font | mcp:write | Remove a font role from a brand kit. |
add_brand_asset | mcp:write | Upload a logo/photo into a brand kit from a public https URL or base64 image. |
update_brand_asset | mcp:write | Rename or reclassify a brand kit asset. |
delete_brand_asset | mcp:write | Remove an asset from a brand kit. |
upload_brand_font | mcp:write | Upload a custom TTF/OTF font for this account (URL or base64). Then add_brand_font with custom_font_id to attach it to a kit. |
list_fonts | mcp:read | Catalog of built-in fonts for text_layer (name, id, category, weights). Use list_brand_fonts for uploaded TTF/OTF files. |
list_brand_fonts | mcp:read | Custom TTF/OTF fonts uploaded to this account. |
wait_for_blocking | mcp:read | Block until a blocking (pre-viz) finishes building (or times out). Convenience long-poll after block_scene / revise_blocking. Returns the step list, summary and |
get_blocking | mcp:read | Everything about a blocking: the Director's summary + assumptions, per-generator prompts, marks/lens/camera metadata, versions, and presigned URLs for the refer |
blender_op | mcp:generate | ADVANCED: run one raw runtime op on a blocking's 3D scene yourself (any op from the Blocking catalog: scene_info, add_mannequin, set_marks, camera_move, render_ |
blocking_render | mcp:generate | Render a NEW version of a blocking from the scene as it is now (after blender_op edits): clean reference video + stills + diagram + glb + package, placed on the |
blocking_close_session | mcp:write | Release a blocking's GPU sandbox now (it otherwise idles out on its own). Saves credits when you are done iterating. |
wait_for_motion | mcp:read | Block until a motion graphic finishes rendering (or times out). Convenience long-poll after render_motion_project / motion_video / revise_motion_video. |
wait_for_plan | mcp:read | Block until a plan needs you (question / acceptance / review) or finishes. Pass since_event_seq to avoid spinning. Default 120s, max 240s. |
list_plan_reviews | mcp:read | Pending plan reviews across all boards for this user. |
answer_plan_review | mcp:write | Answer the pending plan review. Spend-unlocking decisions (approve/continue/retry/resume) require mcp:generate. Questions, changes, and stop only need mcp:write |
create_image | mcp:generate | Generate brand-new images from a text prompt ONLY. If the user referenced ANY existing canvas image — a style guide, template, person, product, 'that photo' — d |
edit_image | mcp:generate | Use whenever ANY existing canvas image is involved: modifying it, combining several, putting words ON a photo when they asked ("add SALE", "headline this", "put |
revert_edit | mcp:write | Rewind a canvas image to an earlier version ("undo that", "go back", "use the version before"). Every edit is kept in history, so reverting is instant and loses |
organize_canvas | mcp:write | Tidy the canvas: arrange all visible images into a clean, evenly-spaced grid and bring everything into view. Use for "clean up my canvas", "organize this", "tid |
focus_image | mcp:read | Pan/zoom the user's view to an image ("focus on X", "zoom in on that", "show me the bugatti"). Omit image_id to zoom out and show the whole canvas ("show everyt |
save_skill | mcp:write | Save a reusable editing skill from what was just done ("save that as a skill", "remember this look as X"). Write the instructions so ANY future image can get th |
apply_skill | mcp:generate | Fetch a saved skill ("use/apply the X skill") and get its instructions. After calling this, FOLLOW the returned instructions immediately. Visual style skills us |
precision_edit | mcp:write | MECHANICAL pixel-exact operations the user EXPLICITLY asked for. Instant, free, never regenerates pixels. Ops: crop_to_selection (needs drawn rect); rotate (deg |
download_images | mcp:read | Save image/video/audio files. Instant, free, does NOT change canvas pixels. Returns agent-fetchable https URLs (url + filename) so MCP clients can HTTP GET the |
rename_images | mcp:write | Rename canvas images — the name on the card, Layers panel, and downloads. Instant, free, does NOT change pixels. Use for "rename this to Hero Shot", "call these |
remove_background | mcp:generate | Remove the background from an EXISTING photo, leaving the subject on transparency (cheap PNG cutout, any model). Use for "remove the background", "cut it/her/hi |
layerize_image | mcp:generate | Split an image into independent transparent-PNG layers (background + each element) using Seedream Layerize. Use for "layerize this", "split into layers", "separ |
create_svg | mcp:generate | Generate a new SVG (vector icon, logo, illustration) from a text prompt via Quiver Arrow. Use for "make an SVG", "vector icon", "logo as SVG". NOT for photoreal |
convert_to_svg | mcp:generate | Vectorize an EXISTING still into an SVG via Quiver Arrow. Use for "convert to SVG", "vectorize this", "make this a vector". Replaces the card (history stays). N |
text_layer | mcp:write | LAST RESORT live type on an image card or FRAME artboard. Default is bake headlines/captions with create_image / edit_image — image models render type well. Use |
sticker_layer | mcp:write | Place one canvas image ON another card as a live, movable STICKER — a design layer (like text) the user can drag, resize, rotate, restack, hide, or delete. Use |
shape_layer | mcp:write | Add or edit geometric SHAPE layers on an image card or FRAME — rectangles, ellipses, triangles, lines, stars, arrows. Free, instant; shapes stay live (move/resi |
apply_ink | mcp:generate | Run the user's drawing. Ink on an image card EDITS that photo (result replaces the card). Ink on a frame is a sketch → creates a NEW image from the flattened ar |
ink_layer | mcp:write | Clear, hide, show, or undo the last ink stroke on an image card or frame. Voice cannot draw — this only manages existing ink. To run the drawing use apply_ink. |
group_layers | mcp:write | Organize canvas layers into named groups (folders). Prefer create_group({ name }) for an empty folder and add_to_group for any canvas refs (img_N, note_N, vfram |
create_group | mcp:write | Create a named canvas group (folder) with zero members. Then add_to_group. Prefer this over group_layers create when you do not have image_ids yet. |
add_to_group | mcp:write | Add any canvas cards to a group — img_N, note_N, vframe_N, or item_id. Not images-only. |
scrape_webpage | mcp:write | Scrape a webpage for design reference. Modes: "screenshot" (full-page capture), "branding" (colors, fonts, logos), "images" (all page images onto canvas in a si |
create_note | mcp:write | Required field is content (Markdown). Also accept title / body — joined as "# title" plus body. Create a sticky note on the canvas. Use for reminders and text t |
update_note | mcp:write | Rewrite or append Markdown on an existing sticky note. Pass note_id (note_N from [canvas]). Use for "change the note", "add to that note", "make note_3 pink". N |
create_frame | mcp:write | Create a blank FRAME on the canvas — a resizable artboard. Use for "add a frame", "make a story frame", "iPhone screenshot canvas". Pass preset or export_width/ |
placeholder_layer | mcp:write | IMAGE PLACEHOLDER slots on a frame or image card — empty dashed boxes you drop a photo into. The photo fills the slot (cover or contain). Use for App Store scre |
create_template | mcp:write | Low-level layout builder: sized frames with branded backgrounds, type, and image PLACEHOLDERS. app_store = iPhone 6.9" (1320×2868) + iPad 13" (2064×2752) rows. |
import_social_url | mcp:write | Import media from a social URL onto the canvas: Facebook Ad Library link (images AND ad videos), Instagram post/reel (photos, carousels, and reel VIDEOS — the a |
search_images | mcp:write | Search the web for a specific real photo (a particular car, product, place, or news shot) and import it onto the canvas. Not for generic stock, lifestyle, textu |
search_unsplash | mcp:write | Search Unsplash for licensed stock photos and import them onto the canvas. Use for lifestyle, textures, backgrounds, and generic scenes — not a specific real-wo |
search_facebook_ads | mcp:write | Search the Facebook Ad Library and put matching ads on the board as usable stills/videos (default). Default sort is best_performing (highest Ad Library impressi |
search_ad_advertisers | mcp:write | Disambiguate a brand in the Facebook Ad Library (page_id, name, category). Does not place media. Then call list_advertiser_ads with the right page_id to put tha |
list_advertiser_ads | mcp:write | Load a brand's Facebook Ad Library ads and put them on the board (default). Same sorts as search_facebook_ads: best_performing (default, impression rank — not R |
import_facebook_ads | mcp:write | Import specific Facebook Ad Library ads onto the board by archive id or ads/library URL. Always places media (download to S3). Auto-files them in Swipe. Always |
inspect_image | mcp:read | Look at a still (or carousel siblings) RIGHT NOW with Gemini 3.8 Flash and answer a specific question. Use when you need on-screen text, layout, or product deta |
analyze_image | mcp:write | Rebuild the stored Gemini 3.8 Flash creative analysis for a still in the background (hook, layout, offer, remix notes). Auto-runs on swipe; call this to re-run. |
get_image_analysis | mcp:read | Read the stored Gemini creative analysis for a still (hook, layout, offer, remix notes). Swipe stills are analyzed automatically. If pending, wait and retry. Us |
save_to_swipe | mcp:write | Bookmark canvas cards or library assets into Swipe (the inspiration collection inside Assets). Starts Gemini creative analysis if missing. Does not copy pixels. |
remove_from_swipe | mcp:write | Remove assets from Swipe. Does not delete the files — they stay in the library. Clears swiped_at only — does not delete the library file. |
upscale_image | mcp:write | Upscale an image to higher resolution with AI (SeedVR). Free — no credits. Use for "upscale", "higher resolution", "make it print-ready", "4K version". Mechanic |
get_brand_kit | mcp:read | Fetch the full contents of one of the user's brand kits (every color with hex + role, every font role, every logo/photo asset, the brand voice). Use when the ro |
apply_brand_logo | mcp:write | Stamp the user's saved brand logo onto an image — "add my logo to this", "put the CarShots logo bottom right", "watermark these with my logo". Composites the ac |
apply_brand_style | mcp:generate | AI-restyle an image with the user's brand kit — "update this using my brand colors", "make it match the CarShots brand", "make this on-brand". Builds the edit f |
apply_brand_text | mcp:write | Restyle existing LIVE text layers to the user's brand fonts/colors — "make the text on-brand", "use my brand font on the title", "brand colors on that caption". |
save_to_brand_kit | mcp:write | Save something into the user's brand kit — "add this color to my brand kit" (pass hex), "save this image as my logo" (pass image_id + asset_kind), "set my brand |
create_video | mcp:generate | Generate a VIDEO on the canvas's selected video model (default H3 Max). If the selected or named video model has a prompting guide, call get_prompting_guide onc |
get_prompting_guide | mcp:read | Fetch the admin markdown prompting guide for a video or audio model. For video, omit model to use the board selection and write create_video from the guide. For |
edit_video | mcp:generate | Edit an existing VIDEO. Word edits (restyle, add/remove objects) use the selected model's edit slot. Replacing the people in a finished clip with other faces is |
extend_video | mcp:generate | Continue a READY video: add new footage after the source from a prompt that describes what happens NEXT (not a restyle — that is edit_video). Uses the selected |
grab_video_frame | mcp:write | Extract one exact frame from a video as a full-resolution IMAGE card placed beside it. Use when the user wants a still/thumbnail/screenshot from a video at a mo |
get_video_analysis | mcp:read | Read the stored AI analysis of a video: scene-by-scene descriptions WITH timestamps, subjects, quotes, wardrobe, brands, spoken content, and tags. Every video i |
inspect_video | mcp:read | Re-watch a video RIGHT NOW with Gemini agentic understanding and answer a specific question. Use when the stored analysis is not enough — exact quotes, on-scree |
analyze_video | mcp:write | (Re)build the stored deep AI index on a video — dense scenes, quotes, wardrobe, brands, tags. Videos are analyzed automatically on arrival; use this only when t |
detach_audio | mcp:write | Split a video's soundtrack into a separate AUDIO asset (MP3 in the asset library, usable as a timeline audio clip in Video Frames). Optionally also produce a mu |
video_precision | mcp:write | FREE deterministic ffmpeg operations on a video (no AI, exact): trim (cut a time range), speed (0.25x-4x), reverse, loop, mute, volume, fade (in/out), resize, c |
create_video_frame | mcp:write | Create a VIDEO FRAME — a timeline artboard on the canvas for assembling videos: stack video clips, images, text overlays, and audio on tracks, preview live, the |
get_video_frame | mcp:read | Read a video frame's full timeline: tracks (volume, locked, order, hidden, muted, duck), clips (ids, z_index, timings, trims, speeds, volume, fades, audio_role, |
add_video_frame_clip | mcp:write | Add a clip to a video frame's timeline: a canvas video/image/audio (by img_N) OR a text overlay. Audio without track_id uses a lane named Score / SFX / VO / Mus |
update_video_frame_clip | mcp:write | Move, trim, retime, restyle, or set a transition on one timeline clip (position, duration, source trim-in, speed 0.25-4, volume, mute, fade in/out, audio_role / |
split_video_frame_clip | mcp:write | Cut one timeline clip into two at a timeline second (like pressing S at the playhead). Both halves keep source trims consistent. |
remove_video_frame_clip | mcp:write | Remove one clip from a video frame's timeline. |
export_video_frame | mcp:write | Compile a video frame's timeline into ONE MP4 (ffmpeg render: cuts, overlays, text, mixed audio), or with format mp3 / wav into a mixed audio file with no pictu |
preview_video_frame | mcp:write | Render one PNG of the timeline at at_sec with the same libass captions the export will burn. Use after adding/updating text — do not wait for a full MP4 to see |
add_video_track | mcp:write | Add a VIDEO / OVERLAY / AUDIO track to a video frame timeline. Use when assembling a multi-track reel (music bed, titles lane, B-roll) or when a score and SFX m |
update_video_track | mcp:write | Patch a video-frame track: name, mute, volume 0–2, lock, hide, reorder, or duck under speech / another track. name / muted / volume / locked / hidden / order / |
delete_video_track | mcp:write | Delete a video-frame track and its clips. The frame must keep at least one track. Frame must keep at least one track. |
update_video_frame | mcp:write | Patch a video frame artboard (label, preset, export size, fps, background, audio_ducking) and/or batch-update clips in one resolve. Pass clips[] for trims/moves |
promote_video_to_frame | mcp:write | Create a Video Frame timeline beside an existing video card, with that video as the first clip. The original card stays. Pass video_id (img_N) or item_id. Pass |
caption_video | mcp:write | ONLY when they asked for captions / subtitles / burned speech text on screen. Talking or VO does not auto-need this. Burns speech-synced captions onto a Video F |
cancel_video | mcp:write | Cancel a VIDEO that is still generating. Only works while status is generating. Never charged. Do not use after the card is ready. Only while status is generati |
cancel_blocking | mcp:write | Cancel a blocking (pre-viz) job that is still queued or running. Pass the blocking card's img_N. GPU work stops; the card is marked cancelled. Only while the jo |
generate_speech | mcp:generate | Voiceover, dialogue, or narration. If list_audio_models marks has_prompting_guide for the TTS model, call get_prompting_guide once and write the text from that |
design_voice | mcp:generate | Create a reusable voice from a one or two sentence description (not a recording). Uses the admin engine: Eleven v4 on fal, or Gemini 3.8. Blocks until saved. Pa |
clone_voice | mcp:generate | Clone a real person's voice on Gemini 3.8 Flash TTS. Requires consent: true, consent_name, a reference recording, and a recording of Google's consent sentence. |
generate_music | mcp:generate | Generate a music bed as a canvas audio card (default Lyria 3 Pro). If list_audio_models marks has_prompting_guide, call get_prompting_guide once and write the p |
generate_sfx | mcp:generate | Generate sound effects from text, or video-synced foley when video_id is set. If list_audio_models marks has_prompting_guide, call get_prompting_guide once and |
compose_score | mcp:generate | Compose a timed, non-vocal synth score that hits the moments in a video or Video Frame. Use when the user wants music that MATCHES the cut ('score this', 'hit t |
revise_score | mcp:generate | Edit an existing timed score in place (move a hit, change intensity) without rewriting from scratch. Edits an existing score. wait_for_audio({ score_id }). |
get_score | mcp:read | Read a timed-score job: status, steps, summary, cue notes, loudness report, and a URL for the Score JSON. Poll status / summary / warnings. Prefer wait_for_audi |
analyze_music | mcp:write | Turned off. Do not call. Music analysis is disabled until drop detection is accurate. |
get_music_analysis | mcp:read | Turned off. Do not call. Music analysis is disabled until drop detection is accurate. |
get_music_markers | mcp:read | Turned off. Do not call. Music analysis is disabled until drop detection is accurate. |
inspect_music | mcp:read | Turned off. Do not call. Music analysis is disabled until drop detection is accurate. |
update_music_markers | mcp:write | Turned off. Do not call. Music analysis is disabled until drop detection is accurate. |
snap_clips_to_music | mcp:write | Turned off. Do not call. Music analysis is disabled until drop detection is accurate. |
block_scene | mcp:generate | BLOCK A SCENE: build a low-fidelity 3D pre-viz ("blocking") of a shot — gray stand-ins for people/props on a simple set, choreographed marks, a real camera move |
revise_blocking | mcp:generate | Change an existing blocking ("lower the camera", "make it a slow crane instead", "add a second person on the left", "make it 8 seconds"). Produces a new version |
blocking_status | mcp:read | Where a blocking is: current step, step list, versions, artifacts. Only when the user asks how it is going — the card already shows live progress. |
blocking_to_video | mcp:generate | MAKE IT REAL: generate the actual video from a blocking, using the canvas's selected video model (H3 Max default; Omni Flash or Seedance 2.5 if selected/named). |
export_blocking | mcp:read | Download a blocking artifact: the reference video (mp4), the 3D scene (glb), the editable scene file (blend), the top-down blocking diagram (png), the first/las |
submit_product_feedback | mcp:write | Send a product report to the Photo Speak team (bugs, something broken, missing features, UX). Use when the user reports a problem / asks to send feedback, or wh |
list_elements | mcp:read | List saved characters, locations, products, and props (the Cast). Call this before inventing a name. Each row is el_N with kind, look counts, and bound TTS voic |
get_element | mcp:read | Read one element's bible (bio, story, profile), looks by role, bound TTS voice, voice clip, and recent appearances. Use before generating so you reuse identity |
create_element | mcp:write | File a reusable character, location, product, or prop. Kind defaults to character. Pass image_ids of look stills on this board (or asset_ids from the library). |
update_element | mcp:write | Edit an element's bible, aliases, TTS voice, or kind. Does not change pixels. Edit bible, aliases, or tts_voice (catalog name or designed voice_id). Not pixels. |
attach_element_asset | mcp:write | Link a library asset or a board still (img_N) to an element as a look, face, wardrobe, voice clip, etc. First look becomes the hero. Tags the asset so search_as |
detach_element_asset | mcp:write | Unlink one look/clip from an element. Does not delete the library file. Unlink one look. Does not delete the library file. |
create_contact_sheet | mcp:generate | Generate a standardized multi-view contact sheet (model sheet) for a CHARACTER with Sunburst: front/3-4/profile/back, face close-ups, expressions, poses in one |
regenerate_contact_sheet | mcp:generate | Re-run an existing contact sheet (same label, standard spec) for a fresh take. Pass evolution_notes / look / rows / cols to change the spec first. The previous |
register_contact_sheet | mcp:write | Register an image you already have (image_id img_N or asset_id) as a character's contact sheet, with no generation and no cost. It shows in list_contact_sheets |
list_contact_sheets | mcp:read | List a character's contact sheets (one per era): label, look, grid, status, which is the default, and whether the character changed since it was generated. Shee |
set_default_contact_sheet | mcp:write | Choose which contact sheet is this character's identity reference for element_ids on generate tools (e.g. switch to the older-era sheet). Pick the sheet element |
delete_contact_sheet | mcp:write | Remove one contact sheet from a character. The images stay in the library. If it was the default, another sheet is promoted. Removes the sheet row; library imag |
place_element_on_board | mcp:write | Drop an element's look stills onto the current board as new cards. Default roles are the identity refs (look/face/body for a character). Drop look stills onto t |
create_motion_project | mcp:write | Create a HyperFrames motion-graphics project from HTML (or a starter title card). Pass image_ids to pack canvas stills into the zip (assets/img_N.jpg) and files |
update_motion_project | mcp:write | Replace the HTML (or files) on an existing motion card. Creates a new version on the SAME card. Then render_motion_project. Replace HTML on the same card. Then |
edit_motion_project | mcp:write | Revise a motion project without resending HTML. Ops: setText, setStyle, setTiming, setVariable, setVariables, setMeta (HyperFrames SDK-compatible). Then render_ |
check_motion_project | mcp:read | Preflight a motion composition: HyperFrames lint now, then the browser gate in the background (runtime errors, layout, motion assertions, empty frames, seek-ord |
snapshot_motion_project | mcp:write | Render a still poster (the most detailed preflight frame of the first scene) in the media sandbox, HeyGen Cloud as fallback. Free. Free poster still. |
render_motion_project | mcp:write | Render the motion card to MP4 (or webm) with HyperFrames: the media sandbox by default, HeyGen HyperFrames Cloud as fallback. The preflight gate runs first and |
batch_render_motion | mcp:write | Variable-driven batch render: same HTML, one HeyGen Cloud MP4 per row of variables. Returns a zip on the card. Free at default credits. One HTML, many variable |
get_motion_project | mcp:read | HTML, variables, versions, and job status for a motion card. HTML + versions + job. |
list_motion_projects | mcp:read | Motion projects on this board. Projects on this board. |
search_motion_catalog | mcp:read | Search the pinned HyperFrames catalog (blocks and components: name, type, description, tags). Returns no HTML. Then add_motion_block with one id. Search the pin |
add_motion_block | mcp:write | Fetch one catalog item into a motion project. A block is saved under compositions/blocks and mounted with data-composition-src. A component is saved as a file w |
motion_video | mcp:generate | MOTION DIRECTOR: write HyperFrames HTML from a brief and render it. Use for designed/kinetic type, lower-thirds, charts, title cards when the user did not suppl |
revise_motion_video | mcp:generate | Revise an existing motion graphic from a note ("make the headline red", "shorter"). Director writes a new version on the SAME card. Returns immediately. Returns |
create_plan | mcp:generate | Draft a multi-step production plan as its own canvas card. Returns immediately with plan_id. Then wait (do not poll): the card asks questions / requests accepta |
get_plan | mcp:read | Read a plan by plan_id: markdown, steps, pending review + answer_schema, deliverables. Authorization is by plan owner, not the current board. Markdown + steps + |
list_plans | mcp:read | List this user's plans. attention:true = waiting on a human/agent answer. First call of any session: pick up where you left off. Cross-board for this user. Firs |
update_plan | mcp:write | Edit future steps, review toggles, cadence, or title. Creates a new version. Does not run steps. Edits future steps / cadence / title (new version). Does not ru |
pause_plan | mcp:write | Pause a running plan after current tool calls. Pause after current tool calls. Produced media stays. |
resume_plan | mcp:write | Resume a paused or blocked plan. Resume a paused or blocked plan. |
cancel_plan | mcp:write | Cancel a plan. Produced media stays. Nothing further is charged. Stop the plan. Produced media stays. Nothing further is charged. |
steer_plan | mcp:write | Add a note the director applies at the next wave (or mid-wave to the concerned subagent). Queue a note for the next wave. Do not run the steps yourself. |
check_script_continuity | mcp:read | Check a script for continuity errors: wardrobe, props, time of day, injuries, timeline, who knows what, plus unlinked speakers, characters with no voice and ele |
script_report | mcp:read | Production breakdown of a script: a strip per scene (INT/EXT, location, time of day, pages, estimated runtime, cast, props, unlinked speakers), cast/location/pr |
design_script_sound | mcp:generate | Plan the sound for one scene from its action lines and mood: one ambience bed, sound effects tied to the lines that call for them, and at most one music cue. Fo |
plan_script_pictures | mcp:write | AUDIO scripts: have an AI art director choose the moments of the story that deserve a picture and write each one's image prompt and cast (characters, location) |
plan_script_wardrobe | mcp:generate | Have an AI costume supervisor build each character's wardrobe chart across the whole story: which look they wear, the condition of their clothes (torn, soaked, |
design_script_voices | mcp:generate | Design a voice for the script's characters who have none, and bind it to each one. An AI voice designer writes each voice from the character's description, voic |
make_script_pictures | mcp:generate | AUDIO scripts: make the images for planned pictures that are missing or out of date, using the characters' and locations' looks as references. image_model picks |
time_script | mcp:write | AUDIO scripts: have the timing director set the spacing of a script: the silence before each line, sound and music block, overlaps and interruptions, how long b |
compile_script_timeline | mcp:write | Compile a script into its timeline: a Video Frame with the picture (video scripts: rendered video, else storyboard still, else a marked gap), every voiced line |
make_script_animatic | mcp:generate | Build a cheap animatic Video Frame: each shot's storyboard still held for its dialogue, with the voiced lines underneath. No video credits. Shots without a stor |
localize_script | mcp:generate | Make a translated copy of a script for dubbing: dialogue is translated by the script model, characters, voices, shots and storyboards carry over, and video with |
place_script_on_board | mcp:write | Put a script (or a range of its scenes) on the board as a script card. Cards on the board give the agent that script's text as context, so edits and generations |
list_scripts | mcp:read | List the user's screenplay scripts: script_ref (scr_N), title, logline, format, scene and dialogue counts. Scripts are their own library, separate from the boar |
get_script | mcp:read | Read a script. view outline (default): scenes with headings, moods, bound elements. full: every block with id, kind, speaker and binding (pass scene_refs to lim |
write_script | mcp:write | Hand a writing job to the Script Writer, a screenwriting model that reads the user's characters, locations and script itself and writes scenes with dialogue lin |
get_script_writer_job | mcp:read | Status of a write_script job: running, waiting (with the question the writer asked), done (with its summary and open questions), failed or cancelled. |
answer_script_writer | mcp:write | Answer the question a waiting write_script job asked, using what the user told you. Resumes the writer. |
edit_script | mcp:write | Edit a script with structured ops (insert_scene, insert_block, update_block, move_block, delete_block, bind_speaker, bind_scene_element, update_script for title |
import_script | mcp:write | Import a screenplay (Fountain, Final Draft XML, plain text) or prose into a script as scenes and blocks. Screenplays are copied verbatim; prose can be adapted ( |
export_script | mcp:read | Export a script as text: fountain, txt (typed layout), csv (one row per block), fdx (Final Draft XML) or srt (subtitles timed from voiced lines). For a PDF down |
voice_script | mcp:generate | Turn script dialogue into speech with each linked character's bound voice. An AI voice director adds the emotion tags that the character's TTS engine understand |
breakdown_script | mcp:write | Break scenes into shots for video: an AI director lists shots that cover every dialogue line, with framing, camera move, duration, the elements in frame, and a |
render_script_shots | mcp:generate | Render the video for shots. Pass shot_refs, scene_refs or neither (all missing shots). estimate_only returns credits per shot and total without spending. Each s |
assemble_script | mcp:write | Lay the rendered shots of a script on a new Video Frame in script order, with voice-over shots' audio on the VO lane and optional subtitles. Refuses when shots |
list_universes | mcp:read | List the user's story universes: id, name, logline, and how many works and cast members each has. Call this before creating a duplicate world. |
get_universe | mcp:read | Read one universe: canon rules, works in story order (series, seasons, episodes, films), cast billing, open threads, and how many canon facts are still waiting |
create_universe | mcp:write | Start a story universe: a world that groups series, seasons, episodes, and films, and keeps canon across them. Elements stay in the user's library and are added |
update_universe | mcp:write | Rename a universe, change its logline or overall arc (synopsis), or rewrite its canon rules. |
add_universe_work | mcp:write | Add a series, season, episode, film, short, or special to a universe. Episodes belong in a season or series. A script links only to an episode, film, short, or |
update_universe_work | mcp:write | Change a work's title, status, story date, parent, or linked script. status released means its facts are locked canon when you sync. story_order is the in-unive |
add_universe_member | mcp:write | Add a filed character, location, prop, or product to a universe. The element stays in the library and can belong to other universes too. billing is main, recurr |
record_canon_event | mcp:write | Record a fact the user is stating as canon (not a guess from a script): a death, a revelation, a relationship, a world rule. It is canon immediately. Use sync_w |
list_canon | mcp:read | List canon facts and story threads for a universe, in story order. status proposed means the fact was read from a script and is waiting for approval. status can |
approve_canon_event | mcp:write | Accept a proposed canon fact so later works and the writer treat it as established. |
retcon_canon_event | mcp:write | Withdraw a canon fact. Pass a replacement summary when the truth changed; omit it when the fact simply is no longer true. The old fact stays in the history as r |
sync_work_canon | mcp:write | Queue a canon sync for a work: the script is read in the background and compared with the canon already recorded for it. New facts are proposed (canon at once f |
add_script_to_universe | mcp:write | Add an existing script to a universe. The AI decides the work kind and where it sits (inside parent_work_id when you pass one), the script's characters and loca |
start_universe_from_scripts | mcp:write | Create a new universe from one or more existing scripts in one step. The AI reads the scripts and decides the universe name, logline and canon rules, which seri |
resolve_canon_withdrawal | mcp:write | Settle a canon fact that sync flagged as no longer supported by its script (proposed_action withdraw in list_canon). accept true retcons it; false keeps it as c |
list_canon_issues | mcp:read | List the places where a work's script clashes with canon: found when canon changed (ripple) or by a script continuity check. Each issue names the work, scene an |
resolve_canon_issue | mcp:write | Close a canon issue: resolved when the script was fixed, dismissed when it is not a real problem, open to reopen it. |
create_opening | mcp:write | Make an opening for a season, episode, film, short, or special: a theme of at most 15 seconds (exact length) and a title still painted from how the cast actuall |
revise_opening | mcp:write | Change an opening. part song writes a new theme (the previous one stays selectable). part keyframe repaints the title still; from_current edits the current pict |
attach_opening | mcp:write | Use an existing opening on another season, episode, or film. link shares it, so a later revision changes every work using it. copy keeps the song and can repain |
create_thread | mcp:write | Track a story thread: a mystery to solve, an arc to follow, or a setup that needs a payoff. Returns thread_id, which storylines in a break can refer to. |
update_thread | mcp:write | Change a story thread's title, kind, notes, or status (open, paid_off, dropped). |
delete_thread | mcp:write | Delete a story thread for good. To close one that was resolved, use update_thread with status paid_off or dropped instead. Ask the user first. |
reorder_works | mcp:write | Set the order of works. axis story is the in-universe order and must list every work in the universe, once. axis release orders the children of one parent (pare |
remove_universe_work | mcp:write | Remove a work from the universe. Its script, if it has one, stays in the user's library. A work that still has works inside it cannot be removed; remove or move |
update_universe_member | mcp:write | Change a cast member's billing (main, recurring, guest) or their canon notes. |
remove_universe_member | mcp:write | Take a character, location, prop, or product out of a universe's cast. The element stays in the library. Ask the user first. |
create_phase | mcp:write | Create a phase: a group of films and seasons that make one chapter or saga of the universe, with its own arc. Works join it with phase_id on add_universe_work, |
update_phase | mcp:write | Rename a phase, rewrite its arc, or move it in the order of phases (a smaller order comes first). |
delete_phase | mcp:write | Delete a phase. Its works stay in the universe and simply leave the group. Ask the user first. |
get_arc_board | mcp:write | Read the plan for one arc: its overall arc, the planned arc of each character, and every work in it in story order with its status, tentpole, logline, A/B/C sto |
break_arc | mcp:write | Break a story: set an arc and lay out its works, with no scripts written. Creates new works at status idea, or revises existing ones, in one call. Each work car |
set_character_arcs | mcp:write | Plan how characters change over an arc: where each starts and where each ends. Pass work_id for a series or season, phase_id for a phase, or neither for the who |
outline_works | mcp:write | Hand works to the Outliner, a background writer that turns each work's saved break into a skeleton script: a logline, the beats grouped by storyline, and scene |
get_outline_job | mcp:write | Status of an outline_works job: running (with which works are saved), done (with its summary and open questions), error or cancelled. Only check when asked or w |
cancel_outline_job | mcp:write | Stop a running outline job. Outlines it already saved are kept; the creator can undo them from the job card. |
Auth & safety
OAuth 2.1 + PKCE. Scopes: mcp:read, mcp:write, mcp:generate. Revoke apps and tokens on My account. We never see your Cursor or Claude keys.
Human docs live at /mcp. The protocol is /api/mcp — do not mix them up.
Connect Agent from the canvas
Signed in? Click Connect Agent on any board for install commands and a pairing code.