Skip to main content
Glama

Edit an HTML animation

edit_animation

Change an HTML animation's site: ONE revision, linted, checked and probed. A passing save with project_id moves that project's uses; a failing one is kept but moves nothing; your next edit continues from it. Saves return a contact sheet (preview: false skips it); preview: true | {filmstrip, video, test} renders the moved element in place (dry run: unsaved page).

Send changes against your copy (server can't read your disk; no read first): patch: '<git diff or diff -ruN of your copy>' any number of files files: [{path, edits: [{old, new, replace_all?}]}] · {path, content} · {path, patch} · {path, upload_id} upload_ids: [...] from upload_file(file_names) + one curl; names are paths (media ≤200 MB too, linked relatively: media/clip.mp4) edits: [{op: delete|move, path, to?}] A hunk or edit that doesn't match saves nothing (the reply shows the lines around it).

Read get_design_guide({topic: "pages"}) before writing or editing a page: the timing, scope, determinism and checking rules. Rules: timing from cues, not voiceover words; sound: add_audio, not in-page; save to the project (library only when asked, then say where); one page per scene, split for own timing; a backdrop that runs on across clips reads window.__frame.filmTime (film seconds), not time.

Reply: rev, probe (passing|failing|pending), checks/errors ({path, line, column, code, message}), files_changed, uses_moved, note; detail 'full' adds hunks. dry_run: true saves nothing (a preview token). animation: 'new' creates one (name, scope).

place: {clip_index | continue_from: <element_id>, x/y/width/height?, start_time/end_time?, entry?, name?} → on that clip after a passing save: placed + element_id. No changes: the site as it is. checkpoint: '' keeps a state as a version.

Refusals: stale_base, check_failed, breaking_unconfirmed (confirm_breaking: true). Edits change only this project's copy. Placed elements' parameters, actions, cues: update_elements. A canvas Mograph becomes a page first (reply: upgraded; code in index.html).

Input Schema

NameRequiredDescriptionDefault
nameNoanimation 'new': its name.
slugNoanimation 'new': its site name (a-z, 0-9, -).
editsNoOps applied first: delete and move (replace and write work too).
filesNoPer-file changes: exactly one of edits, content, patch or upload_id each.
patchNoA unified diff of any number of files (git diff / diff -ruN), from the site folder.
placeNoPut the saved page on a clip in this call (after a passing save): returns element_id. Needs project_id. Without file changes: places the site as it is.
probeNoWith dry_run: also render it in the probe (slower; returns its contact sheet).
scopeNoanimation 'new' only: 'project' (default with project_id), 'element' (with for_element), or 'library' ONLY when the user asks to keep it for other videos.
detailNo'full' adds the diff hunks and thumbnail records.
folderNoanimation 'new' with scope 'library': folder path, e.g. 'Brand/Intros'.
wait_sNoHow long to wait for the probe's verdict (default the server's).
dry_runNoCheck without saving; returns a preview token for get_clip render.preview.
previewNoOmitted: the probe's contact sheet (the page at its defaults). true: render what the save produced IN PLACE -- the element it moved (a dry run: its unsaved page), cropped, at four moments. {filmstrip, video, test, element_id}: the same as a filmstrip, with a short MP4 link, or with test settings. false: no image.
requestNoOne line: what the user asked for (history).
base_revNoThe revision you read; a save made since is refused (stale_base).
animationNoThe site to edit when there is no element; 'new' makes one (name, scope).
checkpointNoA name for a state worth keeping (e.g. 'v1 layout'): labels the saved revision and adds it as a version to the animation's Generations history, where the user can find and restore it.
element_idNoThe element whose page to edit (from the version it shows); a canvas Mograph is upgraded to a page first. Needs project_id.
project_idNoThe project: a passing save moves its uses (one undo step).
upload_idsNoWhole files sent with upload_file(file_names); each upload's name is its path.
for_elementNoanimation 'new' with scope 'element'.
confirm_breakingNoMove this project's uses even when the new version drops something they use (a removed or retyped parameter, action, cue or page, a new size); without it such a save moves nothing and lists `breaking`.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • removedInput schema / properties / target
      Removed value: -{
      -  "description": "When the site is used outside this project: 'shared' changes it for everyone, 'fork' copies it for this project.",
      -  "enum": [
      -    "shared",
      -    "fork"
      -  ],
      -  "type": "string"
      -}
  2. Changed50 schema fields changed
    • changedInput schema / properties / animation / description
      Previous value: -"The animation to edit when there is no element: @org/<slug> or an id. 'new' creates one (then pass scope, name and slug)."New value: +"The site to edit when there is no element; 'new' makes one (name, scope)."
    • changedInput schema / properties / base_rev / description
      Previous value: -"The revision you read and expect to edit from. If it has moved, the save is refused with stale_base, the current revision and the files changed since."New value: +"The revision you read; a save made since is refused (stale_base)."
    • changedInput schema / properties / checkpoint / description
      Previous value: -"A one-line note that saves this revision, when it passes, as a version in the element's history in the editor (the user can preview and restore it there). Set it when you reach a state worth returning to, not on every draft."New value: +"A name for a state worth keeping (e.g. 'v1 layout'): labels the saved revision and adds it as a version to the animation's Generations history, where the user can find and restore it."
    • changedInput schema / properties / checkpoint / maxLength
      Previous value: -200New value: +80
    • addedInput schema / properties / confirm_breaking
      Added value: +{
      +  "description": "Move this project's uses even when the new version drops something they use (a removed or retyped parameter, action, cue or page, a new size); without it such a save moves nothing and lists `breaking`.",
      +  "type": "boolean"
      +}
    • changedInput schema / properties / detail / description
      Previous value: -"summary (default) returns the outcome and what changed; full adds the diff hunks and every probe thumbnail."New value: +"'full' adds the diff hunks and thumbnail records."
    • changedInput schema / properties / dry_run / description
      Previous value: -"Build and check the edits without saving. Returns a `preview` token; render it with get_clip(render: {preview})."New value: +"Check without saving; returns a preview token for get_clip render.preview."
    • changedInput schema / properties / edits / description
      Previous value: -"Operations, applied in order before `files`: delete and move (replace and write also work; files is the shorter way)."New value: +"Ops applied first: delete and move (replace and write work too)."
    • removedInput schema / properties / edits / items / properties / all / description
      Removed value: -"replace: replace every occurrence instead of requiring one."
    • removedInput schema / properties / edits / items / properties / content / description
      Removed value: -"write: the whole file."
    • removedInput schema / properties / edits / items / properties / new / description
      Removed value: -"replace: the text to put in its place."
    • removedInput schema / properties / edits / items / properties / old / description
      Removed value: -"replace: the exact text to find, copied from read_animation."
    • removedInput schema / properties / edits / items / properties / op / description
      Removed value: -"replace: exact-match `old` → `new` in `path` (fails unless `old` occurs exactly once, or pass all: true). write: create or overwrite `path` with `content`. delete: remove `path`. move: rename `path` to `to`."
    • removedInput schema / properties / edits / items / properties / path / description
      Removed value: -"File path inside the animation, e.g. 'entries/maya.js'."
    • changedInput schema / properties / element_id / description
      Previous value: -"The animation element this edit is about. The edit starts from the revision that element shows, and every use in this project moves to the new revision when it passes."New value: +"The element whose page to edit (from the version it shows); a canvas Mograph is upgraded to a page first. Needs project_id."
    • changedInput schema / properties / files / description
      Previous value: -"Per-file changes, each with exactly one of edits, content, patch or upload_id. Applied in order after `edits` and `patch`, all saved as ONE revision."New value: +"Per-file changes: exactly one of edits, content, patch or upload_id each."
    • changedInput schema / properties / files / items / properties / content / description
      Previous value: -"The whole file: a new file, or a full rewrite."New value: +"The whole file (new file or rewrite)."
    • changedInput schema / properties / files / items / properties / edits / description
      Previous value: -"Search-and-replace edits for an existing file, applied in order (each sees the text the one before left). Prefer these over content for changes to existing files."New value: +"Exact-match replaces, applied in order."
    • changedInput schema / properties / files / items / properties / edits / items / properties / old / description
      Previous value: -"The exact text to find, copied from read_animation without the 'N| ' line numbers. Must occur exactly once unless replace_all."New value: +"Exact text to find (without the 'N| ' numbers); must occur once unless replace_all."
    • changedInput schema / properties / files / items / properties / edits / items / properties / replace_all / description
      Previous value: -"Replace every occurrence instead of requiring exactly one."New value: +"Replace every occurrence."
    • changedInput schema / properties / files / items / properties / patch / description
      Previous value: -"A unified diff of this one file ('@@ -a,b +c,d @@' hunks). Context and removed lines must match exactly; a hunk may sit at other line numbers."New value: +"A unified diff of this one file."
    • changedInput schema / properties / files / items / properties / path / description
      Previous value: -"File path inside the animation, e.g. 'entries/maya.js'."New value: +"File path in the site, e.g. 'index.html'."
    • changedInput schema / properties / files / items / properties / upload_id / description
      Previous value: -"The mcp_upload_id (mup_…) of a text file sent with upload_file (file_name + its curl), used as the whole content, so a big file never goes inline. UTF-8 text, at most 256 KB."New value: +"A file sent with upload_file: text is used as the whole content (UTF-8, at most 2 MB); media (video, audio, image, font, model) is added as is (at most 200 MB)."
    • changedInput schema / properties / folder / description
      Previous value: -"Only with animation 'new' and scope 'library' (a save the user asked to keep for the workspace): the library folder, by path, e.g. 'Characters' or 'Characters/Presenters'. Missing folders are created (at most three levels)."New value: +"animation 'new' with scope 'library': folder path, e.g. 'Brand/Intros'."
    • addedInput schema / properties / for_element
      Added value: +{
      +  "description": "animation 'new' with scope 'element'.",
      +  "type": "string"
      +}
    • changedInput schema / properties / name / description
      Previous value: -"Only with animation 'new': the display name."New value: +"animation 'new': its name."
    • changedInput schema / properties / patch / description
      Previous value: -"For a client working from files on disk: a unified diff of any number of files against the saved revision (`git diff`, `diff -u` or `diff -ruN`), run from the folder holding manifest.json. The server holds the base. New files (--- /dev/null), deletes and renames apply too. A hunk whose context no longer matches is refused with the saved lines around it; nothing is saved."New value: +"A unified diff of any number of files (git diff / diff -ruN), from the site folder."
    • changedInput schema / properties / place / description
      Previous value: -"Put the animation on the canvas on the first passing save, as an animation element on this clip (the add_elements placement), and return its element_id: pass that on every later edit so each passing save updates the editor live. Needs project_id. Placing is per entry and clip: an entry already on that clip is not placed again (its element_id comes back); any other entry, or the same entry on another clip, is, and existing elements keep their own entries. Works for an existing animation too (animation: '@org/<slug>', or element_id + place.entry for another entry of the element's animation), and with no file changes at all it only places the latest revision. A failing save places nothing."New value: +"Put the saved page on a clip in this call (after a passing save): returns element_id. Needs project_id. Without file changes: places the site as it is."
    • addedInput schema / properties / place / properties / clip_id
      Added value: +{
      +  "description": "Or the clip by id.",
      +  "minLength": 1,
      +  "type": "string"
      +}
    • changedInput schema / properties / place / properties / clip_index / description
      Previous value: -"Zero-based clip the animation belongs to. With continue_from: the clip it continues into (default the next)."New value: +"The clip, 0-based."
    • changedInput schema / properties / place / properties / continue_from / description
      Previous value: -"An animation element on an earlier clip that this one carries on from across the cut: placed in its box. The same animation, or a fork of it, picks up at the second it reached (timing 'trim'); any other starts at its own 0 with its own settings."New value: +"An animation element of an earlier clip: carry it on into the next clip (or clip_index) from where it stopped, with its box, values and timeline."
    • changedInput schema / properties / place / properties / end_time / description
      Previous value: -"Seconds from the clip's start (default: the clip's end)."New value: +"Clip seconds; default the page's duration."
    • changedInput schema / properties / place / properties / entry / description
      Previous value: -"Which entry to place (default: the only one, else 'main', else the first). Any entry not yet on that clip is placed, also of an animation already on the canvas."New value: +"Another page of the site, e.g. 'outro.html'."
    • changedInput schema / properties / place / properties / height / description
      Previous value: -"Box height, canvas pixels (default: the full canvas)."New value: +"Canvas px; default full frame."
    • changedInput schema / properties / place / properties / name / description
      Previous value: -"The element's label."New value: +"The element's label in the editor (default: the site's name, or site/entry)."
    • changedInput schema / properties / place / properties / start_time / description
      Previous value: -"Seconds from the clip's start (default 0)."New value: +"Clip seconds; default 0."
    • changedInput schema / properties / place / properties / width / description
      Previous value: -"Box width, canvas pixels (default: the full canvas)."New value: +"Canvas px; default full frame."
    • changedInput schema / properties / place / properties / x / description
      Previous value: -"Left edge, canvas pixels (default: centred)."New value: +"Canvas px; default 0."
    • changedInput schema / properties / place / properties / y / description
      Previous value: -"Top edge, canvas pixels (default: centred)."New value: +"Canvas px; default 0."
    • changedInput schema / properties / preview / anyOf
      Previous value: -[
      -  {
      -    "type": "boolean"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "actions": {
      -        "description": "Action clips to try, [{name, start, duration?, args?}], element-local seconds; duration defaults to the action's default_duration. Replaces the element's clips for this render.",
      -        "items": {
      -          "properties": {
      -            "args": {
      -              "additionalProperties": {},
      -              "propertyNames": {
      -                "type": "string"
      -              },
      -              "type": "object"
      -            },
      -            "duration": {
      -              "type": "number"
      -            },
      -            "name": {
      -              "minLength": 1,
      -              "type": "string"
      -            },
      -            "start": {
      -              "type": "number"
      -            }
      -          },
      -          "required": [
      -            "name",
      -            "start"
      -          ],
      -          "type": "object"
      -        },
      -        "type": "array"
      -      },
      -      "cues": {
      -        "additionalProperties": {
      -          "type": "number"
      -        },
      -        "description": "Cue times to try, key: seconds (element-local).",
      -        "propertyNames": {
      -          "type": "string"
      -        },
      -        "type": "object"
      -      },
      -      "duration": {
      -        "description": "How long the entry plays in the preview, in seconds.",
      -        "exclusiveMinimum": 0,
      -        "type": "number"
      -      },
      -      "entry": {
      -        "description": "Which entry to show (default: the element's, or the animation's first).",
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "filmstrip": {
      -        "anyOf": [
      -          {
      -            "const": true,
      -            "type": "boolean"
      -          },
      -          {
      -            "additionalProperties": false,
      -            "properties": {
      -              "around": {
      -                "description": "Center the window on a cue ('cue:land') or an action clip ('action:hop', by name or id) instead of from/to. On a whole clip, a cue several animations share is 'cue:land@<element name>'.",
      -                "pattern": "^(cue|action):.+",
      -                "type": "string"
      -              },
      -              "fps": {
      -                "description": "Frames per second instead of a count, e.g. 8 over 2 s is 17, capped at 16.",
      -                "exclusiveMinimum": 0,
      -                "maximum": 60,
      -                "type": "number"
      -              },
      -              "frames": {
      -                "description": "How many frames across the window, first and last included (default 12, max 16).",
      -                "maximum": 16,
      -                "minimum": 2,
      -                "type": "integer"
      -              },
      -              "from": {
      -                "description": "Window start, element-local seconds, or clip seconds for a whole clip (default 0).",
      -                "minimum": 0,
      -                "type": "number"
      -              },
      -              "seam": {
      -                "const": true,
      -                "description": "get_clip of a whole clip only: the cut from this clip into the next, as the player shows it: this clip's last second, its transition, and the next clip's first second, in this clip's seconds; takes frames, no window. Every cut of the film at once: get_project({render: {seams: true}}).",
      -                "type": "boolean"
      -              },
      -              "span": {
      -                "description": "With around: the window's length in seconds (default 2 around a cue; the clip plus 0.5 around an action).",
      -                "exclusiveMinimum": 0,
      -                "type": "number"
      -              },
      -              "to": {
      -                "description": "Window end, element-local seconds, or clip seconds for a whole clip (default the end).",
      -                "exclusiveMinimum": 0,
      -                "type": "number"
      -              }
      -            },
      -            "type": "object"
      -          }
      -        ],
      -        "description": "See motion in ONE image instead of four moments: frames spaced evenly across a window (default 12 over the whole animation), in reading order, each labelled with its element-local time, with a thin timeline under each row marking the frames, cues (lines) and action clips (bars). Read pacing, easing and whether a beat lands on its cue from it. true for the defaults, or {from, to} / {around: 'cue:<key>' | 'action:<name>', span}, with frames or fps. Replaces timestamps. On get_clip without element_id, animation or preview it shows the whole clip, every element drawn, in clip seconds, and the timeline also ticks each element's start and end."
      -      },
      -      "param_tracks": {
      -        "additionalProperties": {
      -          "items": {
      -            "properties": {
      -              "interpolation": {
      -                "type": "string"
      -              },
      -              "t": {
      -                "type": "number"
      -              },
      -              "value": {}
      -            },
      -            "required": [
      -              "t",
      -              "value"
      -            ],
      -            "type": "object"
      -          },
      -          "minItems": 1,
      -          "type": "array"
      -        },
      -        "description": "Keyframed settings to try, key: [{t, value, interpolation?}], t in element-local seconds. Replaces that key's track for this render.",
      -        "propertyNames": {
      -          "type": "string"
      -        },
      -        "type": "object"
      -      },
      -      "parameter_values": {
      -        "additionalProperties": {},
      -        "description": "Settings to render with, merged over the element's own (key: value).",
      -        "propertyNames": {
      -          "type": "string"
      -        },
      -        "type": "object"
      -      },
      -      "timestamps": {
      -        "anyOf": [
      -          {
      -            "minimum": 0,
      -            "type": "number"
      -          },
      -          {
      -            "items": {
      -              "minimum": 0,
      -              "type": "number"
      -            },
      -            "maxItems": 12,
      -            "minItems": 1,
      -            "type": "array"
      -          }
      -        ],
      -        "description": "Moments to show, element-local seconds (default four across its length)."
      -      },
      -      "video": {
      -        "description": "For people: also a short low-resolution MP4 of the same window (the filmstrip's, or the animation's first 10 s), returned as video_url, a link valid for an hour. You can't watch it: judge motion from the filmstrip.",
      -        "type": "boolean"
      -      }
      -    },
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "type": "boolean"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "element_id": {
      +        "description": "Which use to render when the save moved several (default the first).",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "filmstrip": {
      +        "anyOf": [
      +          {
      +            "const": true,
      +            "type": "boolean"
      +          },
      +          {
      +            "additionalProperties": false,
      +            "properties": {
      +              "around": {
      +                "description": "Center the window on a cue ('cue:land') or an action clip ('action:hop', by name or id) instead of from/to. On a whole clip, a cue several animations share is 'cue:land@<element name>'.",
      +                "pattern": "^(cue|action):.+",
      +                "type": "string"
      +              },
      +              "fps": {
      +                "description": "Frames per second instead of a count, e.g. 8 over 2 s is 17, capped at 16.",
      +                "exclusiveMinimum": 0,
      +                "maximum": 60,
      +                "type": "number"
      +              },
      +              "frames": {
      +                "description": "How many frames across the window, first and last included (default 12, max 16).",
      +                "maximum": 16,
      +                "minimum": 2,
      +                "type": "integer"
      +              },
      +              "from": {
      +                "description": "Window start, element-local seconds, or clip seconds for a whole clip (default 0).",
      +                "minimum": 0,
      +                "type": "number"
      +              },
      +              "seam": {
      +                "const": true,
      +                "description": "get_clip of a whole clip only: the cut from this clip into the next, as the player shows it: this clip's last second, its transition, and the next clip's first second, in this clip's seconds; takes frames, no window. Every cut of the film at once: get_project({render: {seams: true}}).",
      +                "type": "boolean"
      +              },
      +              "span": {
      +                "description": "With around: the window's length in seconds (default 2 around a cue; the clip plus 0.5 around an action).",
      +                "exclusiveMinimum": 0,
      +                "type": "number"
      +              },
      +              "to": {
      +                "description": "Window end, element-local seconds, or clip seconds for a whole clip (default the end).",
      +                "exclusiveMinimum": 0,
      +                "type": "number"
      +              }
      +            },
      +            "type": "object"
      +          }
      +        ],
      +        "description": "See motion in ONE image instead of four moments: frames spaced evenly across a window (default 12 over the whole animation), in reading order, each labelled with its element-local time, with a thin timeline under each row marking the frames, cues (lines) and action clips (bars). Read pacing, easing and whether a beat lands on its cue from it. true for the defaults, or {from, to} / {around: 'cue:<key>' | 'action:<name>', span}, with frames or fps. Replaces timestamps. On get_clip without element_id or preview it shows the whole clip, every element drawn, in clip seconds, and the timeline also ticks each element's start and end. HTML animations (pages) are drawn from their page in every render, the next clip's across a seam included; their cues and actions are the page's."
      +      },
      +      "test": {
      +        "additionalProperties": false,
      +        "description": "Try other settings on the one animation rendered (element_id or preview), nothing saved: parameter_values, param_tracks, actions, cues, in element-local (page) seconds. For an HTML animation the page is drawn with them; check a value or a cue before setting it with update_elements.",
      +        "properties": {
      +          "actions": {
      +            "description": "Action clips to try instead of the element's: [{name, start, duration?, args?}].",
      +            "items": {
      +              "additionalProperties": false,
      +              "properties": {
      +                "args": {
      +                  "additionalProperties": {},
      +                  "propertyNames": {
      +                    "type": "string"
      +                  },
      +                  "type": "object"
      +                },
      +                "duration": {
      +                  "exclusiveMinimum": 0,
      +                  "type": "number"
      +                },
      +                "name": {
      +                  "minLength": 1,
      +                  "type": "string"
      +                },
      +                "start": {
      +                  "minimum": 0,
      +                  "type": "number"
      +                }
      +              },
      +              "required": [
      +                "name",
      +                "start"
      +              ],
      +              "type": "object"
      +            },
      +            "type": "array"
      +          },
      +          "cues": {
      +            "additionalProperties": {
      +              "minimum": 0,
      +              "type": "number"
      +            },
      +            "description": "Cue times to try: {key: seconds}.",
      +            "propertyNames": {
      +              "type": "string"
      +            },
      +            "type": "object"
      +          },
      +          "param_tracks": {
      +            "additionalProperties": {
      +              "items": {
      +                "additionalProperties": {},
      +                "properties": {
      +                  "interpolation": {
      +                    "type": "string"
      +                  },
      +                  "t": {
      +                    "description": "Element-local (page) seconds.",
      +                    "minimum": 0,
      +                    "type": "number"
      +                  },
      +                  "value": {}
      +                },
      +                "required": [
      +                  "t",
      +                  "value"
      +                ],
      +                "type": "object"
      +              },
      +              "minItems": 1,
      +              "type": "array"
      +            },
      +            "description": "Keyframes to try for animatable parameters: {key: [{t, value, interpolation?}]}.",
      +            "propertyNames": {
      +              "type": "string"
      +            },
      +            "type": "object"
      +          },
      +          "parameter_values": {
      +            "additionalProperties": {},
      +            "description": "Values to try, over the element's own (an image or video value: a URL or upload).",
      +            "propertyNames": {
      +              "type": "string"
      +            },
      +            "type": "object"
      +          }
      +        },
      +        "type": "object"
      +      },
      +      "video": {
      +        "description": "For people: also a short low-resolution MP4 of the same window (the filmstrip's, or the animation's first 10 s), returned as video_url, a link valid for an hour. You can't watch it: judge motion from the filmstrip.",
      +        "type": "boolean"
      +      }
      +    },
      +    "type": "object"
      +  }
      +]
    • changedInput schema / properties / preview / description
      Previous value: -"Every direct save already returns a small contact sheet (four moments). false skips it; true or an object asks for a larger one with your choice of entry, moments, a filmstrip and test settings (parameter_values, where an image setting may be an upload id or a URL; param_tracks, actions, cues). With a project it shows a placed use of the entry with that element's own settings; with dry_run the unsaved code; without project_id a plain background. Nothing about the preview is saved."New value: +"Omitted: the probe's contact sheet (the page at its defaults). true: render what the save produced IN PLACE -- the element it moved (a dry run: its unsaved page), cropped, at four moments. {filmstrip, video, test, element_id}: the same as a filmstrip, with a short MP4 link, or with test settings. false: no image."
    • addedInput schema / properties / probe
      Added value: +{
      +  "description": "With dry_run: also render it in the probe (slower; returns its contact sheet).",
      +  "type": "boolean"
      +}
    • changedInput schema / properties / project_id / description
      Previous value: -"Project the element is in. Needed with element_id."New value: +"The project: a passing save moves its uses (one undo step)."
    • addedInput schema / properties / request
      Added value: +{
      +  "description": "One line: what the user asked for (history).",
      +  "type": "string"
      +}
    • changedInput schema / properties / scope / description
      Previous value: -"Only with animation 'new': one element, this project (the default with project_id; every scene of the video can import it), or the workspace library, only when the user asks to reuse it in other videos."New value: +"animation 'new' only: 'project' (default with project_id), 'element' (with for_element), or 'library' ONLY when the user asks to keep it for other videos."
    • changedInput schema / properties / slug / description
      Previous value: -"Only with animation 'new': lowercase letters, digits and dashes; becomes @org/<slug>. Slugs are workspace-wide: one an animation of another project (or the library) holds is saved as the next free <slug>-N (the reply's animation and note say which, nothing to resend); one this project already holds is refused, naming it and a free slug."New value: +"animation 'new': its site name (a-z, 0-9, -)."
    • changedInput schema / properties / target / description
      Previous value: -"Required when the animation is used outside this project: 'shared' changes it for everyone who updates, 'fork' copies it for this project first. Official and community animations always fork."New value: +"When the site is used outside this project: 'shared' changes it for everyone, 'fork' copies it for this project."
    • removedInput schema / properties / update_dependents
      Removed value: -{
      -  "description": "After a passing save, re-pin every animation that imports this one (a kit's scenes) to the new revision in the same call and move this project's uses of them; dependents_updated {report, project_uses_moved, note} says what moved. Left out: on for a project-scoped animation saved with project_id, off otherwise (a library animation's importers span the workspace: pass true).",
      -  "type": "boolean"
      -}
    • changedInput schema / properties / upload_ids / description
      Previous value: -"Whole files sent with upload_file(file_names: [...]) and its one curl: each upload's file name is its path in the animation (e.g. 'entries/city.js'), and its text replaces or adds that file. Applied after files."New value: +"Whole files sent with upload_file(file_names); each upload's name is its path."
    • addedInput schema / properties / wait_s
      Added value: +{
      +  "description": "How long to wait for the probe's verdict (default the server's).",
      +  "maximum": 170,
      +  "minimum": 0,
      +  "type": "number"
      +}
  3. Added

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations, it discloses that saves are one revision, that failing saves are kept but move no uses, that passing saves move project uses in one undo step, that dry_run returns a preview token, and that breaking changes require confirm_breaking. It also explains checkpoint versioning and canvas Mograph upgrading.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but justified by 22 parameters and nested objects, and the core action is front-loaded. It is dense and occasionally telegraphic, with some repetition of schema-covered details, but the sectioned layout keeps it navigable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite having no output schema, it explains the reply fields (rev, probe, checks/errors, files_changed, uses_moved, note), detail modes, preview results, and refusal outcomes. For a complex edit-and-place tool, an agent has enough to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already carries most parameter detail. The description still adds useful cross-parameter semantics: accepted file-change shapes, atomic all-or-nothing matching, upload_id linkage to upload_file, and place/preview behavior.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence states a specific verb and resource: changing an HTML animation's site in one revision, with linting, checking and probing. It also distinguishes the tool from update_elements by assigning placed-element parameters, actions and cues to that sibling.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly instructs the agent to read get_design_guide({topic: "pages"}) before writing or editing a page, explains the preview/dry-run choices, names stale_base/check_failed/breaking_unconfirmed refusals, and redirects placed-element changes to update_elements.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.