Reference
MCP tools
Frame Jam exposes 9 tools over stdio and streamable HTTP. Your agent normally calls them in this order: get_selected_preset, open_review, wait_for_feedback, add_version, then wait_for_feedback again.
Styles
get_selected_preset
At the start of a new video.
Returns the style you picked with Use this style, including its style.json, guide and template files. If you haven't picked one, it returns selected: null and the gallery URL so the agent can ask you to choose.
No arguments.
Returns { selected: id, selectedAt, style, guide, compositionDir, templateFiles } or { selected: null, galleryUrl, next }
list_presets
No style is selected and the agent chooses one itself.
Lists the built-in and user presets, optionally filtered. Each entry carries a gallery URL.
| Argument | Type | Description |
|---|---|---|
mood | string | Filter by mood, for example bold or calm. |
pacing | "slow" | "medium" | "fast" | Filter by pacing. |
format | "16:9" | "9:16" | "1:1" | Filter by aspect ratio. |
query | string | Free-text search over names, taglines and tags. |
Returns { count, presets: [{ id, name, tagline, format, pacing, mood, selected, galleryUrl }] }
get_preset
After choosing a style.
Returns the full style.json (palette, fonts, easing, transitions, text animations, rhythm), the written guide, the template's compositionDir and its source files (up to 200 KB) so the agent can start from working code.
| Argument | Type | Description |
|---|---|---|
idrequired | string | Preset id, for example swiss-editorial. |
Returns { style, guide, compositionDir, templateFiles }
Reviews
open_review
After the first render.
Creates a review and returns its URL for you to open. Called again for the same project (same compositionDir, or same title), it adds the next version instead of a new review. Pass panels or panelsDir instead of a video to review a storyboard.
| Argument | Type | Description |
|---|---|---|
title | string | Name shown in the review list. |
videoPath | string | Absolute path to the rendered mp4. It is copied, so later renders can overwrite the file. |
compositionDir | string | Absolute path to the Hyperframes project. Enables clicking on elements in the live composition. |
panels | array | Storyboard panels: image paths, or { path, title, caption } objects. |
panelsDir | string | Folder of storyboard images, sorted by file name. |
reviewId | string | Add to an existing review instead of matching by project. |
note | string | One line about this version, shown to you as a toast. |
Returns { reviewId, url, version, created, next }
wait_for_feedback
Right after sharing the review URL, and after every new version.
Blocks until you send your comments, then returns them as JSON, as a markdown prompt and as up to six inline frames. After about 50 seconds with nothing it returns status: pending and the agent calls it again. It sends MCP progress notifications every 10 seconds while it waits.
| Argument | Type | Description |
|---|---|---|
reviewIdrequired | string | The review to wait on. |
timeoutSeconds | number | How long to block before returning pending. Default 50, maximum 300. |
Returns { status: "feedback" | "pending", comments[], markdown, frames[] }
get_feedback
You say "apply my Frame Jam feedback" and the agent wasn't waiting.
Returns the newest round of comments right away. Without a reviewId it picks the review whose comments haven't reached the agent yet. Unsent comments are sent, and their version locked, exactly as if you had pressed the button.
| Argument | Type | Description |
|---|---|---|
reviewId | string | Optional. Picks the most relevant review when omitted. |
include | "latest" | "all" | Return only the newest round, or every version's comments. |
Returns { status: "feedback" | "already_delivered" | "empty", comments[], markdown }
add_version
After applying your comments and re-rendering.
Attaches the new render (or new storyboard panels) as the next round. It opens with an empty comment list, and the note is shown to you as a toast.
| Argument | Type | Description |
|---|---|---|
reviewIdrequired | string | The review to add to. |
videoPath | string | Absolute path to the new mp4. Use a new file per version. |
compositionDir | string | Absolute path to the Hyperframes project. |
panels | array | New storyboard panels. |
panelsDir | string | Folder of storyboard images. Re-read when no media is passed. |
note | string | One line about what changed. |
Returns { reviewId, url, version }
list_reviews
The agent needs to find a review.
Lists reviews with their URL and where each round stands: awaiting_user, user_commenting, sent_not_delivered or delivered_to_agent.
No arguments.
Returns { count, reviews: [{ reviewId, title, url, updatedAt, latestVersion, kind, state }] }
resolve_comments
Optional bookkeeping.
Marks comments as handled. The review page doesn't depend on it: each version is one round.
| Argument | Type | Description |
|---|---|---|
reviewIdrequired | string | The review. |
idsrequired | string[] | Comment ids from the feedback, or ["all"] for every sent comment. |
note | string | What was done. |
Returns { resolved, missing, stillOpen }
The feedback your agent receives
wait_for_feedback and get_feedback return three kinds of content: JSON like the example below, the same comments as a markdown prompt, and up to six inline JPEG frames.
{
"status": "feedback",
"reviewId": "rev_14dea90011",
"version": 1,
"comments": [
{
"at": "0:01.5",
"time": 1.5,
"position": { "x": 0.42, "y": 0.61 },
"text": "The red line clips the descenders. Give the mask more room.",
"element": {
"selector": "#scene-1 .headline .line:nth-child(3)",
"clip": "scene-1",
"tweens": [
{ "start": 0.9, "end": 1.6, "ease": "power4.out", "props": { "yPercent": 0 }, "relation": "active" }
]
},
"thumbnailPath": "~/.framejam/reviews/rev_14dea90011/thumbs/c_01.jpg"
},
{
"at": "0:03.1 – 0:05.2",
"time": 3.08,
"endTime": 5.24,
"text": "The three columns land too fast. Hold each one 0.4s longer."
}
]
}atis human-readable;timeandendTimeare seconds.positionis the pin spot as a fraction of the frame, from the top left.elementis present for clicks on a live composition: the CSS selector, the clip that owns it ([data-start]) and the GSAP tweens on it.thumbnailPathpoints to the frame at that moment, grabbed with ffmpeg.
How the blocking wait works
An MCP tool call is a request the agent is waiting on, so Frame Jam simply doesn't answer until there is something to say. It polls the review every 400 ms. After about 50 seconds with nothing it returns { status: "pending" }, which keeps it under client tool-call timeouts, and the agent calls it again without asking you. If the client asked for progress, it sends a notification every 10 seconds.