Diffusion Studio exposes one set of tools, reachable two ways:
- MCP. The running app serves an MCP server at
http://127.0.0.1:3274/mcp(Streamable HTTP). A connected agent gets every tool intools/list, with the descriptions on these pages and its input and output as JSON Schema 2020-12, and instructions that give the path of these docs in the installed app. A client that can only spawn a stdio server can bridge to the URL with a generic proxy such asmcp-remote. - CLI.
dapi, the command-line client shipped with the app, wraps every tool as a command for shells, scripts and CI.dapi <command> --helpprints the same description and the same field help.
Both validate against the same schemas and return the same result, so each tool is documented once, on its own page. The catalog behind all three (server, CLI, these pages) lives in packages/dapi.
The JSX code syntax specified in jsx/ is pseudo-SVG, mirroring SVG's shape-and-paint model with the editor's own tags and props rather than the SVG spec. A project is a folder of that JSX, and the source is the document: the app compiles the entry file and renders every element into an editable node, and edits made on the canvas are written back to the element that authored them. So the loop is open once, then edit the files — there is no tool that pushes content into the app. What the tools do is read the running app (context, capture, logs), inspect media, and list what a declaration may name.
A tool is named as MCP lists it, and the CLI spelling follows from the name:
_in a tool name is a space on the command line:media_grabisdapi media grab. Themediagroup is alsom.- A tool's first field is the positional argument:
capture'sidisdapi capture <id>. - Every other field is an option in kebab-case:
perSheetis--per-sheet,separateis--separate. Short forms are listed on each page. - Times are written the same way everywhere: seconds (
1.5), frames at the project's rate (45f), or a clock string (1:30,00:01:30). Times in results are plain seconds.
Every tool returns one JSON object, its structured content. Over MCP that is the result's structuredContent, repeated as a text block for clients that ignore structured content; the CLI prints it to stdout, unchanged. Tools that render images (capture, media_grab, media_filmstrip, media_waveform, screenshot) write PNGs to disk and return their paths; over MCP a result of at most four images, none over a megabyte, also carries them inline as image content, so a contact sheet arrives in context without opening anything.
A failure is a sentence written to be read, e.g. No project open — run open first. Over MCP it arrives as a tool result with isError: true, not as a protocol error; the CLI prints it to stderr and exits 1. Each page's Errors section lists what the tool fails on; only the delivery differs by surface.
Every tool runs inside the app, so the app has to be running. Over MCP that is a given — the connection is to the app. From a shell, dapi open launches it (macOS) or surfaces the running instance; every other command prints a launch instruction and exits 1 while the app is down.
| Tool | CLI | Does |
|---|---|---|
open |
dapi open |
Open project |
context |
dapi context |
App context |
capture |
dapi capture |
Capture frames |
check |
dapi check |
Check structure |
export |
dapi export |
Export scene |
media_probe |
dapi media probe |
Probe media |
media_grab |
dapi media grab |
Grab frames |
media_transcribe |
dapi media transcribe |
Transcribe speech |
media_filmstrip |
dapi media filmstrip |
Filmstrip preview |
media_waveform |
dapi media waveform |
Waveform preview |
media_listen |
dapi media listen |
Listen to audio |
models |
dapi models |
Generation models |
voices |
dapi voices |
Speech voices |
whoami |
dapi whoami |
Signed-in account |
logs |
dapi logs |
App logs |
screenshot |
dapi screenshot |
Window screenshot |
fonts |
dapi fonts |
Local fonts |
report |
dapi report |
Report a bug |
How the surface is divided:
- The project loop.
opena folder, edit its JSX,contextfor what the source cannot say,captureandcheckto verify,exportwhen asked. - Media inspection (
media_*): a file by path, without adding it to the project. Absolute paths and URLs work with or without an open project; library paths (b-roll/clip.mp4) need one. - What a declaration may name.
models,voices,fonts. Generation itself is declared in the project module (generate.*, see jsx/generate.md); no tool generates. - The app and the machine.
whoami,logs,screenshot,report.
There is no download tool, and none is needed: run yt-dlp from a shell. It handles YouTube, TikTok, Instagram, Vimeo, X, direct media links and most other sites, and a download that lands under the project's assets/ folder is a library asset (see jsx/media.md).
Asset = { id: string; path: string; type: string } // asset ids are content hashes; `path` is the library path
Time = number | `${number}f` | "MM:SS" // seconds, frames at the project's rate ("45f"), or a clock string; see jsx/timing.md
NodeId = string // an element's `id` in the project's JSX; `file:id` (`intro.tsx:hero`, the file name with its extension) when two files collideTime inputs take the Time format unless noted otherwise.