Skip to main content
Glama

Add keyframe

add_keyframe
Destructive

Add or overwrite a keyframe on a layer's animation track. For leaves (image/video/shape), x/y/rotation keyframes are ABSOLUTE canvas-space values: x and y are the layer centre's pixel position (canvas is 1080×1920), rotation is degrees. For groups, x/y keyframes are translation offsets applied around the group's frozen pivot, and rotation is the group's absolute angle. scale orbits the layer/pivot centre (1 = no change). opacity is 0..1. 30 fps. When a keyframe track is present on a property, it OVERRIDES the layer's static base value at every frame. One keyframe alone plays as a constant: a result that leaves a track with a single keyframe carries a warning. To place a layer without animating it, use move_layer.

Input Schema

NameRequiredDescriptionDefault
frameYesFrame number, 0-indexed. 30 fps so frame 30 = 1 second.
valueYesTrack value at this frame.
easingNoInterpolation to the next keyframe. Default linear.
propertyYes
elementIdYesLayer id (video.<id>, image.<id>, shapes.<id>, or group.<id>).
projectIdYesOpaque project id (a v4 UUID, from list_projects/create_project). Selects which existing project this call mutates.

Output Schema

NameRequiredDescriptionDefault
okYesWhether the call succeeded.
dataNoThe payload, shaped by the tool.
noteNoWhat to do next when not ready.
errorNoWhy it failed.
statusNoFor cache-backed readers: whether the answer was ready.
editorUrlNoOpens this project in the editor.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changed
    • removedInput schema / properties / anonymousToken
      Removed value: -{
      -  "description": "The token create_anonymous_account returned. This connection has no Morpha key, so every call carries it.",
      -  "type": "string"
      -}
    • changedInput schema / required
      Previous value: -[
      -  "elementId",
      -  "property",
      -  "frame",
      -  "value",
      -  "projectId",
      -  "anonymousToken"
      -]New value: +[
      +  "elementId",
      +  "property",
      +  "frame",
      +  "value",
      +  "projectId"
      +]
  2. Changed1 schema field changed
    • changedOutput schema / (root)
      Previous value: -nullNew value: +{
      +  "description": "The result envelope every Morpha tool returns.",
      +  "properties": {
      +    "data": {
      +      "description": "The payload, shaped by the tool.",
      +      "type": [
      +        "object",
      +        "array",
      +        "string",
      +        "number",
      +        "boolean",
      +        "null"
      +      ]
      +    },
      +    "editorUrl": {
      +      "description": "Opens this project in the editor.",
      +      "type": "string"
      +    },
      +    "error": {
      +      "description": "Why it failed.",
      +      "type": "string"
      +    },
      +    "note": {
      +      "description": "What to do next when not ready.",
      +      "type": "string"
      +    },
      +    "ok": {
      +      "description": "Whether the call succeeded.",
      +      "type": "boolean"
      +    },
      +    "status": {
      +      "description": "For cache-backed readers: whether the answer was ready.",
      +      "enum": [
      +        "ready",
      +        "not-ready"
      +      ],
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "ok"
      +  ],
      +  "type": "object"
      +}
  3. Changed2 schema fields changed
    • addedInput schema / properties / anonymousToken
      Added value: +{
      +  "description": "The token create_anonymous_account returned. This connection has no Morpha key, so every call carries it.",
      +  "type": "string"
      +}
    • changedInput schema / required
      Previous value: -[
      -  "elementId",
      -  "property",
      -  "frame",
      -  "value",
      -  "projectId"
      -]New value: +[
      +  "elementId",
      +  "property",
      +  "frame",
      +  "value",
      +  "projectId",
      +  "anonymousToken"
      +]
  4. First observed

TDQS

A4.6/5.0
Behavior5/5

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

Annotations declare destructiveHint=true, and the description substantiates that by disclosing that adding overwrites existing values and that a present track OVERRIDES the layer's static base value at every frame. It further adds units and coordinate frames (absolute canvas-space pixels on a 1080x1920 canvas, degrees, 30 fps, opacity 0..1) and the single-keyframe warning, which annotations cannot convey.

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?

Front-loads the core action and overwrite semantics, then the coordinate rules, then the fallback to move_layer. Dense but nearly every clause carries distinct semantic information; the canvas dimensions and fps are stated twice (also in the frame param) but that redundancy is minor.

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?

An output schema exists, so return values need not be described, yet the description still flags the single-keyframe warning case. For a 6-parameter mutation tool with coordinate-frame subtleties, the description supplies everything needed 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 coverage is 83%, so the baseline is 3, but the description goes beyond it by defining what x/y/rotation/scale/opacity values mean and how they differ between leaves and groups (absolute canvas position vs. offsets around a frozen pivot). It leaves 'width', 'height', 'curve', and the easing enum to the schema.

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?

States a specific verb and resource ('Add or overwrite a keyframe on a layer's animation track') and makes the singular/overwrite semantics explicit, which separates it from the batch siblings (add_keyframes, set_keyframes_batch) without needing the schema.

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

Usage Guidelines4/5

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

Explicitly routes the agent away from animating when it only wants placement ('To place a layer without animating it, use move_layer') and warns that a lone keyframe yields a constant track. It does not state when to prefer the batch siblings (add_keyframes/set_keyframes_batch), so it stops short of full alternative coverage.

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.

Resources