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.

ArgumentTypeDescription
moodstringFilter 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.
querystringFree-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.

ArgumentTypeDescription
idrequiredstringPreset 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.

ArgumentTypeDescription
titlestringName shown in the review list.
videoPathstringAbsolute path to the rendered mp4. It is copied, so later renders can overwrite the file.
compositionDirstringAbsolute path to the Hyperframes project. Enables clicking on elements in the live composition.
panelsarrayStoryboard panels: image paths, or { path, title, caption } objects.
panelsDirstringFolder of storyboard images, sorted by file name.
reviewIdstringAdd to an existing review instead of matching by project.
notestringOne 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.

ArgumentTypeDescription
reviewIdrequiredstringThe review to wait on.
timeoutSecondsnumberHow 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.

ArgumentTypeDescription
reviewIdstringOptional. 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.

ArgumentTypeDescription
reviewIdrequiredstringThe review to add to.
videoPathstringAbsolute path to the new mp4. Use a new file per version.
compositionDirstringAbsolute path to the Hyperframes project.
panelsarrayNew storyboard panels.
panelsDirstringFolder of storyboard images. Re-read when no media is passed.
notestringOne 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.

ArgumentTypeDescription
reviewIdrequiredstringThe review.
idsrequiredstring[]Comment ids from the feedback, or ["all"] for every sent comment.
notestringWhat 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." } ] }
  • at is human-readable; time and endTime are seconds.
  • position is the pin spot as a fraction of the frame, from the top left.
  • element is present for clicks on a live composition: the CSS selector, the clip that owns it ([data-start]) and the GSAP tweens on it.
  • thumbnailPath points 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.