MCP App Store
by KeenEthics
Malloy Studio icon

Malloy Studio

By Malloy

Get New App Alerts

Overview

Generate customizable motion graphics from simple text prompts. Create animated titles, charts, lower thirds, social overlays, product visuals, and more, then adjust the design and export it for use in your videos. Malloy Studio helps creators and video editors make motion graphics without starting from scratch in After Effects.

Tools

export_template

ChatGPT
Render a template to a downloadable video (runs asynchronously). Only for an explicit export request — never part of the generation flow (that flow ends at preview_template, where the user exports themselves). Before calling: confirm which template the user means (list_my_templates and ask if unclear), then confirm the field values with them — use list_template_parameters(template_id) to see the editable fields, and pass the agreed values as input_props. Typical use: rendering one or several variants of a template with different field values. A preview is not required first; offer one only if the user asks to see it. template_id: a template id from list_my_templates, OR a session_id from generate_animation — a freshly generated session is turned into a template automatically before rendering (same as the web app's create-then-export). input_props: per-render field values overriding the template's defaults (any subset; omitted fields keep their defaults, including fields inside a field that holds an object). An array is replaced whole, so send the full list when changing one. resolution: "360p" | "720p" | "1080p" | "4k", matching the portal export dialog ("4k" requires a plan that includes it). file_format: output container, e.g. "mp4" (use "webm" for transparent output). high_quality: render at a high bitrate with maximum frame quality — a larger file and a slower render. Requires a plan that includes it. It is independent of resolution, so "4k" + "mp4" + high_quality is a valid combination and is the one to use when the user asks for the best possible quality. transparent: render with a transparent background. duration_seconds: clip length when exporting a freshly generated session (defaults to the template's own duration); ignored when exporting an existing template. Costs one export credit per render. Returns an export_id — wait for the render with wait_for_export(export_id) (call until done).

finish_asset_upload

ChatGPT
Register a completed upload as a library asset. asset_key: the value from start_asset_upload, verbatim. name: display name for the asset, normally the original filename. content_type: the same MIME type given to start_asset_upload. Returns the asset with its id. Pass that id in generate_animation's asset_ids to place the file in an animation. Fails with asset_not_uploaded if the POST to upload_url did not complete. Charges no credits.

generate_animation

ChatGPT
Generate a new animated video template from a natural-language prompt. prompt: the animation to generate, described in natural language. Its length is capped per plan: call get_my_plan and read prompt_char_limit if the prompt may be long. Over the cap the call is rejected outright (no credit is charged), so check first and shorten it with the user rather than trimming their wording yourself. aspect_ratio: "16:9" (landscape), "9:16" (vertical, e.g. TikTok / Reels / Stories) or "1:1" (square). Required, and there is no default: ASK the user which one they want before generating, unless they have already said, or unless it follows unambiguously from what they asked for (a named vertical format implies "9:16"). Do not assume landscape. Getting this wrong means regenerating, which costs another prompt credit. style: "pixel_duck" (Pixel Duck 1.3 — builds your prompt exactly as described; best when the user already knows how it should look) or "rubber_duck" (Rubber Duck 1.4 — designs the scene from the idea first; more polished, single-scene; generates a guiding frame, costs more credits). Defaults to "rubber_duck", the app's recommended method. When talking to the user, call them Pixel Duck and Rubber Duck — the names the Malloy app shows — and if you offer the choice, present Rubber Duck as the recommended option, as the app does. (Super Duck exists in the Malloy web app but is not available here; do not offer it via MCP.) Returns a session_id. Generation takes a while: wait for it with wait_for_animation(session_id) (call until result_ready), then ALWAYS show the result with preview_template(session_id). The user watches it there, adjusts its editable fields, and exports from inside the preview — do NOT call export_template as part of this flow. A freshly generated animation is referenced by this session_id — it does NOT appear in list_my_templates until saved or exported. To refine it afterwards, call update_animation(session_id, ...) to edit this same session in place rather than generating from scratch. asset_ids: ids of library assets (from list_my_assets or finish_asset_upload) that must appear in the animation itself — logos, product shots, icons. The animation embeds these files directly. Free; up to 10 per call. reference_key: key of ONE uploaded reference image (from start_reference_upload) whose look the animation should imitate. The image is never placed in the animation — it only guides the style. Setting this doubles the generation's credit cost (2 credits instead of 1; 4 instead of 2 with style="rubber_duck"), so confirm with the user before using it.

get_animation_status

ChatGPT
Check a generation's status once (point-in-time). To wait for it to finish without spinning, prefer wait_for_animation.

get_export_status

ChatGPT
Check an export's status once (point-in-time). Once done is true, video_url is a signed link to the finished video, valid for 24 hours; the render itself is kept 7 days, so call this again for a fresh link rather than storing one. To wait for the render to finish without spinning, prefer wait_for_export.

get_my_plan

ChatGPT
Show the creator's plan, their prompt character limit, and remaining generation + export credits. Read prompt_char_limit from here before sending a long prompt to generate_animation or update_animation: it is plan-dependent and set server-side, so it cannot be assumed or hardcoded.

list_my_assets

ChatGPT
List the user's asset library (files uploaded here or on the Malloy portal). q: optional case-insensitive name filter. limit: max results, newest first, up to 50. Returns assets whose ids can be passed to generate_animation / update_animation as asset_ids. Read-only, free.

list_my_exports

ChatGPT
List your recent video exports, most recent first. Each entry carries its export_id and, once done is true, the signed download link. Two different clocks: the link is signed for 24 hours, while the render itself is kept 7 days (expired renders are not listed). Do not store a link — call this again to get a fresh one. Read-only — no credits.

list_my_templates

ChatGPT
List templates you've already created/exported (most recent first). A freshly generated animation appears here only after you export it — before that, reference it by the session_id from generate_animation.

list_template_parameters

ChatGPT
List a template's editable parameters and their current default values. template_id is a template id from list_my_templates. The parameters are the fields you can override per render: pass any subset as input_props to export_template (values you omit keep their defaults). Read-only — no credits.

preview_template

ChatGPT
Open an interactive preview of a template so the user can watch it play and adjust its editable fields live. Accepts a template id from list_my_templates OR a session_id from generate_animation. Read-only — costs no credits. ALWAYS include the portal_url link from the structured result in your reply — whether or not the interactive preview rendered — so the user can open the template in Malloy to edit or export it. Never surface composition_url: it is an internal data endpoint for the preview widget, not a page a person can open, and it carries a bearer token that should not be pasted into a chat.

save_template

ChatGPT
Save a generated animation into "my templates", and report its editable fields. Free: costs no credits and renders nothing. Call this before exporting anything that was just generated. It turns the generation session into a stored template and returns that template's parameters, so the field names can be confirmed with the user before any export credit is spent, and so several variants can be rendered against one stable template id. template_id: a session_id from generate_animation (materialized into a new template, created=True), or an existing template id from list_my_templates (returned unchanged, created=False). Saving captures the session's code as it is right now. update_animation edits a session in place, so after an update, call save_template again to get a template carrying the new code; exporting the older template id renders the older code.

start_asset_upload

ChatGPT
Reserve a signed upload slot for a file the user wants in their animations. filename: the user's file name, extension included; it becomes the asset's display name at registration. content_type: exact MIME type. Allowed: image/png, image/jpeg, image/webp, image/gif, image/avif, image/svg+xml. size_bytes: the file's size on disk; the upload is rejected above 10 MB or over the plan's storage quota. Returns an upload slot. YOU perform the upload: send one multipart/form-data POST to upload_url with every upload_fields entry first (verbatim, unmodified), then Content-Type set to the same MIME type, then the file itself as the LAST field, named "file". Do not add an acl field. Expect HTTP 204. Then call finish_asset_upload with asset_key to make the asset usable. If this host cannot make HTTP requests, do not attempt the upload: tell the user to upload the file on the Malloy portal's Assets page instead, then find it here with list_my_assets. This reserves quota but charges no credits.

start_reference_upload

ChatGPT
Reserve a signed upload slot for a style reference image. A reference shows the animation what to LOOK like; it is never placed in the animation and is not saved to the user's asset library. To place the user's file in the animation itself, use start_asset_upload instead. filename: the user's file name, extension included. content_type: exact MIME type; any raster image/* (not image/svg+xml). size_bytes: the file's size on disk; rejected above 10 MB. Returns an upload slot. Perform the upload the same way as start_asset_upload (multipart POST, upload_fields verbatim first, file LAST as "file"), then pass reference_key to generate_animation or update_animation. There is no finish step. Using a reference doubles the generation's credit cost, so confirm with the user first. This call itself charges nothing.

update_animation

ChatGPT
Refine an animation you already generated by describing a change, editing the SAME session in place (the session_id is unchanged). session_id comes from generate_animation and must have finished (result_ready — check with get_animation_status / wait_for_animation). The aspect ratio and style are inherited from the original; just describe the edit in prompt (e.g. "make the background dark blue", "slow the intro down"). Each call costs one prompt credit. The same plan prompt character limit applies here (get_my_plan -> prompt_char_limit). Wait for it with wait_for_animation(session_id) as usual, then show the refreshed result with preview_template(session_id). asset_ids: ids of library assets (from list_my_assets or finish_asset_upload) that must appear in the animation itself — logos, product shots, icons. The animation embeds these files directly. Free; up to 10 per call. reference_key: key of ONE uploaded reference image (from start_reference_upload) whose look the animation should imitate. The image is never placed in the animation — it only guides the style. Setting this doubles the generation's credit cost (2 credits instead of 1; 4 instead of 2 with style="rubber_duck"), so confirm with the user before using it.

wait_for_animation

ChatGPT
Wait for a generation to finish, then report its status. Blocks server-side up to ~20s per call, so just call it repeatedly until result_ready is true — each call resumes the wait, no need to pause in between. Returns early the moment the job completes or fails. Once result_ready, always show the result with preview_template(session_id); the user adjusts fields and exports from inside the preview.

wait_for_export

ChatGPT
Wait for an export/render to finish, then report its status. Blocks server-side up to ~20s per call, so just call it repeatedly until done is true — each call resumes the wait, no need to pause between calls. Returns early the moment the render finishes or errors; when done, video_url is the signed download link.

widget_finish_asset_upload

ChatGPT
INTERNAL — called by the Malloy preview widget's image picker only. Never call this from a conversation; it is not part of the chat toolset. Register a completed upload as a library asset (same as finish_asset_upload) and return it WITH its signed url, which the widget writes into the image field. This finish step is the verdict on the upload: it verifies the object exists, so the widget never has to trust the (unreadable) cross-origin POST.

widget_get_export_status

ChatGPT
INTERNAL — called by the Malloy preview widget only. Never call this from a conversation; it is not part of the chat toolset. Point-in-time status of a widget-started export; video_url is the signed download link once done is true.

widget_list_assets

ChatGPT
INTERNAL — called by the Malloy preview widget's image picker only. Never call this from a conversation; it is not part of the chat toolset. List the user's library assets (newest first) with their signed urls, for the picker's Library tab. Returns an object with items (not a bare list) so the widget can read structuredContent.items.

widget_save_template

ChatGPT
INTERNAL — called by the Malloy preview widget only. Never call this from a conversation; it is not part of the chat toolset. Ensures this composition exists in "my templates". Accepts a template id (echoed back unchanged, created=False) or a completed generation session id (bundled into a new template — code + dimensions + code-extracted defaults, like the web app's create-template step — and its id returned, created=True). Takes no form values by design.

widget_start_asset_upload

ChatGPT
INTERNAL — called by the Malloy preview widget's image picker only. Never call this from a conversation; it is not part of the chat toolset. Reserve a presigned slot for uploading an image to the user's asset library (same gates as start_asset_upload). The widget performs the multipart POST.

widget_start_export

ChatGPT
INTERNAL — called by the Malloy preview widget only. Never call this from a conversation; it is not part of the chat toolset. Renders a saved template to video. input_props are per-render parameters (the widget's current form values); they do not modify the saved template. The export options mirror the portal export dialog and are forwarded to the render unchanged: resolution ("360p" | "720p" | "1080p" | "4k"), file_extension ("mp4" | "webm" | "mov"), high_quality, and transparent (the widget pre-derives transparent from an alpha-capable format). 4k and high_quality are plan-gated and raise feature_not_allowed when the plan doesn't include them.

Capabilities

WritesInteractive

Example Prompts

Click any prompt to copy it.

Similar Apps