Connect your AI
Give an agent the tools to write a script, render a frame, and look at what it made.
The fastest way to make a video with stingo is to not write one. Connect an agent, describe what you want, and let it write the script — then render a frame and look at it.
That last part is the whole reason this works. A model writing video it never
sees produces scripts that validate and read badly: a headline that wrapped, a
chart bar invisible against its background, a scene over before anyone could
read it. stingo_still returns the PNG itself, so the model can check.
#Connect it
Point your agent at the published package:
{
"mcpServers": {
"stingo": {
"command": "bunx",
"args": ["--bun", "--package=@hersidev/stingo", "stingo-mcp"]
}
}
}--package is needed because the binary and the package have different names:
npm would not accept stingo as a package name, so the library publishes under
a scope while the commands stay stingo and stingo-mcp.
Working in a clone of the repository instead? .mcp.json is already there and
Claude Code picks it up, no install required.
It speaks MCP over stdio. ffmpeg still has to be on the PATH.
AGENTS.md in the
repository is written for the agent itself — the loop that works, and the
mistakes worth not making (never put a colour in a script, do not set dur
first, look at frames).
#The loop it is built for
stingo_docs— read how a field actually behaves instead of guessingstingo_validate— catch schema errors instantlystingo_plan— check the pacing before spending minutesstingo_still— render one frame and look at itstingo_render— only once the frames read correctly
Steps 3 and 4 are the ones that matter. They cost a second or two and catch the things a schema cannot: a line too long for the frame, a chart whose highlighted bar is invisible, a scene that is over before it can be read.
#Tools
| Tool | |
|---|---|
stingo_docs |
fetch a documentation page as markdown |
stingo_blocks |
the registered scene types and what they take |
stingo_validate |
parse a script; report the resolved document or exact errors |
stingo_plan |
the resolved timeline, in seconds and in beats |
stingo_still |
render one frame, returned as an image |
stingo_render |
render the MP4 |
stingo_takes |
inspect camera takes: resolution, fps, length, audio |
stingo_beats |
tempo, downbeat, onsets, loudness of a track |
stingo_tastes |
list built-in taste profiles |
stingo_derive_taste |
derive a full profile from one brand colour |
stingo_audit_taste |
check a profile against the contrast floors |
Every tool that takes a script accepts either path (a file) or source
(inline YAML). Inline source is written to a scratch file inside baseDir, so
relative references — ./taste.json, takes/01.mp4 — resolve exactly as they
would on disk.
#Guards worth knowing
stingo_render refuses films longer than ten minutes unless you raise
maxSeconds deliberately, and defaults to draft: true. Rendering is the
expensive operation in this system and an agent should be nudged toward stills.
stingo_still accepts noCamera: true, so a script whose footage does not
exist yet still produces a frame — with the camera box drawn as a placeholder
carrying its source timecode.
#Example
stingo_still {
source: |
title: From an agent
canvas: { preset: horizontal, fps: 30 }
taste: bootdev
scenes:
- block: stat
value: "7x"
label: faster
sub: Cropping before scaling, not after.
at: 2.0
}Returns the frame as a PNG, plus which scene it landed in.
#Machine-readable documentation
Outside MCP, the documentation is published for language models directly:
/llms.txt— an index, in the llms.txt convention/llms-full.txt— every page inlined, one fetch- every page as markdown at its own path, e.g.
/camera.md