For agents and developers
Ask Claude for an ad. Or call it from code.
One pipeline behind three doors: a CLI, an HTTP API and an MCP server with seven tools. All of it ships in one Docker image that renders on CPU.
- Claude Code Works today
- Any MCP client Works today
- Cursor, VS Code Via MCP · untested
- ChatGPT app Coming soon
- Hosted API keys Coming soon
Claude Code · motiontyped MCP · scripted preview
- Make a 4:5 and a 9:16 ad for https://acme-inbox.example
- I'll run the MotionTyped pipeline on that URL.
- motiontyped · generate { "url": "https://acme-inbox.example", "aspects": ["4:5", "9:16"] }
- run 20261020-1737-a1b2
- motiontyped · get_run { "runId": "20261020-1737-a1b2" }
- Done. Two files in runs/20261020-1737-a1b2/:
4x5.mp4and9x16.mp4, 20 scenes, QA passed in both formats. Want me to regenerate the hook scene with a different angle?
Interfaces
Three doors, one pipeline.
# full pipeline: ingest → brand → storyboard → assets → render → QA
motiontyped generate https://example.com \
--brief "AI inbox for ecommerce brands" \
--style kinetic-serif --aspects 4:5,9:16 \
--qa full # or structural; --template forces the no-LLM path
# one stage at a time
motiontyped ingest https://example.com --out runs/x
motiontyped storyboard --run <id> --style punch-sans
motiontyped render runs/<id>/storyboard.json --aspect 9:16
motiontyped qa --run <id> --aspect 4:5
# edit one scene
motiontyped regenerate-scene --run <id> --scene s05 \
--instruction "lead with the pricing feature"
# clip templates
motiontyped template render chat-message-reveal --set headline="Replies in seconds."# the API serves the local web UI on the same port (8787)
POST /generate
{ "url": "https://example.com", "brief": "…", "aspects": ["4:5", "9:16"] }
→ 202 { "runId": "20261020-1737-a1b2", "status": "queued" }
GET /runs/:id # stage, progress, QA per aspect
GET /runs/:id/video/4:5 # the MP4, with Range support// .mcp.json (Claude Code picks this up inside the project)
{ "mcpServers": { "motiontyped": {
"command": "node",
"args": ["/abs/path/motiontyped/apps/mcp/dist/index.js"],
"env": { "ANTHROPIC_API_KEY": "sk-…" } } } }
# or register it for every directory
claude mcp add --scope user motiontyped -- node /abs/path/motiontyped/apps/mcp/dist/index.jsdocker build -t motiontyped .
docker run --rm -e ANTHROPIC_API_KEY=sk-… \
-v "$PWD/runs:/app/runs" \
motiontyped generate https://example.com
# API + local web UI on :8787
docker run --rm -p 8787:8787 -v "$PWD/runs:/app/runs" motiontyped apiFrom a source checkout, prefix commands with pnpm: pnpm motiontyped generate …. In Docker, the image runs the CLI directly.
MCP tools
Seven tools an agent can call.
| Tool | What it does |
|---|---|
generate | The whole pipeline from a URL; returns a run id |
get_run | Stage, progress, file paths and QA per aspect |
ingest_url | Scrape a site into product.json with sources and quotes |
generate_storyboard | Write and validate the storyboard for a run |
render_video | Render a storyboard to one or more aspects |
qa_video | Structural and vision QA for a rendered aspect |
regenerate_scene | Re-prompt one scene with an instruction and re-render only it |
Under the hood
Plain files, strict schemas.
Every stage is a pure function with its own CLI entry and writes into runs/<id>/. Nothing is hidden in a database.
- Node 22, TypeScript, pnpm workspaces, Remotion, Hono, zod
- Structured LLM output, validated by zod and semantic rules, re-prompted with the exact errors (max 3 tries)
- Works without an API key: template storyboard and structural QA
- Uses your Claude Code login when there is no key
- Self-hosted Firecrawl is supported; Playwright is the fallback
- Seeded randomness only: two renders give byte-identical frames, tested
- Local web UI: runs, live stage tracker, scene drawer, compare
Run it on your machine.
Docker, a key or a Claude Code login, and a URL.