Set keyframes (Motion)
figma_set_keyframesAnimate a Figma layer by applying or replacing per-field keyframes on its frame timeline, with optional duration control and validation of landed tracks.
Instructions
Animate a layer on its frame's timeline: each track replaces that field's keyframes; other tracks stay. Every track is read back and re-applied if it did not land: tracks[].status is written or rewritten, timeline is { id, duration, topLevelFrameId }, and a track that never lands fails INTERNAL with partial.notApplied. The timeline grows to fit the last key and never shrinks unless timelineDuration says so (tracks: [] + timelineDuration only sets it). Refused before any change: a top-level frame (animate a child), WIDTH/HEIGHT on a group or vector, a missing or non-SOLID paint, EASE_IN_OUT (Figma spells it EASE_IN_AND_OUT); under BRIDGE_PROCESS=strict (the default) PROCESS_REQUIRED until this session read the motion skill (figma_get_guide) and the frame has a plan (figma_set_motion_plan). Not prototype transitions (figma_set_reactions). Check keys with figma_check_motion. UNSUPPORTED means stop, not retry. Skill: motion. Editors: Design; unverified: FigJam, Slides.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| nodeId | Yes | The layer to animate — inside a top-level frame, not the frame itself. | |
| tracks | No | One entry per field. | |
| session | No | Optional sessionId or file name, to pick a Figma file when more than one is connected. | |
| idempotencyKey | No | Caller-owned retry key, ≤128 chars. Re-calling with the same key never executes twice: it returns the existing result, or waits for the op still in flight. Supply your own for anything large — if the MCP client times out (rather than the bridge), only a key you chose can be used to retry safely. | |
| timelineDuration | No | Seconds. Applied as given, even if shorter than the keyframes. |