# Tools & Keyframes Reference

Complete reference for all MCP tools exposed by DevMotion and the keyframe animation system.

## Available Tools

Tool | Description
--- | ---
`create_project` | Create a new animation project
`get_project` | Inspect project state, layers, and keyframes
`upsert_layer` | Create a layer or patch an existing one
`remove_layer` | Delete a layer from the project
`configure_project` | Update project dimensions, duration, FPS, background
`group_layers` | Group multiple layers together
`ungroup_layers` | Ungroup a layer group
`upload_media` | Request a presigned upload URL (cloud only)
`confirm_media_upload` | Confirm a completed upload (cloud only)
`import_media` | Import media from a public URL (cloud only)

## create_project

create_project

    {
      "name": "TikTok Intro",
      "width": 1080,
      "height": 1920
    }

Returns the project `id` and a preview URL. Use the `id` in every subsequent call.

## upsert_layer

One tool for creating and editing. Omit `layerId` to create (the `layer` field carries type + props; omitted props use schema defaults). Pass `layerId` to edit — everything is a patch.

upsert_layer — create a text layer with slide-in animation

    {
      "projectId": "your_project_id",
      "name": "Title",
      "layer": {
        "type": "text",
        "props": {
          "content": "Hello World",
          "fontSize": 64,
          "color": "#ffffff"
        }
      },
      "transform": {
        "position": { "x": 0, "y": -200 }
      },
      "animation": {
        "keyframes": [
          { "id": "kf1", "time": 0,   "property": "position.x", "value": -400, "easing": "ease-out" },
          { "id": "kf2", "time": 0.5, "property": "position.x", "value": 0 }
        ]
      }
    }

upsert_layer — create a shape with preset animation

    {
      "projectId": "your_project_id",
      "name": "Accent Shape",
      "layer": {
        "type": "shape",
        "props": {
          "shapeType": "rectangle",
          "background": { "type": "solid", "color": "#ff4455" }
        }
      },
      "transform": {
        "position": { "x": 0, "y": 300 },
        "scale": { "x": 0.8, "y": 0.1 }
      },
      "animation": {
        "preset": { "id": "fade-in", "startTime": 0.2, "duration": 0.4 }
      }
    }

### upsert_layer fields

Field | Type | Required | Description
--- | --- | --- | ---
`projectId` | string | ✓ | Project to operate on
`layerId` | string | — | Omit to create; pass an existing layer ID (or name) to edit
`layer` | object | create: ✓ | `{ type, props }` — see Layer Types below. On edit, only when changing props (type must match)
`name` | string | — | Display name
`transform` | object | — | Position, scale, rotation, anchor (deep patch)
`style` | object | — | Opacity, blur, filters, drop shadow (patch)
`enterTime` | number | — | When the layer appears (seconds, default 0)
`exitTime` | number | — | When the layer disappears (seconds)
`animation` | object | — | `{ preset?, keyframes? }` — can use both at once

upsert_layer — edit position and color of an existing layer

    {
      "projectId": "your_project_id",
      "layerId": "layer_abc",
      "transform": {
        "position": { "x": 100, "y": -200 }
      },
      "layer": {
        "type": "text",
        "props": { "color": "#ffcc00" }
      }
    }

On edit, `layer.props` are merged with existing props and validated against the layer’s schema; `transform` and `style` are deep patches — omitted fields keep their current values.

## remove_layer

remove_layer

    {
      "projectId": "your_project_id",
      "layerId": "layer_abc"
    }

`layerId` accepts either the layer’s ID or its display name.

## configure_project

configure_project — resize to landscape

    {
      "projectId": "your_project_id",
      "width": 1920,
      "height": 1080,
      "duration": 10,
      "backgroundColor": "#1a1a2e"
    }

All fields are optional. `backgroundColor` is a hex string.

## group_layers / ungroup_layers

group_layers

    {
      "projectId": "your_project_id",
      "layerIds": ["layer_abc", "layer_def"],
      "name": "Background Group"
    }

ungroup_layers

    {
      "projectId": "your_project_id",
      "groupId": "group_xyz"
    }

## Cloud Media Tools

Local projects use files directly from `assets/`. The tools below are only available on the cloud MCP server at `https://devmotion.app/mcp`.

### upload_media

Request a presigned URL for direct upload.

upload_media

    {
      "projectId": "your_project_id",
      "file_name": "demo.mp4",
      "mime_type": "video/mp4",
      "file_size": 1234567,
      "media_type": "video"
    }

Returns `upload_url`, `key`, `file_url`, and `asset_id`. Upload the file binary to `upload_url`, then call `confirm_media_upload`.

### confirm_media_upload

confirm_media_upload

    {
      "projectId": "your_project_id",
      "asset_id": "asset_abc",
      "key": "uploads/user/demo.mp4",
      "file_url": "https://assets.devmotion.app/uploads/user/demo.mp4",
      "original_name": "demo.mp4",
      "mime_type": "video/mp4",
      "media_type": "video",
      "duration": 4.2
    }

Use the returned asset URL as `src` when creating an image, video, or audio layer.

### import_media

import_media

    {
      "projectId": "your_project_id",
      "url": "https://example.com/demo.mp4",
      "media_type": "video",
      "file_name": "demo.mp4"
    }

Imports a public media URL into your DevMotion assets and returns the asset URL to use in layer props.

## Layer Types

Type | Key props
--- | ---
`text` | `content` (string), `fontSize`, `color`, `fontFamily`, `fontWeight`
`shape` | `shapeType` (`rectangle`/`ellipse`/`circle`/…), `background`
`image` | `src` (URL)
`video` | `src` (URL)
`group` | (no props — use `group_layers` instead)

## Keyframe Animation

Layers are animated by adding keyframes at specific times. DevMotion interpolates between them automatically using the easing curve you specify.

Pass keyframes inside `animation.keyframes` when creating with `upsert_layer`, or add them later by calling it again with the `layerId`.

### Animatable Properties

Property | Description
--- | ---
`position.x` / `position.y` | Position in pixels
`position.z` | Z depth
`scale.x` / `scale.y` | Scale (1 = 100%)
`rotation.x` / `rotation.y` / `rotation.z` | Rotation in degrees
`opacity` | Transparency (0–1)
`props.fontSize` | Font size (text layers)
`props.color` | Text color (hex)
`props.content` | Text content (typewriter)

### Keyframe schema

Each keyframe requires an `id` (any unique string — DevMotion replaces it internally):

    { "id": "kf1", "time": 0.5, "property": "position.y", "value": -200, "easing": "ease-out" }

### Easing Values

Value | Description
--- | ---
`linear` | Constant speed
`ease-in` | Starts slow, ends fast
`ease-out` | Starts fast, ends slow
`ease-in-out` | Slow at both ends
`bounce` | Elastic bounce at end

## Example Prompts

- “Create a 9:16 product showcase with a phone mockup image, a title, and a price tag that bounces in.”
- “Make a lower-third bar with white text on a semi-transparent dark background that slides in from the left.”
- “Build a 5-second countdown animation with a large number that scales up and fades out each second.”
- “Edit the ‘Headline’ layer to use yellow and add a shake animation.”