# TweenFrame TweenFrame renders finished media files from structured inputs: texts, colors, photos and output options go in, a GIF, WebP, APNG, MP4, WebM, PNG, JPEG, SVG or PDF comes out. You drive it with the tools of its MCP server. Your job is the file the user asked for: render it, check it and give the user the link. Do not hand back a plan instead of the result. ## Setup - The tools come from the TweenFrame MCP server at `https://tweenframe.com/mcp`. If you do not have them, the user adds that address: in a chat app as a custom connector, in an agent as a remote MCP server. - Connecting signs the user in on the TweenFrame site with a code sent to their email. There is no key to set up, and every tool then works with their account: saving designs, links and lasting file links included. - `list_docs` lists the guides below; `read_doc` reads one by its name, or by the `docs` link of an answer (a link with `#section` reads only that section). ## Tools | Task | Tools | | ----------------------- | ------------------------------------------------------------------------------------------------------ | | Find and read a recipe | `list_recipes`, `get_recipe` | | Render | `render_recipe`, then `get_render` while the answer is `pending` | | Your own recipe | `check_recipe` | | Icons, decor and fonts | `search_library`, `list_library_sets`, `list_fonts` | | The user's images | `upload_asset`, `analyze_asset`, `remove_background` | | GIF size, video to GIF | `compress_gif`, `convert_video_to_gif` | | Keep a design | `save_recipe`, `list_saved_recipes`, `get_saved_recipe`, `replace_saved_recipe`, `delete_saved_recipe` | | Share a design as a URL | `create_link`, `list_links`, `delete_link` | | A lasting file link | `publish_result`, `list_published`, `delete_published` | | Guides | `list_docs`, `read_doc` | ## Workflow Find the recipe nearest to what the user wants with `list_recipes` (each entry has an `inputs_summary`: required inputs, image slots, text and color counts) and read it with `get_recipe`. Then one of two: - **Its inputs give the result.** Take the closest of its `examples`, change only what the user asked for, put the user's images in (below), then `render_recipe` with `recipe: {id}` and those `inputs`. - **The result needs a change the inputs cannot make** (another layout, more or fewer blocks, other logic). Take the recipe's document (`get_recipe` with `document: true`), edit it, check it with `check_recipe` until it passes, then `render_recipe` with `recipe: {document}`. The `authoring` guide explains the document and has examples to start from when no recipe is near; icons and decor shapes for it come from `search_library`. **The user's images.** `upload_asset` takes an image the user attached (`file`) or an address of one (`url`) and answers its managed `url`; put that URL into the inputs at a path from the recipe's `asset_paths`. An address must answer with the file itself, not a redirect. **Storyboard before every animated file.** Before the final render, render the same inputs with `output.format: "storyboard"` and look at the image: every slide and every transition in one picture for the price of one render. Fix what is wrong, then render the final file. **A size budget, or a video to turn into a GIF.** Keep `normal` quality and about 900 px wide; never start with `minimal` quality or a smaller width. For a budget, first work on the animations (hard cuts or cheaper transitions instead of long full-frame ones, fewer and smaller animated areas and slides), then lower the fps, then `compress_gif` with `settings.target_size`; it may lower the width, so check the result's. A video becomes a GIF with `convert_video_to_gif` (give `settings.width: 900`; the default is smaller). Both are in the `gif-tools` guide. **A photo without its background.** `remove_background` cuts the subject out onto a transparent background and answers a PNG; use it like any image. **The user wants to keep the design or share a link to it** (render it again later with other inputs, or hand out a URL that renders it from its query): `save_recipe` and `create_link`, in the `links` guide. **The user wants a link to the file itself**: a `result_url` is temporary; `publish_result` answers a lasting URL. Output options such as `format`, `width` and `fps` go in `output`, not in the inputs. How recipes, inputs and output options work in detail is in the `recipes` guide; read it before your first render. ## Guides | Guide | Read it when | | ----------- | ------------------------------------------------------------------------------------------------------------ | | `recipes` | Before the first render: catalog, versions, input schemas, examples, images, output options, limits. | | `authoring` | You change a recipe's document or write your own: the check and render loop, the skeleton, the topic guides. | | `output` | You choose a format, size, frame rate or quality, or a file is too large, blurry or cut off. | | `assets` | You work with the user's photos: uploads, focal points, crops, supported formats. | | `gif-tools` | A GIF must fit a size budget, or a video must become a GIF. | | `links` | The user wants to keep a recipe document or share a link that renders it. | | `errors` | A tool answered an error: one section per error code. | For a recipe document, read `authoring` first, then only the topic guide you need, not all of them. ## Errors A failed call answers an error with `code`, `message`, `details`, `hint` and a `docs` link. Read `code`, `details.path` and `hint`; when that is not enough, `read_doc` the `docs` link. Fix the value and retry; never resend the same call unchanged. A `quota_exceeded` error means stop and tell the user. ## Report Give the user the `result_url` (or the lasting URL) of each file with its format, pixel size, byte size and duration when it is animated, as the answer gives them. Name the recipe (`id` and `version` from the render answer). Say which values you chose that the user did not give you (texts, crops, sizes), and anything you could not do and why.