# Vidova
> Full markdown dump of https://vidova.ai/docs. Prefer /llms.txt plus one tool page when possible.

---
URL: https://vidova.ai/docs.md

# Vidova documentation

Local MCP for the Vidova desktop editor, plus custom elements authored with @vidova/2d, @vidova/core, and @vidova/components.

Vidova Local MCP is a Streamable HTTP server inside the desktop app. Coding agents call it on localhost. The editor must be open.

Custom elements are TSX classes that draw on the timeline. They import `@vidova/2d`, `@vidova/core`, and `@vidova/components`.

This site is the public reference. HTML is for people and search engines. The same pages are also available as Markdown so agents do not have to parse navigation.

## MCP

- [Vidova MCP](/docs/mcp): what it is, how to connect, tool map
- [Quickstart](/docs/mcp/quickstart): open a project, read state, change a clip
- [Tools](/docs/mcp/tools): every published tool
- [timeline_edit](/docs/mcp/tools/timeline_edit): clips, `vidovaSettings`, banana cursor

## Custom elements

- [Custom elements](/docs/custom-elements): what they are, how they land on a clip
- [Quickstart](/docs/custom-elements/quickstart): smallest working class, then place it
- [Packages](/docs/custom-elements/packages): `@vidova/2d`, `@vidova/core`, `@vidova/components`
- [Authoring](/docs/custom-elements/authoring): props, signals, `this.add()`, animation methods
- [Inputs](/docs/custom-elements/inputs): asset inputs, `inputDefs`, `componentInputs`
- [Shaders](/docs/custom-elements/shaders): SkSL on a cached node
- [Layout](/docs/custom-elements/layout): flex, `layout={false}`

## For agents

Fetch [llms.txt](/llms.txt) first. Links point at `.md` files. Then open one tool page or one authoring page, not the full dump, unless you need [llms-full.txt](/llms-full.txt).

The docs-only index is [/docs/llms.txt](/docs/llms.txt).

---
URL: https://vidova.ai/docs/custom-elements.md

# Custom elements

A custom element is a TSX class that extends Node. It compiles into a component asset and plays on a type=component clip.

A custom element is a TSX class that extends `Node`, or a closer built-in such as `Txt` or `Layout`. The class compiles into a component asset. The timeline plays it on a clip with `type` `component`.

JSX creates real nodes immediately. It is not React.

Prefer a catalog template when one already covers the design. Call [component](/docs/mcp/tools/component) with `action` `createFromTemplate`, then place the returned `assetId` with [timeline_edit](/docs/mcp/tools/timeline_edit) `addClip`. Write a class from scratch only when no template fits.

## Packages

Import from these three packages only:

| Package | Role |
| --- | --- |
| `@vidova/2d` | Nodes, JSX, `@signal` / `@initial` / `@colorSignal` |
| `@vidova/core` | Signals, generators, tweens, refs, easing |
| `@vidova/components` | Built-in scene nodes such as `ScreenRecording` and `FaceCamera` |

Details: [Packages](/docs/custom-elements/packages).

## Timeline contract

The exported class name is `componentName`. `animate()` is the method the timeline calls. `animateIn()` is the intro. Keep them separate. Layout and naming rules that fail at render: [Layout](/docs/custom-elements/layout).

The editor must be open. A create or edit that reports `FAILED TO RENDER` is a broken element. Fix it before you place the clip.

Asset inputs (`type: asset`) let a component take an image, video, audio, 3D model, or screen recording. The clip stores the asset ID. At preview the class receives a playback URL or a `VidovaClipData` object. [Inputs](/docs/custom-elements/inputs).

Shaders are SkSL on a cached node, not GLSL. [Shaders](/docs/custom-elements/shaders).

## Next

- [Quickstart](/docs/custom-elements/quickstart): smallest working class, then place it
- [Packages](/docs/custom-elements/packages): `@vidova/2d`, `@vidova/core`, `@vidova/components`
- [Authoring](/docs/custom-elements/authoring): props, constructor, methods
- [Inputs](/docs/custom-elements/inputs): `inputDefs`, asset inputs, `componentInputs`
- [Signals](/docs/custom-elements/signals): reactive props
- [Layout](/docs/custom-elements/layout): flex, `layout={false}`, naming
- [Shaders](/docs/custom-elements/shaders): SkSL, `cache`, `withCommonShader`
- [Animation](/docs/custom-elements/animation): generators, `animate` vs `animateIn`

---
URL: https://vidova.ai/docs/custom-elements/quickstart.md

# Custom element quickstart

Write a Node subclass with @vidova/2d, implement animateIn and animate, then place it with component create and timeline_edit addClip.

This path assumes Vidova is running, Local MCP is on, and a project is open in the editor. Install steps are on the [MCP overview](/docs/mcp).

## 1. Write the class

The exported class name must match `componentName`. `animate()` is the timeline entry point. `animateIn()` is the intro.

```tsx
import { Node, NodeProps, Txt, signal, initial, colorSignal } from '@vidova/2d';
import {
  SignalValue,
  SimpleSignal,
  ColorSignal,
  PossibleColor,
  easeOutCubic,
  type ThreadGenerator,
} from '@vidova/core';

export interface HelloTitleProps extends NodeProps {
  label?: SignalValue<string>;
  textColor?: SignalValue<PossibleColor>;
  textSize?: SignalValue<number>;
}

export class HelloTitle extends Node {
  @initial('Hello')
  @signal()
  public declare readonly label: SimpleSignal<string, this>;

  @initial('#ffffff')
  @colorSignal()
  public declare readonly textColor: ColorSignal<this>;

  @initial(48)
  @signal()
  public declare readonly textSize: SimpleSignal<number, this>;

  public constructor(props?: HelloTitleProps) {
    super({ ...props });
    this.add(
      <Txt
        text={() => this.label()}
        fill={() => this.textColor()}
        fontSize={() => this.textSize()}
        fontFamily="Inter Variable"
        fontWeight={600}
      />,
    );
  }

  public *animateIn(duration: number = 0.4): ThreadGenerator {
    this.opacity(0);
    yield* this.opacity(1, duration, easeOutCubic);
  }

  public *animate(duration?: number): ThreadGenerator {
    yield* this.animateIn(duration ?? 0.4);
  }
}
```

Use the exact `fontFamily` string. `Inter Variable` is the default UI font. Code text uses `Fira Code Variable`.

## 2. Create the asset

Call [component](/docs/mcp/tools/component) with `action` `create`:

```json
{
  "action": "create",
  "name": "Hello title",
  "componentName": "HelloTitle",
  "code": "<the TSX above>"
}
```

The result includes `assetId`. If the tool reports `FAILED TO RENDER`, fix the class before you place it.

## 3. Place it on the timeline

Call [timeline_edit](/docs/mcp/tools/timeline_edit) with `action` `addClip`, `type` `component`, and that `assetId`. Never `type=text`.

## 4. Capture a preview

Call `preview` with `action` `captureFrame` at a timecode where the clip is visible. Confirm the text is on screen and fully inside the frame.

A catalog template is faster when one already covers the design. Use `createFromTemplate` instead of `create`. Full props and methods: [Authoring](/docs/custom-elements/authoring).

---
URL: https://vidova.ai/docs/mcp.md

# Vidova MCP

Connect Cursor, Claude Code, Codex, or Windsurf to the local Vidova desktop editor at http://127.0.0.1:17373/mcp.

Vidova Local MCP is a Streamable HTTP endpoint on the desktop app. Server name is `vidova-desktop`. URL is `http://127.0.0.1:17373/mcp`. There is no HTTP auth. Traffic never leaves the machine except when a tool starts a hosted job.

## Prerequisites

1. Vidova desktop is running.
2. Local MCP is enabled. Fresh installs leave it on.
3. A project is active. Use `get_active_project` or `set_active_project`.
4. The editor window for that project is open. Editor tools fail if it is not.

Project tools (`list_projects`, `get_active_project`, `create_project`, `set_active_project`) work without the editor. Everything else requires the editor.

## One-click install

The app can write the local endpoint into the client config. You can also add it by hand. The MCP server name in client configs is `vidova`.

| Client | Config | Entry |
| --- | --- | --- |
| Cursor | `~/.cursor/mcp.json` | `{ "mcpServers": { "vidova": { "url": "http://127.0.0.1:17373/mcp" } } }` |
| Windsurf | `~/.codeium/windsurf/mcp_config.json` | `{ "mcpServers": { "vidova": { "serverUrl": "http://127.0.0.1:17373/mcp" } } }` |
| Claude Code | `~/.claude.json` plus `claude mcp add --transport http --scope user vidova http://127.0.0.1:17373/mcp` | HTTP / streamable-http URL |
| Codex | `~/.codex/config.toml` plus `codex mcp add vidova --url http://127.0.0.1:17373/mcp` | streamable HTTP URL |

Restart the client after install when the app says a restart is required.

## Tool map

Eighteen tools are published. Open a page for every field.

| Job | Tool |
| --- | --- |
| List or switch projects | [list_projects](/docs/mcp/tools/list_projects), [get_active_project](/docs/mcp/tools/get_active_project), [set_active_project](/docs/mcp/tools/set_active_project), [create_project](/docs/mcp/tools/create_project) |
| Read the timeline | [timeline_get_state](/docs/mcp/tools/timeline_get_state) |
| Edit clips | [timeline_edit](/docs/mcp/tools/timeline_edit) |
| Zooms and chroma key | [clip_enhance](/docs/mcp/tools/clip_enhance) |
| Assets, captions, transcribe | [asset](/docs/mcp/tools/asset) |
| Inspect media | [inspect_media](/docs/mcp/tools/inspect_media) |
| Import | [import_asset](/docs/mcp/tools/import_asset) |
| Preview | [preview](/docs/mcp/tools/preview) |
| Image and speech | [generate_asset](/docs/mcp/tools/generate_asset) |
| Sound effects | [sfx](/docs/mcp/tools/sfx) |
| Components | [component](/docs/mcp/tools/component) |
| Branches | [branch_action](/docs/mcp/tools/branch_action) |
| Undo | [project_history](/docs/mcp/tools/project_history) |
| Recipes | [recipe](/docs/mcp/tools/recipe) |
| Poll wait | [sleep](/docs/mcp/tools/sleep) |

Cursor, camera overlay, layout, and captions are `vidovaSettings` on `timeline_edit` `updateClip`. There is no `vidova_set_cursor` tool.

## FAQ

**Can I edit Vidova from Cursor or Claude?** Yes. The desktop app must be running. Local MCP must be enabled. The editor must be open. See the install table above.

**Does this use hosted quota?** Most calls are local. [generate_asset](/docs/mcp/tools/generate_asset) image uses the image-generation allowance. Speech and `asset` transcribe use included quotas. Details: [quotas](/docs/mcp/quotas).

**How do I set the banana cursor?** `timeline_edit` action `updateClip` with `vidovaSettings.cursorStyle` set to `banana`. Field spec: [vidovaSettings](/docs/mcp/schemas/vidova-settings).

---
URL: https://vidova.ai/docs/custom-elements/packages.md

# @vidova packages

Custom elements import @vidova/2d for nodes and JSX, @vidova/core for signals and tweens, and @vidova/components for built-in scene nodes.

Custom element source imports three packages. JSX is compiled with `@vidova/2d` as the JSX source. Do not import React.

## `@vidova/2d`

Nodes, JSX, and property decorators.

| Export | Use |
| --- | --- |
| `Node`, `NodeProps` | Base class and props for a custom element |
| `Rect`, `Circle`, `Txt`, `Layout` | Shapes, text, flex containers |
| `Code` | Syntax-highlighted code. Set `letterSpacing` to `0` and `fontFamily` to `Fira Code Variable` |
| `Line`, `Path`, `QuadBezier` | Vector drawing |
| `Img`, `Video` | Bitmap and video. Call `videoRef().play()` directly. Do not `spawn(videoRef().play())` |
| `Gradient` | Fills |
| `@signal`, `@initial`, `@colorSignal` | Class property decorators |

```tsx
import { Node, NodeProps, Txt, Rect, signal, initial } from '@vidova/2d';
```

## `@vidova/core`

Signals, generator types, flow helpers, and easing.

| Export | Use |
| --- | --- |
| `SignalValue`, `SimpleSignal`, `ColorSignal`, `PossibleColor` | Prop and field types |
| `ThreadGenerator` | Return type of `animate()` and `animateIn()` |
| `waitFor`, `tween`, `all` | Timing and parallel tweens |
| `createRef` | Hold a child node for later animation |
| `easeOutCubic`, `easeInOutCubic` | Timing functions |
| `withCommonShader` | Prepend the standard SkSL prelude to a fragment body |

```tsx
import {
  SignalValue,
  SimpleSignal,
  all,
  easeOutCubic,
  withCommonShader,
  type ThreadGenerator,
} from '@vidova/core';
```

`createSignal` exists for local values inside a method. Do not use it for class props. Declare those with `@initial` and `@signal`. See [Signals](/docs/custom-elements/signals).

## `@vidova/components`

Built-in scene nodes. Use these when an element needs recording footage, the camera overlay, or the same cursor and caption chrome as the editor.

| Export | Use |
| --- | --- |
| `ScreenRecording` | Screen-recording surface |
| `FaceCamera` | Camera overlay |
| `AnimatedCursor` | Cursor overlay |
| `AnimatedCaptions` | Caption renderer |
| `AnimatedKeybindings` | Keystroke overlay |
| `ClickEffect` | Click burst |
| `MouseIndicator` | Mouse highlight |
| `BackgroundImage` | Still background |
| `ThreeViewport` | 3D viewport |
| `VidovaClipData` | Type for a `vidova` asset input |

```tsx
import { ScreenRecording, FaceCamera } from '@vidova/components';
```

Asset inputs of type `vidova` resolve to a `VidovaClipData` object (screen, camera, cursor, click, keyboard). Image, video, audio, and model3d asset inputs resolve to playback URLs. The clip still stores asset IDs. Use `@initial('')` on URL signals. Details: [Inputs](/docs/custom-elements/inputs). SkSL on a cached node: [Shaders](/docs/custom-elements/shaders).

Most catalog templates import only `@vidova/2d` and `@vidova/core`. Reach for `@vidova/components` when the element wraps editor footage, not when it is a title or chip.

---
URL: https://vidova.ai/docs/mcp/quickstart.md

# Vidova Cursor MCP quickstart

Open a Vidova project from Cursor or Claude, read the timeline, capture a preview, and set vidovaSettings.cursorStyle to banana.

This path assumes Vidova is running, Local MCP is on, and a project is open in the editor. Install steps are on the [overview](/docs/mcp).

## 1. Confirm the project

Call `get_active_project`. If nothing is active, call `list_projects` and then `set_active_project` with that `projectId`.

Editor tools fail until the matching editor window is open.

## 2. Read the timeline

Call `timeline_get_state`. Use the clip ids and layer ids it returns. Do not invent ids.

## 3. Capture one preview

Call `preview` with `action` `captureFrame` and `timecode` `0` (zero is valid). Confirm the composition rendered before you edit.

## 4. Change a screen-recording clip

This is a real `timeline_edit` call that sets the banana cursor on a Vidova clip:

```json
{
  "action": "updateClip",
  "clipId": "CLIP_ID_FROM_STATE",
  "vidovaSettings": {
    "cursorStyle": "banana"
  }
}
```

`cursorStyle` is an enum on [vidovaSettings](/docs/mcp/schemas/vidova-settings). `banana` is a valid value. There is no `vidova_set_cursor` tool.

After the edit, capture `preview` `captureFrame` again at a timecode where the cursor is visible.

## 5. Page large results

If a tool result is truncated, pass `resultStart` and `resultEnd`. The window is at most 8000 characters. Increment `resultStart` by 8000 to read the next window.

Full field lists: [timeline_edit](/docs/mcp/tools/timeline_edit), [preview](/docs/mcp/tools/preview).

---
URL: https://vidova.ai/docs/custom-elements/authoring.md

# Authoring a custom element

Define a props interface with SignalValue, extend Node, wire @initial and @signal, add children in the constructor, then implement animateIn and animate.

A custom element is a class. It extends `Node` or a closer built-in. It takes a props interface. It builds a child tree in the constructor. It exposes generator methods for animation.

Start from a catalog template when one already covers the design. This page is the from-scratch path.

## Props

Every custom prop is wrapped in `SignalValue`. Extend `NodeProps` (or `LayoutProps` / `Txt` props) so position, opacity, and scale stay available.

```tsx
import { Node, NodeProps } from '@vidova/2d';
import { SignalValue, PossibleColor } from '@vidova/core';

export interface HelloTitleProps extends NodeProps {
  label?: SignalValue<string>;
  textColor?: SignalValue<PossibleColor>;
  textSize?: SignalValue<number>;
}
```

Use `PossibleColor` for color props so callers can pass a hex string. Extend `Layout` and `LayoutProps` when the element is itself a flex container.

## Class

The class must extend `Node` or one of its subclasses. Pick the closest built-in. A title that is only text can extend `Txt`. A chip with a background extends `Node` and adds a `Rect` plus a `Txt`.

```tsx
export class HelloTitle extends Node {
  // implementation
}
```

The exported class name is `componentName` on the [component](/docs/mcp/tools/component) `create` call.

## Signals

Each prop on the interface needs a class field of the same name. Decorate it with `@initial` and `@signal`. Colors use `@colorSignal` and `ColorSignal`.

```tsx
export class HelloTitle extends Node {
  @initial('Hello')
  @signal()
  public declare readonly label: SimpleSignal<string, this>;

  @initial('#ffffff')
  @colorSignal()
  public declare readonly textColor: ColorSignal<this>;

  @initial(48)
  @signal()
  public declare readonly textSize: SimpleSignal<number, this>;
}
```

Fields use `public`, `declare`, and `readonly`. `@signal` is required for every prop you accept. `@initial` sets the value when the caller omits it.

Do not name a field after a `Node` member. `draw`, `size`, `scale`, `opacity`, `position`, and the rest of that list overwrite the real method or property. The element then draws nothing, with no compile error. Full list: [Layout](/docs/custom-elements/layout).

How signals update: [Signals](/docs/custom-elements/signals).

## Constructor

Pass props to `super`. Then `this.add()` the child tree, the same way a scene adds to its view.

```tsx
public constructor(props?: HelloTitleProps) {
  super({ ...props });
  this.add(
    <Txt
      text={() => this.label()}
      fill={() => this.textColor()}
      fontSize={() => this.textSize()}
      fontFamily="Inter Variable"
      fontWeight={600}
    />,
  );
}
```

Bind child props to functions that read the class signals. A one-shot `text` assignment that calls `label()` will not update when `label` changes.

You can pin a built-in prop in `super` when it must always be on:

```tsx
super({
  layout: true,
  ...props,
});
```

## Animation methods

Generator methods on the class are how you animate the element. The timeline calls `animate()`. Thumbnails play `animateIn()`. Keep them as two methods. Details: [Animation](/docs/custom-elements/animation).

```tsx
public *animateIn(duration: number = 0.4): ThreadGenerator {
  this.opacity(0);
  yield* this.opacity(1, duration, easeOutCubic);
}

public *animate(duration?: number): ThreadGenerator {
  yield* this.animateIn(duration ?? 0.4);
}
```

## Full source

```tsx
import { Node, NodeProps, Txt, signal, initial, colorSignal } from '@vidova/2d';
import {
  SignalValue,
  SimpleSignal,
  ColorSignal,
  PossibleColor,
  easeOutCubic,
  type ThreadGenerator,
} from '@vidova/core';

export interface HelloTitleProps extends NodeProps {
  label?: SignalValue<string>;
  textColor?: SignalValue<PossibleColor>;
  textSize?: SignalValue<number>;
}

export class HelloTitle extends Node {
  @initial('Hello')
  @signal()
  public declare readonly label: SimpleSignal<string, this>;

  @initial('#ffffff')
  @colorSignal()
  public declare readonly textColor: ColorSignal<this>;

  @initial(48)
  @signal()
  public declare readonly textSize: SimpleSignal<number, this>;

  public constructor(props?: HelloTitleProps) {
    super({ ...props });
    this.add(
      <Txt
        text={() => this.label()}
        fill={() => this.textColor()}
        fontSize={() => this.textSize()}
        fontFamily="Inter Variable"
        fontWeight={600}
      />,
    );
  }

  public *animateIn(duration: number = 0.4): ThreadGenerator {
    this.opacity(0);
    yield* this.opacity(1, duration, easeOutCubic);
  }

  public *animate(duration?: number): ThreadGenerator {
    yield* this.animateIn(duration ?? 0.4);
  }
}
```

Place it with [component](/docs/mcp/tools/component) `create` and [timeline_edit](/docs/mcp/tools/timeline_edit) `addClip`. Walkthrough: [Quickstart](/docs/custom-elements/quickstart). Asset slots and `inputDefs`: [Inputs](/docs/custom-elements/inputs). SkSL: [Shaders](/docs/custom-elements/shaders).

---
URL: https://vidova.ai/docs/mcp/architecture.md

# Vidova MCP architecture

Localhost Streamable HTTP MCP at 127.0.0.1:17373, no HTTP auth, 1MB body, 5 minute timeout, 8000-character result windows, and grouped-tool passthrough.

## Endpoint

- Host: `127.0.0.1`
- Port: `17373` unless `VIDOVA_APP_MCP_PORT` is set
- Path: `/mcp`
- Protocol: Streamable HTTP, POST only
- Server name: `vidova-desktop`

The process binds localhost only. There is no HTTP authentication. Firebase is used only when a tool needs SFX search or image vectorize.

## Limits

- JSON body: at most 1,048,576 bytes
- Dispatch timeout: 5 minutes (300,000 ms)
- Result window: `resultStart` / `resultEnd`, at most 8000 characters per window

Sleep in the MCP server waits in-process. The renderer `sleep` tool is 1 to 60 seconds. Prefer the advertised MCP `seconds` field and keep waits short between `generate_asset` status polls.

## Grouped tools and passthrough

Several MCP tools are grouped. `listTools` advertises `action` or `kind` plus a small field set, then **passthrough**. Extra fields are not rejected at the MCP wrapper. The renderer validates the child schema for that action.

That is why `timeline_edit` `updateClip` accepts `vidovaSettings` even though the advertised schema does not list it. Authoritative child fields are on each [tool page](/docs/mcp/tools).

## Ask mode

Grouped mutating actions are rejected in Ask mode. Read actions still run. `project_history` allows `status` in Ask mode and rejects `undo` / `redo`.

## Locks

The editor serializes tool work with resource locks: timeline, components, assets, project, recipes, and an exclusive render lock for preview capture. Parallel MCP calls that write the same project wait. Do not assume two writes ran at once.

## Branch merge approval

`branch_action` `merge` and `mergeToMain` require approval. A rejected merge leaves the project unchanged.

## Editor must be open

Project tools talk to the local project store. Editor tools dispatch into the open renderer. If no editor is registered for the active project, the call fails with a message to open the project in Vidova.

---
URL: https://vidova.ai/docs/custom-elements/inputs.md

# Component inputs

inputDefs are static inspector values. Asset inputs store IDs on the clip and resolve to playback URLs or VidovaClipData before they reach the class.

`inputDefs` are static values on the clip. The inspector sets them. They do not tween. Animation still lives in generators and class signals. See [Animation](/docs/custom-elements/animation).

## Types

| `type` | Clip value | Class signal |
| --- | --- | --- |
| `string` | string | `SimpleSignal<string, this>` |
| `number` | number | `SimpleSignal<number, this>` |
| `boolean` | boolean | `SimpleSignal<boolean, this>` |
| `color` | hex string | `ColorSignal<this>` with `@colorSignal` |
| `enum` | one of `options` | `SimpleSignal<string, this>` |
| `font` | family string | `SimpleSignal<string, this>` |
| `asset` | **asset ID** on the clip | playback URL string, or `VidovaClipData` |

Each def needs `name`, `type`, and `default`. `label` is optional. `enum` needs `options`. `asset` needs `assetTypes`.

## Asset contract

The clip stores an asset UUID in `inputs` and in `inputDefs.default`. At preview and render, Vidova replaces that ID before the class constructor runs.

| `assetTypes` | Runtime prop |
| --- | --- |
| `['image']` | playback URL string |
| `['video']` | playback URL string |
| `['audio']` | playback URL string |
| `['model3d']` | playback URL string |
| `['vidova']` | `VidovaClipData` object |

Do not mix kinds on one input. An image slot is `assetTypes: ['image']` only.

The class signal for a URL asset **must** use `@initial('')`. Never put the UUID in `@initial`. `inputDefs.default` may be an asset ID. `@initial` must not.

```tsx
@initial('')
@signal()
public declare readonly image: SimpleSignal<string, this>;
```

Pass that signal to the media node with explicit size:

```tsx
<Img
  src={() => this.image()}
  width={() => this.frameWidth()}
  height={() => this.frameHeight()}
/>
```

Empty string is a no-op. A UUID is not a URL. `<Img>` will refuse it.

For screen recordings:

```tsx
import { ScreenRecording, FaceCamera, type VidovaClipData } from '@vidova/components';

@initial(undefined)
@signal()
public declare readonly screen: SimpleSignal<VidovaClipData | undefined, this>;
```

Use fields on `this.screen()` (`screenSrc`, `cameraSrc`, cursor arrays). Do not pass the whole object to `<Video src>`.

## Timeline

After [component](/docs/mcp/tools/component) `create` or `edit`, place **one** clip:

```
timeline_edit addClip
  type: component
  assetId: <component asset id>
  componentInputs: { image: "<image asset id>" }
```

Do not add a parallel `type: image` or `type: video` clip for the same file. The component input **is** the media. A leftover still on the timeline means the shader never ran.

`componentInputs` overrides `inputDefs.default`. Both store asset IDs, not URLs.

## Example

```json
[
  {
    "name": "image",
    "type": "asset",
    "default": "",
    "label": "Image",
    "assetTypes": ["image"]
  },
  {
    "name": "refraction",
    "type": "number",
    "default": 0.04,
    "label": "Refraction"
  }
]
```

`refraction` is a static knob. If it should move over time, keep a class signal and tween it in `animate()` instead of expecting the input to change.

Shaders that sample this image: [Shaders](/docs/custom-elements/shaders).

---
URL: https://vidova.ai/docs/custom-elements/signals.md

# Signals

Class props are signals. Read with label(), write with label(value), tween with yield* label(next, duration). Bind children with () => this.label().

A signal is a value that can change over time. Other values that read it update when it changes.

On a custom element, every public prop is a signal. Declare it with `@initial` and `@signal` on the class. Do not store animated state in a plain field or a hand-rolled `createSignal` on the class.

## Three calls

The action depends on how many arguments you pass.

Read:

```ts
const value = this.label();
```

Write immediately:

```ts
this.label('Hello');
```

Tween (inside a generator):

```ts
yield* this.label('Hello', 0.3);
```

Colors work the same after `@colorSignal`:

```ts
yield* this.textColor('#68ABDF', 0.4);
```

## Bind children to functions

Pass a function into JSX so the child keeps reading the signal:

```tsx
this.add(
  <Txt
    text={() => this.label()}
    fill={() => this.textColor()}
    fontSize={() => this.textSize()}
  />,
);
```

A one-shot `text` assignment that calls `label()` copies the string once. Later edits to `label` will not reach the `Txt`.

A signal can also compute from other signals:

```ts
const width = () => this.label().length * this.textSize() * 0.55 + this.textSize();
```

Use that pattern when a chip or keycap must size to its string. Do not let flex measure the `Txt`. See [Layout](/docs/custom-elements/layout).

## Class signals vs `createSignal`

`createSignal` from `@vidova/core` is for a local value inside a method. It is not a replacement for a class prop.

Forbidden for props and animated class state:

```ts
// Wrong. Not a class signal. Tweening it does not update the element.
const label = createSignal('Hello');
```

Required:

```tsx
@initial('Hello')
@signal()
public declare readonly label: SimpleSignal<string, this>;
```

Do not cast a closure to `SimpleSignal`. It is not reactive and never animates.

Node properties are already signals. `this.opacity()`, `this.scale()`, and `this.position()` tween the same way. Do not declare a class field with those names. The field overwrites the node property.

How to wire props onto a class: [Authoring](/docs/custom-elements/authoring). How to sequence tweens: [Animation](/docs/custom-elements/animation).

---
URL: https://vidova.ai/docs/mcp/tools.md

# Vidova MCP tools

Index of every published Vidova Local MCP tool, including timeline_edit, generate_asset, and project tools.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

Eighteen published local MCP tools. Open a page for every field. Grouped tools document advertised fields and renderer child fields separately.

| MCP name | Renderer name | Quota |
| --- | --- | --- |
| [`list_projects`](/docs/mcp/tools/list_projects) | — | local |
| [`get_active_project`](/docs/mcp/tools/get_active_project) | — | local |
| [`create_project`](/docs/mcp/tools/create_project) | — | local |
| [`set_active_project`](/docs/mcp/tools/set_active_project) | — | local |
| [`timeline_get_state`](/docs/mcp/tools/timeline_get_state) | getTimelineState | local |
| [`timeline_edit`](/docs/mcp/tools/timeline_edit) | timelineEdit | local |
| [`clip_enhance`](/docs/mcp/tools/clip_enhance) | clipEnhance | local |
| [`asset`](/docs/mcp/tools/asset) | asset | List, search, metadata, notes, and captions are local. action transcribe starts a hosted transcription job. |
| [`inspect_media`](/docs/mcp/tools/inspect_media) | inspectMedia | local |
| [`import_asset`](/docs/mcp/tools/import_asset) | importAsset | local |
| [`preview`](/docs/mcp/tools/preview) | preview | local |
| [`generate_asset`](/docs/mcp/tools/generate_asset) | generateAsset | Image generation uses your image-generation allowance. Speech is included with a usage quota. |
| [`sfx`](/docs/mcp/tools/sfx) | sfx | local |
| [`component`](/docs/mcp/tools/component) | component | local |
| [`branch_action`](/docs/mcp/tools/branch_action) | branchAction | local |
| [`project_history`](/docs/mcp/tools/project_history) | projectHistory | local |
| [`recipe`](/docs/mcp/tools/recipe) | recipe | local |
| [`sleep`](/docs/mcp/tools/sleep) | sleep | local |

Retired names such as `web_research` and `vidova_set_cursor` are listed on [Not in MCP](/docs/mcp/not-in-mcp).

---
URL: https://vidova.ai/docs/custom-elements/layout.md

# Layout

Do not shadow Node methods, do not flex-size to unmeasured text, match anchors to coordinates, and keep sizes proportional to the frame.

Layout uses Flexbox on a hidden DOM tree. Text size is measured before the webfont loads, and offscreen before the node joins a document. Most broken custom elements come from that.

Flex is for placement inside a container that already has an explicit `width` and `height`. It is not for measuring content.

## Do not shadow `Node` members

Never name a class field after a `Node` method or property. The field overwrites the real member. The element compiles and then draws nothing, or crashes at render.

Do not use these names for `@signal` fields:

`draw`, `render`, `size`, `position`, `scale`, `opacity`, `cache`, `key`, `children`, `add`, `remove`, `view`, `parent`, `clip`, `filters`, `x`, `y`, `width`, `height`, `fill`, `stroke`, `rotation`, `zIndex`

Prefix intent: `drawProgress`, `revealProgress`, `textSize`.

## Do not flex-size to text you drew

A `Rect` that hugs a `Txt` is measured with a fallback font. After the real font loads, the label clips.

Compute width from the string instead:

```ts
const CHARACTER_WIDTH_RATIO = 0.55; // ~0.62 for monospace
const textWidth = this.label().length * this.textSize() * CHARACTER_WIDTH_RATIO;
const capWidth = Math.max(this.capHeight(), textWidth + this.textSize());
```

Give that number to the `Rect` as `width`. Then place children with `layout` inside that fixed box.

Set an explicit `width` on wrapping text and use `textWrap`. Do not rely on a manual newline inside `Txt`.

## Anchors and coordinates

Vidova uses a center origin. X increases to the right. Y increases downward. Do not treat the origin as top-left.

`offsetX` of `-1` means x is the left edge. Passing a center-based x then shifts the node by half its width. Derive both from one helper: an anchor of -1, 0, or 1, and the matching coordinate.

## Sizes follow the frame

Hard-coded pixel margins that look right at 1920x1080 are wrong at the 480x270 thumbnail. Express insets as a fraction of the frame.

Hidden means hidden in every dimension. Setting `visible` to `false` is not enough if a stroked rect still draws. Zero opacity or size as well.

## `Code` letter spacing

`Code` reads letter spacing from computed CSS, not from its signal. That CSS is `normal` until the element joins the document. Set `letterSpacing` to `0` on every `Code` node.

Code text uses `fontFamily="Fira Code Variable"`. Do not pass a CSS font stack. The family string must match a bundled font exactly. UI text uses `Inter Variable`.

## `layout` on a root

`layout` on a container with explicit `width` and `height` is safe. `layout` where the container size falls out of its children is where measurement bites.

```tsx
<Rect layout width={480} height={72} gap={16} alignItems="center">
  <Circle width={24} height={24} />
  <Txt text={() => this.label()} fontSize={28} fontFamily="Inter Variable" />
</Rect>
```

The `Rect` has a fixed size. The `Txt` does not decide the box.

## `layout={false}` overlays; it does not stack

Children with `layout={false}` **do not occupy flex space**. They overlay siblings. The parent size ignores them.

Use `layout={false}` only for overlay animation: a measured in-flow sibling sets the box, and a second copy with `layout={false}` moves or fades on top of it.

Stacked cards, counters, labels, and image-plus-chrome must stay **in the layout flow** with explicit `width` and `height`. If you mark the visible stack `layout={false}`, it draws on top of the previous child and the parent collapses.

```tsx
<Rect layout width={480} height={220} direction="column" gap={12} alignItems="center">
  <Rect width={480} height={160} fill="#111" />
  <Txt text={() => this.label()} fontSize={28} fontFamily="Inter Variable" />
</Rect>
```

Both children participate in flex. The photo and the caption take height.

Signal bindings for labels: [Signals](/docs/custom-elements/signals). Intro vs timeline playback: [Animation](/docs/custom-elements/animation). Asset images inside a stack: [Inputs](/docs/custom-elements/inputs).

---
URL: https://vidova.ai/docs/mcp/schemas.md

# Vidova MCP schemas

Nested objects used by Vidova MCP, including vidovaSettings, perspective, zooms, and scene config.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

Nested objects shared by MCP tools. `vidovaSettings` is the cursor, camera, layout, and caption patch for screen-recording clips.

| Schema | Zod export |
| --- | --- | --- |
| [vidovaSettings](/docs/mcp/schemas/vidova-settings) | `vidovaSettingsSchema` |
| [perspective](/docs/mcp/schemas/perspective) | `perspectiveObjectSchema` |
| [colorGrading](/docs/mcp/schemas/color-grading) | `colorGradingSchema` |
| [chromaKey](/docs/mcp/schemas/chroma-key) | `chromaKeySchema` |
| [focus](/docs/mcp/schemas/focus) | `focusSchema` |
| [cameraSettings](/docs/mcp/schemas/camera-settings) | `cameraSettingsSchema` |
| [clipTransition](/docs/mcp/schemas/clip-transition) | `clipTransitionSchema` |
| [keyframeAction](/docs/mcp/schemas/keyframe-action) | `keyframeActionSchema` |
| [zoomSegment](/docs/mcp/schemas/zoom-segment) | `zoomSegmentSchema` |
| [zoomDepth](/docs/mcp/schemas/zoom-depth) | `zoomDepthInputSchema` |
| [setSceneConfig](/docs/mcp/schemas/set-scene-config) | `setSceneConfigSchema` |
| [vector](/docs/mcp/schemas/vector) | `vectorSchema` |
| [normalizedVector](/docs/mcp/schemas/normalized-vector) | `normalizedVectorSchema` |
| [vidovaSettings.camera](/docs/mcp/schemas/vidova-camera) | `vidovaCameraSettingsSchema` |
| [vidovaSettings.crop](/docs/mcp/schemas/vidova-crop) | `vidovaCropSettingsSchema` |
| [vidovaSettings.mouseIndicator](/docs/mcp/schemas/mouse-indicator) | `vidovaMouseIndicatorSettingsSchema` |
| [cursorSpotlight](/docs/mcp/schemas/cursor-spotlight) | `cursorSpotlightUpdateSchema` |
| [captionSettings](/docs/mcp/schemas/caption-settings) | `captionSettingsUpdateSchema` |

---
URL: https://vidova.ai/docs/custom-elements/shaders.md

# Shaders

SkSL runtime effects on cached nodes. Include the common prelude or wrap the body with withCommonShader. Not GLSL.

Shaders are **SkSL** runtime effects. They are not GLSL. Do not write `#version 300 es`, `void main()`, `sampler2D`, `texture()`, or `outColor`.

The entry point is `half4 main(float2 coord)`.

## Cached node

Put `cache` on the node that owns the shader. Children render into a texture. The fragment samples that texture. Use `cachePadding` if the effect bleeds past the box.

```tsx
<Rect
  cache
  cachePadding={48}
  width={() => this.frameWidth()}
  height={() => this.frameHeight()}
  shaders={{
    fragment: GLASS_SKSL,
    uniforms: {
      uRefraction: () => this.refraction(),
    },
  }}
>
  <Img
    src={() => this.image()}
    width={() => this.frameWidth()}
    height={() => this.frameHeight()}
  />
</Rect>
```

The image is a child of the cached rect. It is an **asset input**, not a second timeline clip. See [Inputs](/docs/custom-elements/inputs).

## Prelude

Every useful fragment needs `sourceTexture`, `sampleSource`, and `computeSourceUV`. Two equivalent ways to get them:

**Include** at the top of the inline fragment:

```sksl
#include "@vidova/core/shaders/common.sksl"

half4 main(float2 coord) {
    float2 uv = computeSourceUV(coord);
    return sampleSource(uv);
}
```

**Or** wrap the body:

```ts
import { withCommonShader } from '@vidova/core';

const PASS_THROUGH = withCommonShader(`
half4 main(float2 coord) {
    float2 uv = computeSourceUV(coord);
    return sampleSource(uv);
}
`);
```

Custom components are a single `.tsx` file. Vidova expands that include before the runtime effect compiles. You do not import a separate `.sksl` file.

## Helpers and uniforms

From the prelude:

| Name | Role |
| --- | --- |
| `sampleSource(uv)` | Sample the cached node. `uv` is 0–1 |
| `computeSourceUV(coord)` | Convert fragment `coord` to source UV |
| `sourceTexture` | The cached children |
| `sourceSize`, `sourceTexelSize` | Cache size in pixels |
| `resolution` | Node size |
| `time`, `deltaTime`, `framerate`, `frame` | Playback clock |

System uniforms are injected. You still declare them by including the prelude (or `withCommonShader`). Do not paste a fake GLSL preamble.

Destination sampling (what's already on screen) only happens if the fragment also declares `uniform shader destinationTexture`. Most image effects sample **source only**.

## Custom uniforms

Keys on `shaders.uniforms` become SkSL uniform names. Signals are allowed.

| TypeScript | SkSL |
| --- | --- |
| `number` | `float` |
| `[number, number]` | `float2` |
| `[number, number, number]` | `float3` |
| `[number, number, number, number]` | `float4` |

```tsx
shaders={{
  fragment: GLASS_SKSL,
  uniforms: {
    uRefraction: () => this.refraction(),
    uFrost: () => this.frost(),
  },
}}
```

```sksl
uniform float uRefraction;
uniform float uFrost;
```

## Pass-through

```ts
import { withCommonShader } from '@vidova/core';

const PASS_THROUGH = withCommonShader(`
half4 main(float2 coord) {
    return sampleSource(computeSourceUV(coord));
}
`);
```

## Glass on an image input

Declare an image asset input. Keep `@initial('')` on the signal. Wrap `<Img src={this.image} />` in a cached `Rect` and run SkSL on that cache.

```tsx
import { Node, NodeProps, Img, Rect, signal, initial } from '@vidova/2d';
import { SignalValue, SimpleSignal, withCommonShader } from '@vidova/core';

const GLASS_SKSL = withCommonShader(`
uniform float uRefraction;

half4 main(float2 coord) {
    float2 uv = computeSourceUV(coord);
    float2 warped = uv + (uv - 0.5) * uRefraction;
    return sampleSource(warped);
}
`);

export interface GlassImageProps extends NodeProps {
  image?: SignalValue<string>;
  refraction?: SignalValue<number>;
  frameWidth?: SignalValue<number>;
  frameHeight?: SignalValue<number>;
}

export class GlassImage extends Node {
  @initial('')
  @signal()
  public declare readonly image: SimpleSignal<string, this>;

  @initial(0.04)
  @signal()
  public declare readonly refraction: SimpleSignal<number, this>;

  @initial(1600)
  @signal()
  public declare readonly frameWidth: SimpleSignal<number, this>;

  @initial(900)
  @signal()
  public declare readonly frameHeight: SimpleSignal<number, this>;

  public constructor(props?: GlassImageProps) {
    super({ ...props });
    this.add(
      <Rect
        cache
        cachePadding={32}
        width={() => this.frameWidth()}
        height={() => this.frameHeight()}
        shaders={{
          fragment: GLASS_SKSL,
          uniforms: { uRefraction: () => this.refraction() },
        }}
      >
        <Img
          src={() => this.image()}
          width={() => this.frameWidth()}
          height={() => this.frameHeight()}
        />
      </Rect>,
    );
  }
}
```

`inputDefs` for that class:

```json
[
  { "name": "image", "type": "asset", "default": "", "assetTypes": ["image"] },
  { "name": "refraction", "type": "number", "default": 0.04 }
]
```

Place **only** the component clip. Pass the image asset ID in `componentInputs.image`. Do not add a separate image clip underneath.

## Failures

| What you wrote | What happens |
| --- | --- |
| `#version 300 es` / `void main()` / `sampler2D` / `outColor` | Compile error: shaders are SkSL |
| `#include "local.sksl"` | Compile error: only the common prelude expands |
| Shader on a node without `cache` | Effect is skipped or samples the wrong buffer |
| Asset UUID in `@initial` or `<Img src>` | `Img.src received asset ID` — use `@initial('')` |
| Extra image clip on the timeline | The component is unused; the still is just a media clip |

A create or edit that reports `FAILED TO RENDER` is broken. Fix the SkSL before you place the clip. Thumbnail render compiles shaders.

Layout of stacked chrome around the image: [Layout](/docs/custom-elements/layout). Wiring `inputDefs`: [Inputs](/docs/custom-elements/inputs).

---
URL: https://vidova.ai/docs/custom-elements/animation.md

# Animation

animate() is the timeline entry point. animateIn() is the intro. Use generator functions, yield*, all, and tween. Keep fontSize a positive constant.

Custom element animation is a generator function. `yield` pauses until the next frame. `yield*` runs another generator to completion, such as a tween.

```tsx
public *animateIn(duration: number = 0.4): ThreadGenerator {
  this.opacity(0);
  yield* this.opacity(1, duration, easeOutCubic);
}
```

Import `ThreadGenerator`, `all`, `tween`, `waitFor`, and easing from `@vidova/core`.

## `animate` vs `animateIn`

`animate()` is the timeline entry point. The player calls it when the clip is active.

`animateIn()` is the intro. Thumbnails play `animateIn()` before capture. Frame 0 of a reveal-driven element is blank, which is why the thumbnail path needs a separate intro.

Keep them as two methods. `animate()` may call `animateIn()`, then hold or play the rest:

```tsx
public *animateIn(duration: number = 0.4): ThreadGenerator {
  this.opacity(0);
  yield* this.opacity(1, duration, easeOutCubic);
}

public *animate(duration?: number): ThreadGenerator {
  yield* this.animateIn(duration ?? 0.4);
}
```

If `animate()` hides the element at the end, a thumbnail that played only `animate()` would capture an empty frame. That is the reason for the split.

## Tweens and flow

A signal tween takes the next value, a duration in seconds, and an optional timing function:

```tsx
yield* this.opacity(1, 0.4, easeOutCubic);
```

Run tweens together with `all`:

```tsx
yield* all(
  this.opacity(1, 0.4, easeOutCubic),
  this.scale(1, 0.4, easeOutCubic),
);
```

Wait with `waitFor`:

```tsx
yield* waitFor(0.2);
```

`tween` is the low-level helper when you need a callback per frame:

```tsx
yield* tween(0.4, (value) => {
  this.opacity(value);
});
```

Prefer signal tweens when the property is already a signal.

## `fontSize` stays positive

`fontSize` must be a positive number on every frame. Do not drive it from a signal that starts at 0. Keep `fontSize` constant and animate `scale`.

```tsx
public *animateIn(duration: number = 0.4): ThreadGenerator {
  this.scale(0);
  yield* this.scale(1, duration, easeOutCubic);
}
```

A `fontSize` of 0 compiles and then fails at render. The clip shows nothing.

## Refs

Hold a child when a method needs to tween it later:

```tsx
import { createRef } from '@vidova/core';
import { Rect, Txt } from '@vidova/2d';

private readonly title = createRef<Txt>();

public constructor(props?: HelloTitleProps) {
  super({ ...props });
  this.add(
    <Rect>
      <Txt ref={this.title} text={() => this.label()} fontFamily="Inter Variable" />
    </Rect>,
  );
}

public *animateIn(duration: number = 0.4): ThreadGenerator {
  this.title().opacity(0);
  yield* this.title().opacity(1, duration, easeOutCubic);
}
```

Class fields for refs are fine. Class fields for `@signal` props must not collide with `Node` members. See [Layout](/docs/custom-elements/layout).

---
URL: https://vidova.ai/docs/mcp/tools/list_projects.md

# list_projects MCP tool

List all projects stored by this local Vidova desktop app.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

Project-level MCP tool. It does not dispatch into the open editor.

Does not use hosted quota. Local editor operation.

List all projects stored by this local Vidova desktop app. Does not use hosted quota. Local editor operation.

## Advertised MCP input

The MCP server validates this object with `.strict()`. Unknown fields are rejected.

_No fields._



## Result window

Every local MCP tool accepts `resultStart` and `resultEnd` so large payloads can be paged.

- `resultStart` — first character offset. Default `0`.
- `resultEnd` — exclusive end offset. Default `8000`.
- `resultEnd - resultStart` must be at most **8000** characters.
- Increment `resultStart` by 8000 to read the next window.

---
URL: https://vidova.ai/docs/mcp/tools/get_active_project.md

# get_active_project MCP tool

Show which local Vidova project MCP is currently targeting.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

Project-level MCP tool. It does not dispatch into the open editor.

Does not use hosted quota. Local editor operation.

Show which local Vidova project MCP is currently targeting. Does not use hosted quota. Local editor operation.

## Advertised MCP input

The MCP server validates this object with `.strict()`. Unknown fields are rejected.

_No fields._



## Result window

Every local MCP tool accepts `resultStart` and `resultEnd` so large payloads can be paged.

- `resultStart` — first character offset. Default `0`.
- `resultEnd` — exclusive end offset. Default `8000`.
- `resultEnd - resultStart` must be at most **8000** characters.
- Increment `resultStart` by 8000 to read the next window.

---
URL: https://vidova.ai/docs/mcp/tools/create_project.md

# create_project MCP tool

Create a new empty local Vidova project and set it as the active project.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

Project-level MCP tool. It does not dispatch into the open editor.

Does not use hosted quota. Local editor operation.

Create a new empty local Vidova project and set it as the active project. Does not use hosted quota. Local editor operation.

## Advertised MCP input

The MCP server validates this object with `.strict()`. Unknown fields are rejected.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `name` | string | yes | minLength 1 | — | — |



## Result window

Every local MCP tool accepts `resultStart` and `resultEnd` so large payloads can be paged.

- `resultStart` — first character offset. Default `0`.
- `resultEnd` — exclusive end offset. Default `8000`.
- `resultEnd - resultStart` must be at most **8000** characters.
- Increment `resultStart` by 8000 to read the next window.

---
URL: https://vidova.ai/docs/mcp/tools/set_active_project.md

# set_active_project MCP tool

Set which local Vidova project MCP should target for editor tool calls.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

Project-level MCP tool. It does not dispatch into the open editor.

Does not use hosted quota. Local editor operation.

Set which local Vidova project MCP should target for editor tool calls. Does not use hosted quota. Local editor operation.

## Advertised MCP input

The MCP server validates this object with `.strict()`. Unknown fields are rejected.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `projectId` | string | yes | minLength 1 | — | — |



## Result window

Every local MCP tool accepts `resultStart` and `resultEnd` so large payloads can be paged.

- `resultStart` — first character offset. Default `0`.
- `resultEnd` — exclusive end offset. Default `8000`.
- `resultEnd - resultStart` must be at most **8000** characters.
- Increment `resultStart` by 8000 to read the next window.

---
URL: https://vidova.ai/docs/mcp/tools/timeline_get_state.md

# timeline_get_state MCP tool

Get the current state of the project timeline: all layers, clips, positions, and properties.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

MCP name `timeline_get_state` dispatches to renderer `getTimelineState`.

Does not use hosted quota. Local editor operation.

Get the current state of the project timeline: all layers, clips, positions, and properties. Editor must be open. Does not use hosted quota. Local editor operation.

## Advertised MCP input

The MCP server validates this object with `.strict()`. Unknown fields are rejected.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `includeClipDetails` | boolean | no | — | true | Whether to include detailed clip information |
| `resultStart` | integer | no | min 0; max 9007199254740991 | 0 | First character offset to return. Use 0 for the first call. |
| `resultEnd` | integer | no | min 1; max 9007199254740991 | 8000 | Exclusive end offset. resultEnd - resultStart must be at most 8000. Increment resultStart by 8000 to page through large results. |


## Renderer schema

Authoritative input the editor applies after MCP passthrough or dispatch.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `includeClipDetails` | boolean | no | — | true | Whether to include detailed clip information |

## Result window

Every local MCP tool accepts `resultStart` and `resultEnd` so large payloads can be paged.

- `resultStart` — first character offset. Default `0`.
- `resultEnd` — exclusive end offset. Default `8000`.
- `resultEnd - resultStart` must be at most **8000** characters.
- Increment `resultStart` by 8000 to read the next window.

---
URL: https://vidova.ai/docs/mcp/tools/timeline_edit.md

# timeline_edit MCP tool

Edit the timeline.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

MCP name `timeline_edit` dispatches to renderer `timelineEdit`.

Does not use hosted quota. Local editor operation.

Edit the timeline. Set action to addClip, updateClip, deleteClip, splitClip, deleteLayer, removeTimeRanges, removeSilences, addTransition, addFade, or removeTransition. Call timeline_get_state before using clip or layer ids. Never use type=text; use component clips for typography. After creating a component, place it with addClip type=component and that assetId. Omit layerId unless targeting an existing layer; addClip creates a matching layer when none exists. Pass newLayer true only when the user wants a separate layer of the same type. To shorten the timeline to N seconds: action removeTimeRanges with ranges [{from: N, to: currentEnd}]. To shorten one clip from its in-point: action updateClip with clipId and duration N. removeSilences takes only an assetId. addFade is the fade between two adjacent clips. addClip ripples later clips by default. Pass the child fields for that action. Editor must be open. Does not use hosted quota. Local editor operation.

## Advertised MCP input

This tool is registered with **passthrough**. The fields below are what `listTools` advertises. The renderer still validates the child fields for the chosen action or kind. Extra advertised-only values are documented under Reachable behavior.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `action` | enum("addClip", "updateClip", "deleteClip", "splitClip", "deleteLayer", "removeTimeRanges", "removeSilences", "addTransition", "addFade", "removeTransition") | yes | — | — | action for timeline_edit |
| `clipId` | string | no | minLength 1 | — | Required for updateClip and splitClip. Clip id from timeline_get_state. |
| `clipIds` | string[] | no | minItems 1 | — | Required for deleteClip. One or more clip ids from timeline_get_state. |
| `layerId` | string | no | minLength 1 | — | Optional target layer id for addClip or updateClip. |
| `layerIds` | string[] | no | minItems 1 | — | Required for deleteLayer. |
| `assetId` | string | no | minLength 1 | — | Required for removeSilences. Also used by addClip for media clips. |
| `type` | string | no | — | — | Clip type for addClip, or transition type for addTransition. |
| `name` | string | no | — | — | Optional clip name for addClip or updateClip. |
| `start` | number | no | min 0 | — | Timeline start in seconds for addClip or updateClip. |
| `duration` | number | no | exclusiveMin 0 | — | Clip duration in seconds for addClip, updateClip, addFade, or addTransition. |
| `offset` | number | no | min 0 | — | Source in-point in seconds for addClip or updateClip. |
| `time` | number | no | min 0 | — | Required for splitClip. Timeline time in seconds. 0 is valid. |
| `speed` | number | no | exclusiveMin 0 | — | Playback speed for addClip or updateClip. |
| `newLayer` | boolean | no | — | — | addClip: place on a new layer of the same type. |
| `ripple` | boolean | no | — | — | addClip: ripple later clips. Default true. |
| `snapTo` | enum("beat", "downbeat") | no | — | — | Optional beat snap for addClip, updateClip, or splitClip. |
| `ranges` | object[] | no | minItems 1 | — | Required for removeTimeRanges. Ripple-delete these timeline ranges. |
| `ranges[].from` | number | yes | min 0 | — | Range start in timeline seconds. |
| `ranges[].to` | number | yes | min 0 | — | Range end in timeline seconds. |
| `fromClipId` | string | no | minLength 1 | — | Required for addFade, addTransition, and removeTransition. |
| `toClipId` | string | no | minLength 1 | — | Required for addFade, addTransition, and removeTransition. |
| `resultStart` | integer | no | min 0; max 9007199254740991 | 0 | First character offset to return. Use 0 for the first call. |
| `resultEnd` | integer | no | min 1; max 9007199254740991 | 8000 | Exclusive end offset. resultEnd - resultStart must be at most 8000. Increment resultStart by 8000 to page through large results. |

## Reachable behavior

Advertised action values match the renderer children: `addClip`, `updateClip`, `deleteClip`, `splitClip`, `deleteLayer`, `removeTimeRanges`, `removeSilences`, `addTransition`, `addFade`, `removeTransition`.

## Renderer child fields

These are the authoritative fields for each `action`. Send them on the same MCP call. Grouped MCP tools use passthrough, so these fields are not all listed in the advertised schema.

### `action=addClip`

Renderer tool: `timelineAddClip`.

Insert a new clip on the timeline. Never use type='text'; for titles, captions, labels, callouts, lower thirds, or any typography, create a custom component asset and add it with type='component'. For media clips (video/audio/image/model3d), provide type and assetId only—do not pass src (playback URL is resolved from assetId). For component clips, provide type='component' and assetId—componentName and inputDefs are resolved from the asset automatically. For 3D model clips, use type='model3d' with a GLB or glTF asset. For screen recordings, use type='vidova' with assetId—cursor data, face camera, and auto-zoom are resolved automatically. Use type='camera' for project-level whole-composition camera moves; these go on the singleton camera track, not a visual layer. Omit layerId unless targeting an existing layer; a matching layer is created when none exists. Pass newLayer true to put the clip on a new top layer of the same type. Optionally pass componentInputs to override default input values; for component asset inputs, pass asset IDs and Vidova resolves them to playback URLs at preview/render time. Use enterTransition and exitTransition for fade, slide, zoom, blur, RGB split, fisheye, swoosh, whip pan, radial blur, glitch, pixel burst, light leak, liquid warp, prism split, bounce pop, spin zoom, shake pop, flash bang, or vortex twist effects (type, duration 0.1-5s).

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `layerId` | string | no | — | — | — |
| `newLayer` | boolean | no | — | — | When true, place the clip on a new top layer instead of the existing matching-type layer. Use only when the user wants a separate layer. Omit layerId in that case. |
| `name` | string | no | minLength 1; maxLength 180 | — | — |
| `start` | number | no | min 0 | 0 | — |
| `duration` | number | no | exclusiveMin 0 | — | — |
| `offset` | number | no | min 0 | — | — |
| `speed` | number | no | max 8; exclusiveMin 0 | — | — |
| `position` | object | no | — | — | — |
| `position.x` | number | yes | — | — | — |
| `position.y` | number | yes | — | — | — |
| `scale` | object | no | — | — | — |
| `scale.x` | number | yes | — | — | — |
| `scale.y` | number | yes | — | — | — |
| `assetId` | string | no | — | — | — |
| `ripple` | boolean | no | — | — | Ripple insert (default). Every clip already at or after 'start' on the same layer shifts right by the new clip's duration, so the insert makes room instead of covering existing content. Pass false to drop the clip in place, which fails if it would overlap a neighbour. |
| `snapTo` | enum("beat", "downbeat") | no | — | — | Snap start to the nearest beat or downbeat of this clip's asset. Requires a completed detectBeatGrid result for that asset. |
| `type` | enum("video", "audio", "image", "text", "component", "model3d", "blur", "vidova", "camera") | no | — | — | — |
| `width` | number | no | exclusiveMin 0 | — | — |
| `height` | number | no | exclusiveMin 0 | — | — |
| `sourceDuration` | number | no | exclusiveMin 0 | — | — |
| `focus` | object | no | — | — | — |
| `focus.x` | number | yes | min 0; max 1 | — | — |
| `focus.y` | number | yes | min 0; max 1 | — | — |
| `focus.zoom` | number | yes | min 1 | — | — |
| `objectFit` | enum("contain", "cover", "fill") | no | — | — | — |
| `audioVolume` | number | no | min 0; max 1 | — | — |
| `volume` | number | no | min 0; max 1 | — | — |
| `text` | string | no | — | — | — |
| `fontSize` | number | no | exclusiveMin 0 | — | — |
| `fill` | string | no | — | — | — |
| `opacity` | number | no | min 0; max 1 | — | — |
| `template` | enum("text", "title-card", "lower-third", "caption-style") | no | — | — | — |
| `subtitle` | string | no | — | — | — |
| `backgroundColor` | string | no | — | — | — |
| `enterTransition` | object | no | — | — | — |
| `enterTransition.type` | enum("none", "fade", "slide-left", "slide-right", "slide-up", "slide-down", "cross-dissolve", "zoom", "blur", "dip-to-black", "rgb-split-in", "rgb-split-out", "fisheye-in", "fisheye-out", "swoosh-left", "swoosh-right", "swoosh-up", "swoosh-down", "radial-blur-burst", "glitch-pop-in", "glitch-pop-out", "whip-pan-left", "whip-pan-right", "pixel-burst", "light-leak", "liquid-warp", "prism-split", "bounce-pop", "spin-zoom", "shake-pop", "flash-bang", "vortex-twist") | yes | — | — | — |
| `enterTransition.duration` | number | yes | min 0.1; max 5 | — | — |
| `exitTransition` | object | no | — | — | — |
| `exitTransition.type` | enum("none", "fade", "slide-left", "slide-right", "slide-up", "slide-down", "cross-dissolve", "zoom", "blur", "dip-to-black", "rgb-split-in", "rgb-split-out", "fisheye-in", "fisheye-out", "swoosh-left", "swoosh-right", "swoosh-up", "swoosh-down", "radial-blur-burst", "glitch-pop-in", "glitch-pop-out", "whip-pan-left", "whip-pan-right", "pixel-burst", "light-leak", "liquid-warp", "prism-split", "bounce-pop", "spin-zoom", "shake-pop", "flash-bang", "vortex-twist") | yes | — | — | — |
| `exitTransition.duration` | number | yes | min 0.1; max 5 | — | — |
| `componentInputs` | object | no | — | — | For component clips: input values keyed by input name. For asset inputs, pass the source asset ID; preview/render resolves it to a playback URL. |
| `blurStrength` | number | no | min 0; max 100 | — | — |
| `blurQuality` | number | no | min 1; max 32 | — | — |
| `roundedness` | number | no | min 0 | — | — |
| `cameraSettings` | object | no | — | — | For camera clips: whole-composition pan/zoom/rotation settings. |
| `cameraSettings.position` | object | no | — | — | — |
| `cameraSettings.position.x` | number | yes | — | — | — |
| `cameraSettings.position.y` | number | yes | — | — | — |
| `cameraSettings.zoom` | number | no | min 0.05 | — | — |
| `cameraSettings.rotation` | number | no | — | — | — |

### `action=updateClip`

Renderer tool: `timelineUpdateClip`.

Adjust clip timing, target layer, static opacity, and type-specific settings. For text clips, use textSettings with typography, effects, template, subtitle, and backgroundColor. For component clips, use componentInputs to update input values; for asset inputs, pass asset IDs and Vidova resolves them to playback URLs at preview/render time. For video, image, component, and Vidova clips, use perspectiveSettings to set the exact ClipPerspectiveSurface object: enabled, rotateX, rotateY, rotateZ, perspective, depthShading, rim, sheen, depthBlur, shadow, debugGrid. For Vidova screen-recording clips, use vidovaSettings to edit layout, cursor/spotlight, click effects, motion/tracking, facecam/camera overlay, appearance/quality, captions, audio, and keyboard shortcut UI controls. For camera clips, use cameraSettings and camera.* keyframe paths for whole-composition pan/zoom/rotation on the singleton camera track. Vidova zoom clips remain screen-recording zooms only; clip animation is per-clip attention motion only. Use enterTransition and exitTransition to set fade, slide, zoom, blur, RGB split, fisheye, swoosh, whip pan, radial blur, glitch, pixel burst, light leak, liquid warp, prism split, bounce pop, spin zoom, shake pop, flash bang, or vortex twist effects (type, duration 0.1-5s). Use animation (none|hover|pulse|float|glow|zoom-in|zoom-out) and animationIntensity (0-5x) for idle animations on visual layer clips. Use keyframeActions to set/remove/clear keyframes on position.x/y, scale.x/y, focus.x/y/zoom, modelPosition.x/y/z, modelRotation.x/y/z, camera.position.x/y, camera.zoom, camera.rotation, faceCamera.position.x/y, perspective.rotateX/Y/Z, perspective.depth, perspective.depthShading, perspective.rim, perspective.sheen, perspective.depthBlur, and perspective.shadow using clip-local display seconds. COLOR GRADING: contrast, saturation, temperature, tint, highlights, shadows use range -100 to 100 (NOT 0–1). Use 20–50 for visible effect—values like 0.1 or 0.2 are too small. exposure is -2 to 2.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `clipId` | string | yes | minLength 1 | — | — |
| `name` | string | no | minLength 1; maxLength 180 | — | — |
| `start` | number | no | min 0 | — | — |
| `snapTo` | enum("beat", "downbeat") | no | — | — | Snap start to the nearest beat or downbeat of this clip asset. Requires a completed detectBeatGrid result. Ignored unless start is provided. |
| `duration` | number | no | min 0.1 | — | — |
| `offset` | number | no | min 0 | — | — |
| `speed` | number | no | max 8; exclusiveMin 0 | — | — |
| `layerId` | string | no | minLength 1 | — | — |
| `position` | object | no | — | — | — |
| `position.x` | number | yes | — | — | — |
| `position.y` | number | yes | — | — | — |
| `scale` | object | no | — | — | — |
| `scale.x` | number | yes | — | — | — |
| `scale.y` | number | yes | — | — | — |
| `opacity` | number | no | min 0; max 1 | — | — |
| `assetId` | string | no | — | — | — |
| `videoSettings` | object | no | — | — | — |
| `videoSettings.width` | number | no | exclusiveMin 0 | — | — |
| `videoSettings.height` | number | no | exclusiveMin 0 | — | — |
| `videoSettings.objectFit` | enum("contain", "cover", "fill") | no | — | — | — |
| `videoSettings.focus` | object | no | — | — | — |
| `videoSettings.focus.x` | number | yes | min 0; max 1 | — | — |
| `videoSettings.focus.y` | number | yes | min 0; max 1 | — | — |
| `videoSettings.focus.zoom` | number | yes | min 1 | — | — |
| `videoSettings.colorGrading` | object | no | — | — | Exposure: -2 to 2. All others: -100 to 100. Use 20-50 for visible change—never 0.1 or 0.2. |
| `videoSettings.colorGrading.exposure` | number | no | min -2; max 2 | — | Range -2 to 2 only |
| `videoSettings.colorGrading.contrast` | number | no | min -100; max 100 | — | Range -100 to 100. Use 15-50 for visible effect (not 0.1). |
| `videoSettings.colorGrading.saturation` | number | no | min -100; max 100 | — | Range -100 to 100. Use 15-50 for visible effect (not 0.15). |
| `videoSettings.colorGrading.temperature` | number | no | min -100; max 100 | — | Range -100 to 100 (cool to warm). Use 15-50 for visible effect (not 0.2). |
| `videoSettings.colorGrading.tint` | number | no | min -100; max 100 | — | Range -100 to 100 (green to magenta). Use 15-50 for visible effect. |
| `videoSettings.colorGrading.highlights` | number | no | min -100; max 100 | — | Range -100 to 100. Use 15-50 for visible effect. |
| `videoSettings.colorGrading.shadows` | number | no | min -100; max 100 | — | Range -100 to 100. Use 15-50 for visible effect. |
| `videoSettings.chromaKey` | object | no | — | — | — |
| `videoSettings.chromaKey.color` | string | yes | pattern `^#[0-9a-fA-F]{3,6}$` | — | — |
| `videoSettings.chromaKey.threshold` | number | yes | min 0; max 1 | — | — |
| `videoSettings.chromaKey.smoothness` | number | no | min 0; max 1 | — | — |
| `videoSettings.audioVolume` | number | no | min 0; max 1 | — | — |
| `audioSettings` | object | no | — | — | For audio and video clips: playback volume from 0 to 1. Use volume 0 to mute a clip. On a video clip this sets the same value as videoSettings.audioVolume. |
| `audioSettings.volume` | number | no | min 0; max 1 | — | — |
| `imageSettings` | object | no | — | — | — |
| `imageSettings.width` | number | no | exclusiveMin 0 | — | — |
| `imageSettings.height` | number | no | exclusiveMin 0 | — | — |
| `imageSettings.colorGrading` | object | no | — | — | Exposure: -2 to 2. All others: -100 to 100. Use 20-50 for visible change—never 0.1 or 0.2. |
| `imageSettings.colorGrading.exposure` | number | no | min -2; max 2 | — | Range -2 to 2 only |
| `imageSettings.colorGrading.contrast` | number | no | min -100; max 100 | — | Range -100 to 100. Use 15-50 for visible effect (not 0.1). |
| `imageSettings.colorGrading.saturation` | number | no | min -100; max 100 | — | Range -100 to 100. Use 15-50 for visible effect (not 0.15). |
| `imageSettings.colorGrading.temperature` | number | no | min -100; max 100 | — | Range -100 to 100 (cool to warm). Use 15-50 for visible effect (not 0.2). |
| `imageSettings.colorGrading.tint` | number | no | min -100; max 100 | — | Range -100 to 100 (green to magenta). Use 15-50 for visible effect. |
| `imageSettings.colorGrading.highlights` | number | no | min -100; max 100 | — | Range -100 to 100. Use 15-50 for visible effect. |
| `imageSettings.colorGrading.shadows` | number | no | min -100; max 100 | — | Range -100 to 100. Use 15-50 for visible effect. |
| `textSettings` | object | no | — | — | — |
| `textSettings.text` | string | no | minLength 1 | — | — |
| `textSettings.fontSize` | number | no | exclusiveMin 0 | — | — |
| `textSettings.fontFamily` | string | no | minLength 1 | — | — |
| `textSettings.fontWeight` | number | no | min 1; max 1000 | — | — |
| `textSettings.fill` | string | no | — | — | — |
| `textSettings.opacity` | number | no | min 0; max 1 | — | — |
| `textSettings.effect` | enum("none", "glitch", "ripple", "vhs", "pixelate", "chromatic", "fisheye") | no | — | — | — |
| `textSettings.effectIntensity` | number | no | min 0; max 1 | — | — |
| `textSettings.template` | enum("text", "title-card", "lower-third", "caption-style") | no | — | — | — |
| `textSettings.subtitle` | string | no | — | — | — |
| `textSettings.backgroundColor` | string | no | — | — | — |
| `enterTransition` | object \\| null | no | — | — | — |
| `exitTransition` | object \\| null | no | — | — | — |
| `animation` | enum("none", "hover", "pulse", "float", "glow", "zoom-in", "zoom-out") \\| null | no | — | — | — |
| `animationIntensity` | number | no | min 0; max 5 | — | — |
| `componentInputs` | object | no | — | — | For component clips: input values keyed by input name. For asset inputs, pass the source asset ID; preview/render resolves it to a playback URL. |
| `perspectiveSettings` | object | no | strict | — | For video, image, component, and Vidova clips: exact ClipPerspectiveSurface object. Required fields: enabled, rotateX, rotateY, rotateZ, perspective, depthShading, rim, sheen, depthBlur, shadow, debugGrid. |
| `perspectiveSettings.enabled` | boolean | yes | — | — | — |
| `perspectiveSettings.rotateX` | number | yes | min -1.2; max 1.2 | — | — |
| `perspectiveSettings.rotateY` | number | yes | min -1.2; max 1.2 | — | — |
| `perspectiveSettings.rotateZ` | number | yes | min -3.14; max 3.14 | — | — |
| `perspectiveSettings.perspective` | number | yes | min 0.1; max 4 | — | — |
| `perspectiveSettings.depthShading` | number | yes | min 0; max 0.6 | — | — |
| `perspectiveSettings.rim` | number | yes | min 0; max 1 | — | — |
| `perspectiveSettings.sheen` | number | yes | min 0; max 1 | — | — |
| `perspectiveSettings.depthBlur` | number | yes | min 0; max 10 | — | — |
| `perspectiveSettings.shadow` | number | yes | min 0; max 0.6 | — | — |
| `perspectiveSettings.debugGrid` | boolean | yes | — | — | — |
| `vidovaSettings` | object | no | — | — | — |
| `vidovaSettings.layout` | enum("screen-and-cam", "screen-only", "cam-only", "half-half") | no | — | — | — |
| `vidovaSettings.crop` | object | no | — | — | Normalized crop edges for the screen recording: Left/Top/Right/Bottom in the 0..1 range. |
| `vidovaSettings.crop.Top` | number | no | min 0; max 1 | — | — |
| `vidovaSettings.crop.Bottom` | number | no | min 0; max 1 | — | — |
| `vidovaSettings.crop.Left` | number | no | min 0; max 1 | — | — |
| `vidovaSettings.crop.Right` | number | no | min 0; max 1 | — | — |
| `vidovaSettings.zoomLayerId` | string | no | — | — | Use a zoom layer ID from timeline_get_state. Pass an empty string to clear. |
| `vidovaSettings.blurLayerId` | string | no | — | — | Use an overlay/blur layer ID from timeline_get_state. Pass an empty string to clear. |
| `vidovaSettings.roundedness` | number | no | min 0; max 50 | — | — |
| `vidovaSettings.padding` | number | no | min 0; max 100 | — | — |
| `vidovaSettings.screenAudioVolume` | number | no | min 0; max 1 | — | — |
| `vidovaSettings.cameraAudioVolume` | number | no | min 0; max 1 | — | — |
| `vidovaSettings.muteScreenAudio` | boolean | no | — | — | — |
| `vidovaSettings.muteCameraAudio` | boolean | no | — | — | — |
| `vidovaSettings.zoomAnimationStyle` | enum("soft-spring", "snappy-spring", "soft-landing", "fast-settle", "gentle-curve") | no | — | — | Zoom feel: soft-spring (default), snappy-spring, soft-landing, fast-settle, gentle-curve. |
| `vidovaSettings.panAnimationStyle` | enum("heavy-camera", "quick-follow", "soft-lag") | no | — | — | Pan feel: heavy-camera (default), quick-follow, soft-lag. |
| `vidovaSettings.linkedZoomTransitionDuration` | number | no | min 0; max 2 | — | — |
| `vidovaSettings.useAutoLinkedZoomTransitionDuration` | boolean | no | — | — | Set true to clear the manual linked zoom handoff duration. |
| `vidovaSettings.trackingIntensity` | integer | no | min 0; max 5 | — | — |
| `vidovaSettings.trackingStyle` | enum("steadicam", "director", "anchor", "momentum") | no | — | — | Camera-path solver for cursor-following zooms: steadicam, director, anchor, or momentum. |
| `vidovaSettings.clickFollow` | object | no | strict | — | Keep out-of-view clicks in frame and near centre. Clicks already in view stay put. enabled (default true), tight 0.05-0.45 (default 0.35), zoom 1-6 (steadicam click-punch cap, default 3.5), window 0.2-1.6s (default 0.8), lead 0-0.8s (default 0.38), margin 0.35-1 (steadicam hold slack, default 0.85). Partial objects merge with the clip current values. |
| `vidovaSettings.clickFollow.enabled` | boolean | no | — | — | — |
| `vidovaSettings.clickFollow.tight` | number | no | min 0.05; max 0.45 | — | — |
| `vidovaSettings.clickFollow.window` | number | no | min 0.2; max 1.6 | — | — |
| `vidovaSettings.clickFollow.lead` | number | no | min 0; max 0.8 | — | — |
| `vidovaSettings.clickFollow.zoom` | number | no | min 1; max 6 | — | — |
| `vidovaSettings.clickFollow.margin` | number | no | min 0.35; max 1 | — | — |
| `vidovaSettings.motionBlurStrength` | number | no | min 0; max 2 | — | — |
| `vidovaSettings.cursorHidden` | boolean | no | — | — | False shows the cursor. |
| `vidovaSettings.cursorStyle` | enum("default", "cartoon", "modern", "original", "banana", "capitaine-dark", "capitaine-light", "touch", "tahoe", "whitesur", "bibata", "bibata-original") | no | — | — | — |
| `vidovaSettings.cursorSize` | number | no | min 16; max 256 | — | — |
| `vidovaSettings.smoothCursorChanges` | boolean | no | — | — | — |
| `vidovaSettings.hideCursorWhenStill` | boolean | no | — | — | — |
| `vidovaSettings.enableCursorMotionBlur` | boolean | no | — | — | — |
| `vidovaSettings.cursorMotionBlurStrength` | number | no | min 0; max 2 | — | — |
| `vidovaSettings.enableCursorTilting` | boolean | no | — | — | — |
| `vidovaSettings.returnToOriginalPosition` | boolean | no | — | — | — |
| `vidovaSettings.cursorSmoothingStyle` | enum("original", "steady", "soft", "fluid", "glide") | no | — | — | Cursor path: original, steady (default), soft, fluid, glide. |
| `vidovaSettings.pinCursorToClicks` | boolean | no | — | — | Pin the path through each click so the cursor lands on the button. |
| `vidovaSettings.cursorClickPinWindow` | number | no | min 0.04; max 0.4 | — | How long the cursor holds on each click, in seconds. Default 0.12. |
| `vidovaSettings.cursorSmoothingTime` | number | no | min 0.01; max 0.12 | — | Steady and Soft smoothness in seconds. Default 0.045. |
| `vidovaSettings.cursorSmoothingSpace` | number | no | min 4; max 80 | — | Steady: how strongly fast flicks are kept, in pixels. Default 18. |
| `vidovaSettings.cursorSmoothingTension` | number | no | min 40; max 400 | — | Fluid spring weight. Default 170. |
| `vidovaSettings.cursorSmoothingFriction` | number | no | min 4; max 40 | — | Fluid spring damping. Default 20. |
| `vidovaSettings.cursorSmoothingSimplify` | number | no | min 2; max 40 | — | Glide: how much jitter to drop before the curve. Default 8. |
| `vidovaSettings.clickEffectStyle` | enum("none", "default", "effect-1", "effect-2", "effect-3", "effect-4", "effect-5", "effect-6") | no | — | — | — |
| `vidovaSettings.clickEffectSize` | number | no | min 16; max 256 | — | — |
| `vidovaSettings.cursorSpotlight` | object | no | strict | — | — |
| `vidovaSettings.cursorSpotlight.enabled` | boolean | no | — | — | — |
| `vidovaSettings.cursorSpotlight.radius` | number | no | — | — | — |
| `vidovaSettings.cursorSpotlight.softness` | number | no | — | — | — |
| `vidovaSettings.cursorSpotlight.dimOpacity` | number | no | — | — | — |
| `vidovaSettings.cursorSpotlight.onlyOnClick` | boolean | no | — | — | — |
| `vidovaSettings.cursorSpotlight.clickWindow` | number | no | min 0.05; max 4 | — | — |
| `vidovaSettings.camera` | object | no | — | — | — |
| `vidovaSettings.camera.size` | number | no | min 5; max 70 | — | — |
| `vidovaSettings.camera.sizeDuringZoom` | number | no | min 5; max 100 | — | — |
| `vidovaSettings.camera.roundedness` | number | no | min 0; max 100 | — | — |
| `vidovaSettings.camera.shape` | enum("default", "squircle", "circle") | no | — | — | — |
| `vidovaSettings.camera.hideCamera` | boolean | no | — | — | False shows the camera overlay. |
| `vidovaSettings.camera.mirrorCamera` | boolean | no | — | — | — |
| `vidovaSettings.camera.removeBackground` | boolean | no | — | — | True composites the baked person mask. The mask must already exist on the camera asset. |
| `vidovaSettings.camera.position` | object | no | — | — | Camera anchor grid position. Use -1, 0, or 1 for x/y. |
| `vidovaSettings.camera.position.x` | number | yes | min -1; max 1 | — | — |
| `vidovaSettings.camera.position.y` | number | yes | min -1; max 1 | — | — |
| `vidovaSettings.camera.alignment` | object | no | — | — | Crop alignment inside squircle/circle camera shapes. |
| `vidovaSettings.camera.alignment.x` | number | yes | min -1; max 1 | — | — |
| `vidovaSettings.camera.alignment.y` | number | yes | min -1; max 1 | — | — |
| `vidovaSettings.camera.differentSizeDuringZoom` | boolean | no | — | — | — |
| `vidovaSettings.camera.verticalPadding` | number | no | min 0; max 100 | — | — |
| `vidovaSettings.camera.globalPosition` | boolean | no | — | — | True anchors the camera to the scene instead of the clip. |
| `vidovaSettings.mouseIndicator` | object | no | — | — | — |
| `vidovaSettings.mouseIndicator.enabled` | boolean | no | — | — | — |
| `vidovaSettings.mouseIndicator.position` | object | no | — | — | Mouse indicator anchor grid position. Use -1, 0, or 1 for x/y. |
| `vidovaSettings.mouseIndicator.position.x` | number | yes | min -1; max 1 | — | — |
| `vidovaSettings.mouseIndicator.position.y` | number | yes | min -1; max 1 | — | — |
| `vidovaSettings.mouseIndicator.size` | number | no | min 40; max 180 | — | Mouse indicator size in px. |
| `vidovaSettings.mouseIndicator.opacity` | number | no | min 0; max 1 | — | — |
| `vidovaSettings.mouseIndicator.style` | enum("minimal", "dark", "light", "colored") | no | — | — | — |
| `vidovaSettings.mouseIndicator.highlightColor` | string | no | pattern `^#[0-9a-fA-F]{6}$` | — | — |
| `vidovaSettings.mouseIndicator.minActiveDuration` | number | no | min 0.02; max 0.5 | — | Minimum button/wheel highlight duration in seconds. |
| `vidovaSettings.mouseIndicator.globalPosition` | boolean | no | — | — | True anchors the mouse indicator to the scene instead of the clip. |
| `vidovaSettings.quality` | number | no | min 0 | — | Motion-blur shader sample quality. 0 disables sampled motion blur. |
| `vidovaSettings.sharpenFactor` | number | no | min 0; max 5 | — | — |
| `vidovaSettings.shadowStrength` | number | no | min 0; max 100 | — | — |
| `vidovaSettings.inset` | number | no | min 0; max 50 | — | — |
| `vidovaSettings.isVertical` | boolean | no | — | — | — |
| `vidovaSettings.showShortcuts` | boolean | no | — | — | — |
| `vidovaSettings.shortcutsSize` | number | no | min 1; max 300 | — | — |
| `vidovaSettings.shortcutsDuration` | number | no | min 0.5; max 5 | — | — |
| `vidovaSettings.captionSettings` | object | no | strict | — | — |
| `vidovaSettings.captionSettings.enabled` | boolean | no | — | — | — |
| `vidovaSettings.captionSettings.fontFamily` | string | no | — | — | — |
| `vidovaSettings.captionSettings.fontWeight` | 400 \\| 500 \\| 700 | no | — | — | — |
| `vidovaSettings.captionSettings.fontSize` | number | no | — | — | — |
| `vidovaSettings.captionSettings.distanceFromBottom` | number | no | — | — | — |
| `vidovaSettings.captionSettings.style` | enum("pill", "karaoke-lime", "karaoke-magenta", "karaoke-cyan", "outlined", "bold-outline", "minimal", "word-highlight", "pink-pill", "dark-pill-lime", "cloud-blob", "amber-tape", "studio") | no | — | — | — |
| `vidovaSettings.captionSettings.textColor` | string | no | — | — | — |
| `vidovaSettings.captionSettings.highlightColor` | string | no | — | — | — |
| `vidovaSettings.captionSettings.backgroundColor` | string | no | — | — | — |
| `vidovaSettings.captionSettings.shadowColor` | string | no | — | — | — |
| `vidovaSettings.captionSettings.shadowBlur` | number | no | — | — | — |
| `vidovaSettings.captionSettings.maxCharsPerLine` | number | no | — | — | — |
| `cameraSettings` | object | no | — | — | For camera clips only: project-level whole-composition pan/zoom/rotation. |
| `cameraSettings.position` | object | no | — | — | Whole-composition pan in scene pixels. |
| `cameraSettings.position.x` | number | yes | — | — | — |
| `cameraSettings.position.y` | number | yes | — | — | — |
| `cameraSettings.zoom` | number | no | min 0.05 | — | Whole-composition camera zoom. 1 = default, 2 = 2x. |
| `cameraSettings.rotation` | number | no | — | — | Whole-composition camera rotation in degrees. |
| `keyframeActions` | object \\| object \\| object[] | no | minItems 1 | — | Optional keyframe edits using clip-local display seconds. Supported propertyPath values: position.x, position.y, scale.x, scale.y, focus.x, focus.y, focus.zoom, modelPosition.x, modelPosition.y, modelPosition.z, modelRotation.x, modelRotation.y, modelRotation.z, camera.position.x, camera.position.y, camera.zoom, camera.rotation, faceCamera.position.x, faceCamera.position.y, perspective.rotateX, perspective.rotateY, perspective.rotateZ, perspective.depth, perspective.depthShading, perspective.rim, perspective.sheen, perspective.depthBlur, perspective.shadow. Use op=set with time/value, op=remove with time, or op=clear to remove all keys for a property. |

### `action=deleteClip`

Renderer tool: `timelineDeleteClip`.

Remove one or more clips from the timeline by their IDs. Deletion is a ripple delete: each clip's time range is cut from every layer and all later content shifts left to close the gap, so the edit never leaves a hole. To cut a range without naming clips, use timelineRemoveTimeRanges instead.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `clipIds` | string[] | yes | minItems 1 | — | List of clip IDs to delete from the timeline |

### `action=splitClip`

Renderer tool: `timelineSplitClip`.

Split a single clip at a specific timestamp. For removing multiple silence segments or time ranges at once, prefer timelineRemoveTimeRanges instead.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `clipId` | string | yes | minLength 1 | — | — |
| `time` | number | yes | min 0 | — | Timeline timestamp in seconds |
| `snapTo` | enum("beat", "downbeat") | no | — | — | Snap the split time to the nearest beat or downbeat of this clip's asset. Requires a completed detectBeatGrid result. |

### `action=deleteLayer`

Renderer tool: `timelineDeleteLayer`.

Remove one or more timeline layers by their IDs. All clips on those layers are removed.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `layerIds` | string[] | yes | minItems 1 | — | List of layer IDs to delete from the timeline |

### `action=removeTimeRanges`

Renderer tool: `timelineRemoveTimeRanges`.

Remove multiple time ranges from the timeline in a single operation. Each range is deleted with ripple: all content after the removed interval shifts left to close the gap. Use this for bulk silence removal or any scenario where multiple segments need to be cut at once.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `ranges` | object[] | yes | minItems 1 | — | List of timeline time ranges (in seconds) to remove with ripple. All clips after each removed range will shift left automatically. Overlapping or adjacent ranges are merged before applying. |
| `ranges[].from` | number | yes | min 0 | — | Start of the range to remove, in timeline seconds |
| `ranges[].to` | number | yes | min 0 | — | End of the range to remove, in timeline seconds |

### `action=removeSilences`

Renderer tool: `removeSilencesFromAsset`.

Remove the dead air from a transcribed recording. Vidova computes the silence ranges from the transcript word timings itself and ripple-deletes them, so no timestamps are needed and no speech is cut. Use this instead of working out silence ranges and calling timelineRemoveTimeRanges by hand. Requires a completed transcription and exactly one recording clip for the asset on the timeline.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `assetId` | string | yes | minLength 1 | — | Asset id of the transcribed recording to tighten. |

### `action=addTransition`

Renderer tool: `timelineAddTransition`.

Add a named transition between two adjacent video clips on the same layer. Prefer timelineAddFade when the user asks for a fade — do not use cross-dissolve as a substitute for fade. Supports fade, slide, zoom, blur, RGB split, fisheye, swoosh, whip pan, radial blur, glitch, pixel burst, light leak, liquid warp, prism split, bounce pop, spin zoom, shake pop, flash bang, and vortex twist transitions.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `fromClipId` | string | yes | minLength 1 | — | — |
| `toClipId` | string | yes | minLength 1 | — | — |
| `type` | enum("fade", "slide-left", "slide-right", "slide-up", "slide-down", "cross-dissolve", "zoom", "blur", "dip-to-black", "rgb-split-in", "rgb-split-out", "fisheye-in", "fisheye-out", "swoosh-left", "swoosh-right", "swoosh-up", "swoosh-down", "radial-blur-burst", "glitch-pop-in", "glitch-pop-out", "whip-pan-left", "whip-pan-right", "pixel-burst", "light-leak", "liquid-warp", "prism-split", "bounce-pop", "spin-zoom", "shake-pop", "flash-bang", "vortex-twist") | no | — | "fade" | Transition effect type |
| `duration` | number | no | max 5; exclusiveMin 0 | 0.5 | Transition duration in seconds |

### `action=addFade`

Renderer tool: `timelineAddFade`.

Add a fade between two adjacent video clips on the same layer. Use this whenever the user asks for a fade or soft dissolve — always applies type fade (never cross-dissolve). Prefer this over timelineAddTransition for fade requests.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `fromClipId` | string | yes | minLength 1 | — | — |
| `toClipId` | string | yes | minLength 1 | — | — |
| `duration` | number | no | max 5; exclusiveMin 0 | 0.5 | Fade duration in seconds |

### `action=removeTransition`

Renderer tool: `timelineRemoveTransition`.

Remove an existing transition between two clips.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `fromClipId` | string | yes | minLength 1 | — | — |
| `toClipId` | string | yes | minLength 1 | — | — |

## Result window

Every local MCP tool accepts `resultStart` and `resultEnd` so large payloads can be paged.

- `resultStart` — first character offset. Default `0`.
- `resultEnd` — exclusive end offset. Default `8000`.
- `resultEnd - resultStart` must be at most **8000** characters.
- Increment `resultStart` by 8000 to read the next window.

## Nested objects

Cursor, camera overlay, layout, and captions live on `vidovaSettings` during `updateClip`. See [vidovaSettings](/docs/mcp/schemas/vidova-settings).

Do not call a retired `vidova_set_cursor` tool. It is not in MCP.

---
URL: https://vidova.ai/docs/mcp/tools/clip_enhance.md

# clip_enhance MCP tool

Zooms and chroma key.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

MCP name `clip_enhance` dispatches to renderer `clipEnhance`.

Does not use hosted quota. Local editor operation.

Zooms and chroma key. action addZoom adds Vidova zoom segments. action manageZooms lists/adds/updates/deletes zooms; pass zoomAction as list, add, update, or delete. action chromaKey keys a video or image clip. Editor must be open. Does not use hosted quota. Local editor operation.

## Advertised MCP input

This tool is registered with **passthrough**. The fields below are what `listTools` advertises. The renderer still validates the child fields for the chosen action or kind. Extra advertised-only values are documented under Reachable behavior.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `action` | enum("addZoom", "manageZooms", "chromaKey") | yes | — | — | action for clip_enhance |
| `resultStart` | integer | no | min 0; max 9007199254740991 | 0 | First character offset to return. Use 0 for the first call. |
| `resultEnd` | integer | no | min 1; max 9007199254740991 | 8000 | Exclusive end offset. resultEnd - resultStart must be at most 8000. Increment resultStart by 8000 to page through large results. |

## Reachable behavior

Advertised action values match the renderer children: `addZoom`, `manageZooms`, `chromaKey`.

## Renderer child fields

These are the authoritative fields for each `action`. Send them on the same MCP call. Grouped MCP tools use passthrough, so these fields are not all listed in the advertised schema.

### `action=addZoom`

Renderer tool: `addZoomToVidovaClip`.

Add zoom effects to a vidova (screen recording) clip. Creates zoom clips on the associated zoom layer. Each zoom segment defines when the zoom starts, its duration, magnification factor, and behavior. Use 'tracking' zoomEffectType for cursor-following zooms (great for tutorials) and 'manual' for fixed-point zooms. Use getTimelineState first to find the vidova clip ID.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `clipId` | string | yes | minLength 1 | — | — |
| `zooms` | object[] | yes | minItems 1 | — | Array of zoom segments to add to the vidova clip |
| `zooms[].start` | number | yes | min 0 | — | Start time in seconds (relative to the vidova clip start) |
| `zooms[].duration` | number | yes | exclusiveMin 0 | — | Duration of the zoom effect in seconds |
| `zooms[].factor` | number | no | min 1; max 10 | 1.5 | Zoom magnification factor (1 = no zoom, 2 = 2x, etc.) |
| `zooms[].anchorX` | number | no | min -1; max 1 | 0 | Anchor X in range -1 to 1. 0 = center. Only used for manual zoom. |
| `zooms[].anchorY` | number | no | min -1; max 1 | 0 | Anchor Y in range -1 to 1. 0 = center. Only used for manual zoom. |
| `zooms[].zoomEffectType` | enum("tracking", "manual") | no | — | "tracking" | 'tracking' follows the cursor (default for screen recordings), 'manual' zooms to a fixed anchor point |
| `zooms[].trackType` | enum("cinematic", "centered") | no | — | "cinematic" | 'cinematic' = smooth follow, 'centered' = lock to cursor. Only applies when zoomEffectType is 'tracking'. |
| `zooms[].name` | string | no | — | — | Optional name for this zoom segment |
| `zooms[].depth` | object | no | strict | — | Optional 3D zoom. Set enabled:true to re-project the frame onto a tilted plane with real perspective instead of a flat scale. Angles (tiltX/tiltY/roll and glideTiltX/glideTiltY/glideRoll) are RADIANS in -0.35..0.35; focalLength is 24-120mm. The zoom eases into the tilt/roll/dolly pose, glides to the glide* pose while held, then eases flat. Omitted fields fall back to the defaults. |
| `zooms[].depth.enabled` | boolean | no | — | — | — |
| `zooms[].depth.intensity` | number | no | min 0; max 2 | — | — |
| `zooms[].depth.focalLength` | number | no | min 24; max 120 | — | — |
| `zooms[].depth.tiltX` | number | no | min -0.35; max 0.35 | — | — |
| `zooms[].depth.tiltY` | number | no | min -0.35; max 0.35 | — | — |
| `zooms[].depth.roll` | number | no | min -0.35; max 0.35 | — | — |
| `zooms[].depth.dolly` | number | no | min -0.35; max 0.35 | — | — |
| `zooms[].depth.glideTiltX` | number | no | min -0.35; max 0.35 | — | — |
| `zooms[].depth.glideTiltY` | number | no | min -0.35; max 0.35 | — | — |
| `zooms[].depth.glideRoll` | number | no | min -0.35; max 0.35 | — | — |
| `zooms[].depth.glideDolly` | number | no | min -0.35; max 0.35 | — | — |
| `zooms[].depth.anchorInfluence` | number | no | min 0; max 1 | — | — |
| `zooms[].depth.depthShading` | number | no | min 0; max 0.6 | — | — |
| `zooms[].depth.rim` | number | no | min 0; max 0.5 | — | — |
| `zooms[].depth.sheen` | number | no | min 0; max 0.6 | — | — |
| `zooms[].depth.depthBlur` | number | no | min 0; max 10 | — | — |
| `zooms[].depth.shadow` | number | no | min 0; max 0.6 | — | — |

### `action=manageZooms`

Renderer tool: `manageVidovaZooms`.

List, add, update, or delete the zoom regions on a vidova (screen recording) clip. Zoom regions live on the clip's linked zoom layer. Use zoomAction 'list' to discover zoom clip IDs before updating or deleting them.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `clipId` | string | yes | minLength 1 | — | — |
| `zoomAction` | enum("list", "add", "update", "delete") | yes | — | — | — |
| `zooms` | object[] | no | minItems 1 | — | — |
| `zooms[].start` | number | yes | min 0 | — | — |
| `zooms[].duration` | number | yes | exclusiveMin 0 | — | — |
| `zooms[].factor` | number | no | min 1; max 10 | 1.5 | — |
| `zooms[].anchorX` | number | no | min -1; max 1 | 0 | — |
| `zooms[].anchorY` | number | no | min -1; max 1 | 0 | — |
| `zooms[].zoomEffectType` | enum("tracking", "manual") | no | — | "tracking" | — |
| `zooms[].trackType` | enum("cinematic", "centered") | no | — | "cinematic" | — |
| `zooms[].name` | string | no | — | — | — |
| `zooms[].depth` | object | no | strict | — | — |
| `zooms[].depth.enabled` | boolean | no | — | — | — |
| `zooms[].depth.intensity` | number | no | min 0; max 2 | — | — |
| `zooms[].depth.focalLength` | number | no | min 24; max 120 | — | — |
| `zooms[].depth.tiltX` | number | no | min -0.35; max 0.35 | — | — |
| `zooms[].depth.tiltY` | number | no | min -0.35; max 0.35 | — | — |
| `zooms[].depth.roll` | number | no | min -0.35; max 0.35 | — | — |
| `zooms[].depth.dolly` | number | no | min -0.35; max 0.35 | — | — |
| `zooms[].depth.glideTiltX` | number | no | min -0.35; max 0.35 | — | — |
| `zooms[].depth.glideTiltY` | number | no | min -0.35; max 0.35 | — | — |
| `zooms[].depth.glideRoll` | number | no | min -0.35; max 0.35 | — | — |
| `zooms[].depth.glideDolly` | number | no | min -0.35; max 0.35 | — | — |
| `zooms[].depth.anchorInfluence` | number | no | min 0; max 1 | — | — |
| `zooms[].depth.depthShading` | number | no | min 0; max 0.6 | — | — |
| `zooms[].depth.rim` | number | no | min 0; max 0.5 | — | — |
| `zooms[].depth.sheen` | number | no | min 0; max 0.6 | — | — |
| `zooms[].depth.depthBlur` | number | no | min 0; max 10 | — | — |
| `zooms[].depth.shadow` | number | no | min 0; max 0.6 | — | — |
| `updates` | object[] | no | minItems 1 | — | — |
| `updates[].zoomClipId` | string | yes | minLength 1 | — | — |
| `updates[].start` | number | no | min 0 | — | — |
| `updates[].duration` | number | no | exclusiveMin 0 | — | — |
| `updates[].factor` | number | no | min 1; max 10 | — | — |
| `updates[].anchorX` | number | no | min -1; max 1 | — | — |
| `updates[].anchorY` | number | no | min -1; max 1 | — | — |
| `updates[].zoomEffectType` | enum("tracking", "manual") | no | — | — | — |
| `updates[].trackType` | enum("cinematic", "centered") | no | — | — | — |
| `updates[].name` | string | no | — | — | — |
| `updates[].depth` | object | no | strict | — | — |
| `updates[].depth.enabled` | boolean | no | — | — | — |
| `updates[].depth.intensity` | number | no | min 0; max 2 | — | — |
| `updates[].depth.focalLength` | number | no | min 24; max 120 | — | — |
| `updates[].depth.tiltX` | number | no | min -0.35; max 0.35 | — | — |
| `updates[].depth.tiltY` | number | no | min -0.35; max 0.35 | — | — |
| `updates[].depth.roll` | number | no | min -0.35; max 0.35 | — | — |
| `updates[].depth.dolly` | number | no | min -0.35; max 0.35 | — | — |
| `updates[].depth.glideTiltX` | number | no | min -0.35; max 0.35 | — | — |
| `updates[].depth.glideTiltY` | number | no | min -0.35; max 0.35 | — | — |
| `updates[].depth.glideRoll` | number | no | min -0.35; max 0.35 | — | — |
| `updates[].depth.glideDolly` | number | no | min -0.35; max 0.35 | — | — |
| `updates[].depth.anchorInfluence` | number | no | min 0; max 1 | — | — |
| `updates[].depth.depthShading` | number | no | min 0; max 0.6 | — | — |
| `updates[].depth.rim` | number | no | min 0; max 0.5 | — | — |
| `updates[].depth.sheen` | number | no | min 0; max 0.6 | — | — |
| `updates[].depth.depthBlur` | number | no | min 0; max 10 | — | — |
| `updates[].depth.shadow` | number | no | min 0; max 0.6 | — | — |
| `zoomClipIds` | string[] | no | minItems 1 | — | — |

### `action=chromaKey`

Renderer tool: `applyChromaKeyToClip`.

Apply a chroma key (green screen) effect to a video or image clip. Makes the chosen key color transparent so you can composite over another background. Use getTimelineState to find clip IDs.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `clipId` | string | yes | minLength 1 | — | — |
| `color` | string | yes | pattern `^#[0-9a-fA-F]{3,6}$` | — | Key color to make transparent (hex) |
| `threshold` | number | no | min 0; max 1 | 0.4 | Tolerance 0–1: higher = more pixels become transparent |
| `smoothness` | number | no | min 0; max 1 | 0.1 | Edge softness 0–1 (optional) |

## Result window

Every local MCP tool accepts `resultStart` and `resultEnd` so large payloads can be paged.

- `resultStart` — first character offset. Default `0`.
- `resultEnd` — exclusive end offset. Default `8000`.
- `resultEnd - resultStart` must be at most **8000** characters.
- Increment `resultStart` by 8000 to read the next window.

---
URL: https://vidova.ai/docs/mcp/tools/asset.md

# asset MCP tool

Project assets.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

MCP name `asset` dispatches to renderer `asset`.

List, search, metadata, notes, and captions are local. action transcribe starts a hosted transcription job.

Project assets. action list returns every asset. action search finds assets by filename, description, or transcript. action metadata returns pipeline metadata for one assetId. action notes sets or clears notes on an assetId. action captions returns timed captions for one assetId. action transcribe starts a caption job for one assetId; poll generate_asset kind status with the jobId, then call captions. Editor must be open. List, search, metadata, notes, and captions are local. action transcribe starts a hosted transcription job.

## Advertised MCP input

This tool is registered with **passthrough**. The fields below are what `listTools` advertises. The renderer still validates the child fields for the chosen action or kind. Extra advertised-only values are documented under Reachable behavior.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `action` | enum("list", "search", "metadata", "notes", "captions", "transcribe") | yes | — | — | action for asset |
| `assetId` | string | no | minLength 1 | — | Required for metadata, notes, captions, and transcribe. |
| `resultStart` | integer | no | min 0; max 9007199254740991 | 0 | First character offset to return. Use 0 for the first call. |
| `resultEnd` | integer | no | min 1; max 9007199254740991 | 8000 | Exclusive end offset. resultEnd - resultStart must be at most 8000. Increment resultStart by 8000 to page through large results. |

## Reachable behavior

Advertised action values match the renderer children: `list`, `search`, `metadata`, `notes`, `captions`, `transcribe`.

## Renderer child fields

These are the authoritative fields for each `action`. Send them on the same MCP call. Grouped MCP tools use passthrough, so these fields are not all listed in the advertised schema.

### `action=list`

Renderer tool: `listAssets`.

Return the uploaded assets currently available in the Assets panel.

_No fields._

### `action=search`

Renderer tool: `searchAssets`.

Search for assets by content - filename, AI description, transcripts, and detected metadata. Use when the user asks to 'find' or 'search' for specific content.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `query` | string | yes | minLength 1 | — | Search query - can be natural language like 'sunset beach' or 'person talking' |
| `type` | enum("all", "video", "audio", "image", "other") | no | — | — | Filter by asset type |
| `limit` | number | no | min 1; max 50 | 10 | Maximum number of results |

### `action=metadata`

Renderer tool: `getAssetMetadata`.

Get detailed metadata for an asset. For media: face detection, shot detection, labels, transcription, etc. For 3D model assets: returns scenes, meshes, materials, animations, and related structure. For component assets: returns component name, description, inputDefs, and full source code.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `assetId` | string | yes | minLength 1 | — | — |
| `metadataType` | enum("face-detection", "shot-detection", "label-detection", "person-detection", "transcription", "metadata") | no | — | — | — |

### `action=notes`

Renderer tool: `setAssetNotes`.

Set or update notes on an asset to remember what it is for (e.g. B-roll for intro, voiceover take 2). Use empty notes to clear.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `assetId` | string | yes | minLength 1 | — | — |
| `notes` | string | yes | — | — | — |

### `action=captions`

Renderer tool: `getAssetCaptions`.

Return timed captions (transcript and segments) for one asset. If captions are missing, call asset action transcribe with the same assetId, then poll generateAsset kind status and call captions again.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `assetId` | string | yes | minLength 1 | — | — |

### `action=transcribe`

Renderer tool: `transcribeAsset`.

Start a caption job for one audio, video, or screen-recording assetId. Returns a jobId immediately. Poll generateAsset kind status with that jobId, then call asset action captions to read the result. Does not start a second job when captions already exist or a job is already running.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `assetId` | string | yes | minLength 1 | — | — |

## Result window

Every local MCP tool accepts `resultStart` and `resultEnd` so large payloads can be paged.

- `resultStart` — first character offset. Default `0`.
- `resultEnd` — exclusive end offset. Default `8000`.
- `resultEnd - resultStart` must be at most **8000** characters.
- Increment `resultStart` by 8000 to read the next window.

---
URL: https://vidova.ai/docs/mcp/tools/inspect_media.md

# inspect_media MCP tool

Look at project media.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

MCP name `inspect_media` dispatches to renderer `inspectMedia`.

Does not use hosted quota. Local editor operation.

Look at project media. action inspect views an asset: images and audio return the media, video and screen recordings return timestamped contact sheets (optional startTime and endTime as second strings), components return source. action captureStill saves a still from an asset. action captureFaces saves detected faces. Editor must be open. Does not use hosted quota. Local editor operation.

## Advertised MCP input

This tool is registered with **passthrough**. The fields below are what `listTools` advertises. The renderer still validates the child fields for the chosen action or kind. Extra advertised-only values are documented under Reachable behavior.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `action` | enum("inspect", "captureStill", "captureFaces") | yes | — | — | action for inspect_media |
| `assetId` | string | no | minLength 1 | — | Required for inspect, captureStill, and captureFaces. |
| `timecode` | number | no | min 0 | — | Required when action is captureStill. Asset time in seconds. 0 is valid. |
| `startTime` | string | no | — | — | Optional inspect range start in seconds as a string, for example "2.5". Pair with endTime. |
| `endTime` | string | no | — | — | Optional inspect range end in seconds as a string, for example "10". Pair with startTime. |
| `resultStart` | integer | no | min 0; max 9007199254740991 | 0 | First character offset to return. Use 0 for the first call. |
| `resultEnd` | integer | no | min 1; max 9007199254740991 | 8000 | Exclusive end offset. resultEnd - resultStart must be at most 8000. Increment resultStart by 8000 to page through large results. |

## Reachable behavior

Advertised action values match the renderer children: `inspect`, `captureStill`, `captureFaces`.

## Renderer child fields

These are the authoritative fields for each `action`. Send them on the same MCP call. Grouped MCP tools use passthrough, so these fields are not all listed in the advertised schema.

### `action=inspect`

Renderer tool: `inspectAsset`.

Load an asset by ID so you can see/hear it or read its description. For image or audio: returns the media for viewing. For SVG images: returns a sanitized PNG preview when possible and sanitized SVG source code. For 3D model assets (.glb/.gltf): returns a structural summary of the model (scenes, meshes, materials, animations). For component assets: returns name, class, inputs, and full source code (no playable URL). For video or screen recording assets: returns contact-sheet stills with timestamps, covering the full asset or startTime–endTime.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `assetId` | string | yes | minLength 1 | — | — |
| `startTime` | string | no | pattern `^\d+(?:\.\d+)?$` | — | Start time in seconds, for example '2.5' or '10' |
| `endTime` | string | no | pattern `^\d+(?:\.\d+)?$` | — | End time in seconds, for example '5.0' or '15' |

### `action=captureStill`

Renderer tool: `captureAsset`.

Bookmark a timeline moment for an uploaded asset using its asset ID and capture an exact still.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `assetId` | string | yes | minLength 1 | — | — |
| `timecode` | number | yes | min 0 | — | — |
| `notes` | string | no | — | — | — |

### `action=captureFaces`

Renderer tool: `captureFaces`.

Capture frames from a video at face detection timestamps with bounding boxes drawn around detected faces.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `assetId` | string | yes | minLength 1 | — | — |
| `faceIndex` | number | no | min 0 | — | — |
| `notes` | string | no | — | — | — |

## Result window

Every local MCP tool accepts `resultStart` and `resultEnd` so large payloads can be paged.

- `resultStart` — first character offset. Default `0`.
- `resultEnd` — exclusive end offset. Default `8000`.
- `resultEnd - resultStart` must be at most **8000** characters.
- Increment `resultStart` by 8000 to read the next window.

---
URL: https://vidova.ai/docs/mcp/tools/import_asset.md

# import_asset MCP tool

Bring media into the project.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

MCP name `import_asset` dispatches to renderer `importAsset`.

Does not use hosted quota. Local editor operation.

Bring media into the project. action web downloads a direct URL. action local imports absolute file paths. action vectorize converts a raster image or URL to SVG. Editor must be open. Does not use hosted quota. Local editor operation.

## Advertised MCP input

This tool is registered with **passthrough**. The fields below are what `listTools` advertises. The renderer still validates the child fields for the chosen action or kind. Extra advertised-only values are documented under Reachable behavior.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `action` | enum("web", "local", "vectorize") | yes | — | — | action for import_asset |
| `resultStart` | integer | no | min 0; max 9007199254740991 | 0 | First character offset to return. Use 0 for the first call. |
| `resultEnd` | integer | no | min 1; max 9007199254740991 | 8000 | Exclusive end offset. resultEnd - resultStart must be at most 8000. Increment resultStart by 8000 to page through large results. |

## Reachable behavior

Advertised action values match the renderer children: `web`, `local`, `vectorize`.

## Renderer child fields

These are the authoritative fields for each `action`. Send them on the same MCP call. Grouped MCP tools use passthrough, so these fields are not all listed in the advertised schema.

### `action=web`

Renderer tool: `importWebAsset`.

Download a direct web URL into the current project Assets panel (local import — no Firebase sign-in required). Supports images, videos, audio, and 3D models. Returns an assetId for timelineEdit action addClip. Prefer import_local_assets when the file is already on disk.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `url` | string | yes | — | — | Direct URL to an image, video, audio, 3D model, or other supported asset file. |
| `fileName` | string | no | minLength 1; maxLength 180 | — | Optional filename to use in the project assets panel. |

### `action=local`

Renderer tool: `importLocalAssets`.

Import one or more local files into the current project Assets panel by absolute path. No Firebase sign-in required. Prefer this over import_web_asset when files are already on disk. Returns assetIds for timelineEdit action addClip.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `paths` | string[] | yes | minItems 1; maxItems 50 | — | Absolute local file paths to import into the open project. |

### `action=vectorize`

Renderer tool: `vectorizeImage`.

Convert a project image asset or direct image URL into an SVG vector asset. Use this for logos, icons, flat illustrations, screenshots with simple shapes, or any raster image the AI should reuse as scalable SVG. Returns the new SVG assetId.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `assetId` | string | no | minLength 1 | — | Project image asset ID to vectorize. Provide either assetId or imageUrl, not both. |
| `imageUrl` | string | no | — | — | Direct public image URL to vectorize. Provide either imageUrl or assetId, not both. |
| `outputName` | string | no | minLength 1; maxLength 180 | — | Optional SVG filename to create in project assets. |
| `preset` | enum("logo", "default", "detailed", "smooth", "sharp", "grayscale") | no | — | "logo" | Tracing preset. Use logo for icons/logos, detailed for illustrations, grayscale for monochrome art. |
| `numberOfColors` | number | no | min 2; max 32 | 8 | Palette size for color tracing. Lower values create cleaner, smaller SVGs. |
| `maxDimension` | number | no | min 128; max 2048 | 1024 | Longest side, in pixels, used for tracing before SVG generation. |
| `blurRadius` | number | no | min 0; max 5 | 0 | Optional pre-trace blur radius to smooth noisy images. |
| `minShapeOutline` | number | no | min 0; max 64 | 4 | Discard tiny traced regions. Increase this to simplify noisy SVGs. |

## Result window

Every local MCP tool accepts `resultStart` and `resultEnd` so large payloads can be paged.

- `resultStart` — first character offset. Default `0`.
- `resultEnd` — exclusive end offset. Default `8000`.
- `resultEnd - resultStart` must be at most **8000** characters.
- Increment `resultStart` by 8000 to read the next window.

---
URL: https://vidova.ai/docs/mcp/tools/preview.md

# preview MCP tool

Look at the live timeline.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

MCP name `preview` dispatches to renderer `preview`.

Does not use hosted quota. Local editor operation.

Look at the live timeline. action captureFrame requires timecode in seconds (0 is valid) and captures one composed still. action timeline returns timestamped contact sheets of the composed timeline (optional startTime and endTime in seconds). Editor must be open. Does not use hosted quota. Local editor operation.

## Advertised MCP input

This tool is registered with **passthrough**. The fields below are what `listTools` advertises. The renderer still validates the child fields for the chosen action or kind. Extra advertised-only values are documented under Reachable behavior.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `action` | enum("captureFrame", "timeline") | yes | — | — | action for preview |
| `timecode` | number | no | min 0 | — | Required when action is captureFrame. Timeline time in seconds to seek to before capturing. 0 is valid. |
| `grid` | number | no | exclusiveMin 0 | — | Optional captureFrame grid step in scene pixels (top-left origin). |
| `crop` | object | no | strict | — | Optional captureFrame crop rectangle in scene pixels. |
| `crop.x` | number | yes | — | — | Crop left edge in scene pixels (top-left origin) |
| `crop.y` | number | yes | — | — | Crop top edge in scene pixels (top-left origin) |
| `crop.w` | number | yes | exclusiveMin 0 | — | Crop width in scene pixels |
| `crop.h` | number | yes | exclusiveMin 0 | — | Crop height in scene pixels |
| `startTime` | number | no | min 0 | — | Optional start time in seconds for action timeline. |
| `endTime` | number | no | min 0 | — | Optional end time in seconds for action timeline. |
| `resultStart` | integer | no | min 0; max 9007199254740991 | 0 | First character offset to return. Use 0 for the first call. |
| `resultEnd` | integer | no | min 1; max 9007199254740991 | 8000 | Exclusive end offset. resultEnd - resultStart must be at most 8000. Increment resultStart by 8000 to page through large results. |

## Reachable behavior

Advertised action values match the renderer children: `captureFrame`, `timeline`.

## Renderer child fields

These are the authoritative fields for each `action`. Send them on the same MCP call. Grouped MCP tools use passthrough, so these fields are not all listed in the advertised schema.

### `action=captureFrame`

Renderer tool: `previewCaptureFrame`.

Seek the live preview to a specific time and capture the current frame from the preview canvas. Optional grid (scene-pixel step) and crop (scene top-left x/y/w/h) annotate absolute coordinates so you can place overlays without guessing. Timeline clip positions use center origin: position.x = topLeftX - sceneWidth/2. Use this as the default way to verify timeline edits; capture several timecodes for motion-heavy changes. This is much faster than rendering a video preview.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `timecode` | number | yes | min 0 | — | Time in seconds on the timeline to seek to before capturing the frame. |
| `grid` | number | no | exclusiveMin 0 | — | Optional grid step in scene pixels (top-left origin). Draws labeled axes so you can read absolute coordinates from the image. |
| `crop` | object | no | strict | — | Optional crop rectangle in scene pixels (top-left origin). Use with grid to zoom into a UI region. |
| `crop.x` | number | yes | — | — | Crop left edge in coordinate-space pixels (top-left origin) |
| `crop.y` | number | yes | — | — | Crop top edge in coordinate-space pixels (top-left origin) |
| `crop.w` | number | yes | exclusiveMin 0 | — | Crop width in coordinate-space pixels |
| `crop.h` | number | yes | exclusiveMin 0 | — | Crop height in coordinate-space pixels |

### `action=timeline`

Renderer tool: `previewTimeline`.

Sample the composed timeline as timestamped contact-sheet stills. Omit startTime and endTime for the full duration, or pass both in seconds for a range. Use captureFrame when you need one high-resolution still at a known timecode.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `startTime` | number | no | min 0 | — | Start time in seconds. Required with endTime, or omit both for the full timeline. |
| `endTime` | number | no | min 0 | — | End time in seconds. Required with startTime, or omit both for the full timeline. |

## Result window

Every local MCP tool accepts `resultStart` and `resultEnd` so large payloads can be paged.

- `resultStart` — first character offset. Default `0`.
- `resultEnd` — exclusive end offset. Default `8000`.
- `resultEnd - resultStart` must be at most **8000** characters.
- Increment `resultStart` by 8000 to read the next window.

---
URL: https://vidova.ai/docs/mcp/tools/generate_asset.md

# generate_asset MCP tool

Start or poll hosted generation.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

MCP name `generate_asset` dispatches to renderer `generateAsset`.

Image generation uses your image-generation allowance. Speech is included with a usage quota.

Start or poll hosted generation. kind image uses prompt, aspectRatio, imageSize. kind music uses prompt and durationSeconds. kind speech uses text and voice. kind video uses prompt, durationSeconds, aspectRatio, resolution, negativePrompt. kind status polls jobId from those jobs or from asset transcribe. Editor must be open. Image generation uses your image-generation allowance. Speech is included with a usage quota.

## Advertised MCP input

This tool is registered with **passthrough**. The fields below are what `listTools` advertises. The renderer still validates the child fields for the chosen action or kind. Extra advertised-only values are documented under Reachable behavior.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `kind` | enum("image", "music", "speech", "video", "status") | yes | — | — | kind for generate_asset |
| `resultStart` | integer | no | min 0; max 9007199254740991 | 0 | First character offset to return. Use 0 for the first call. |
| `resultEnd` | integer | no | min 1; max 9007199254740991 | 8000 | Exclusive end offset. resultEnd - resultStart must be at most 8000. Increment resultStart by 8000 to page through large results. |

## Reachable behavior

MCP advertisement and the renderer child map are not the same. Call only what the renderer wires.

**Advertised but not reachable:** `music`, `video`. The MCP wrapper lists these values. The renderer does not register a child for them, so the call fails.

## Renderer child fields

These are the authoritative fields for each `kind`. Send them on the same MCP call. Grouped MCP tools use passthrough, so these fields are not all listed in the advertised schema.

### `kind=image`

Renderer tool: `generateImage`.

Start generating an image from a text prompt. Returns a job ID immediately; poll generationStatus with that job ID until the job is completed to get the resulting image asset.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `prompt` | string | yes | minLength 1 | — | — |
| `aspectRatio` | enum("1:1", "16:9", "9:16") | no | — | "1:1" | — |
| `imageSize` | enum("1K", "2K", "4K") | no | — | "1K" | — |

### `kind=speech`

Renderer tool: `generateSpeech`.

Start generating speech from text. Included with a usage quota. Returns a job ID immediately; poll generationStatus with that job ID until it is completed to get the audio asset.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `text` | string | yes | minLength 2; maxLength 5000 | — | — |
| `voice` | enum("asteria", "luna", "stella", "athena", "hera", "orion", "arcas", "perseus", "angus", "orpheus", "helios", "zeus") | no | — | "asteria" | — |

### `kind=status`

Renderer tool: `generationStatus`.

Check the status of an image, speech, or transcription job by its job ID. Returns the result when the job is completed, or the error if it failed. After a transcription job completes, call asset action captions to read the captions.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `jobId` | string | yes | minLength 1 | — | — |

## Result window

Every local MCP tool accepts `resultStart` and `resultEnd` so large payloads can be paged.

- `resultStart` — first character offset. Default `0`.
- `resultEnd` — exclusive end offset. Default `8000`.
- `resultEnd - resultStart` must be at most **8000** characters.
- Increment `resultStart` by 8000 to read the next window.

---
URL: https://vidova.ai/docs/mcp/tools/sfx.md

# sfx MCP tool

Search and import sound effects.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

MCP name `sfx` dispatches to renderer `sfx`.

Does not use hosted quota. Local editor operation.

Search and import sound effects. action search queries the sound library. action import downloads a soundId from search results into the project. Editor must be open. Does not use hosted quota. Local editor operation.

## Advertised MCP input

This tool is registered with **passthrough**. The fields below are what `listTools` advertises. The renderer still validates the child fields for the chosen action or kind. Extra advertised-only values are documented under Reachable behavior.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `action` | enum("search", "import") | yes | — | — | action for sfx |
| `resultStart` | integer | no | min 0; max 9007199254740991 | 0 | First character offset to return. Use 0 for the first call. |
| `resultEnd` | integer | no | min 1; max 9007199254740991 | 8000 | Exclusive end offset. resultEnd - resultStart must be at most 8000. Increment resultStart by 8000 to page through large results. |

## Reachable behavior

Advertised action values match the renderer children: `search`, `import`.

## Renderer child fields

These are the authoritative fields for each `action`. Send them on the same MCP call. Grouped MCP tools use passthrough, so these fields are not all listed in the advertised schema.

### `action=search`

Renderer tool: `searchSfx`.

Search for sound effects to use in the video. Returns sound IDs that can be passed to importSfx. Use this for whooshes, risers, impacts, UI sounds, foley, glitch hits, camera clicks, transitions, and other short effects.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `query` | string | yes | minLength 1 | — | Sound effect search query, for example 'whoosh', 'glitch hit', 'riser', or 'camera shutter' |
| `limit` | number | no | min 1; max 40 | 10 | Maximum number of sound effects to return |
| `maxDuration` | number | no | min 1; max 120 | 20 | Only return sound effects up to this many seconds long |

### `action=import`

Renderer tool: `importSfx`.

Import a sound effect into the current project's Assets panel. Use a soundId returned by searchSfx. After import, the asset can be added to the timeline with timelineEdit action addClip using type='audio' and the returned assetId.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `soundId` | string | yes | minLength 1 | — | Sound ID from searchSfx results |

## Result window

Every local MCP tool accepts `resultStart` and `resultEnd` so large payloads can be paged.

- `resultStart` — first character offset. Default `0`.
- `resultEnd` — exclusive end offset. Default `8000`.
- `resultEnd - resultStart` must be at most **8000** characters.
- Increment `resultStart` by 8000 to read the next window.

---
URL: https://vidova.ai/docs/mcp/tools/component.md

# component MCP tool

Custom components and scene config.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

MCP name `component` dispatches to renderer `component`.

Does not use hosted quota. Local editor operation.

Custom components and scene config. action create writes a new component from name, code, componentName. action createFromTemplate instantiates a catalog template. action edit updates an existing component assetId. action setSceneConfig sets resolution, fps, background, style, or caption defaults. After create or createFromTemplate, place the component with timeline_edit action addClip, type component, and the returned assetId. Editor must be open. Does not use hosted quota. Local editor operation.

## Advertised MCP input

This tool is registered with **passthrough**. The fields below are what `listTools` advertises. The renderer still validates the child fields for the chosen action or kind. Extra advertised-only values are documented under Reachable behavior.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `action` | enum("create", "createFromTemplate", "edit", "setSceneConfig") | yes | — | — | action for component |
| `resultStart` | integer | no | min 0; max 9007199254740991 | 0 | First character offset to return. Use 0 for the first call. |
| `resultEnd` | integer | no | min 1; max 9007199254740991 | 8000 | Exclusive end offset. resultEnd - resultStart must be at most 8000. Increment resultStart by 8000 to page through large results. |

## Reachable behavior

Advertised action values match the renderer children: `create`, `createFromTemplate`, `edit`, `setSceneConfig`.

## Renderer child fields

These are the authoritative fields for each `action`. Send them on the same MCP call. Grouped MCP tools use passthrough, so these fields are not all listed in the advertised schema.

### `action=create`

Renderer tool: `createComponent`.

Create a new Vidova custom component asset with TSX source code. Supports inputDefs including asset inputs: clip values store asset IDs; at preview/render, video/audio/image/model3d inputs become playback URLs, while assetTypes ['vidova'] becomes a VidovaClipData object with screen, camera, cursor, click, and keyboard data. For image/video/audio signals use @initial('') — never put an asset ID in @initial. Pass the signal to `<Img src>` or `<Video src>` with explicit width and height. Place only the component clip; do not add a parallel image/video clip for the same asset. Import from @vidova/2d, @vidova/core, and @vidova/components. Shaders are SkSL, not GLSL: wrap content in a cached node and pass shaders={{ fragment, uniforms }}. Put `#include "@vidova/core/shaders/common.sksl"` at the top of the fragment, or wrap the body with withCommonShader() from @vidova/core. Entry point is half4 main(float2 coord); sample with sampleSource(uv). For embedded Video nodes, call videoRef().play() directly; never spawn(videoRef().play()) because Video.play() returns void. The component will be compiled and available for use on the timeline.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `name` | string | yes | minLength 1 | — | Display name for the component asset |
| `code` | string | yes | minLength 1 | — | Vidova Motion TSX source code |
| `componentName` | string | yes | minLength 1 | — | Exported class name (e.g. ProgressRing) |
| `inputDefs` | object[] | no | — | — | Input definitions for dynamic props. For type 'asset', default/component input values are asset IDs; Vidova resolves them to playback URLs before passing props into the component. |
| `inputDefs[].name` | string | yes | — | — | — |
| `inputDefs[].type` | enum("string", "number", "boolean", "color", "enum", "asset", "font") | yes | — | — | — |
| `inputDefs[].default` | string \\| number \\| boolean | yes | — | — | — |
| `inputDefs[].label` | string | no | — | — | — |
| `inputDefs[].options` | string[] | no | — | — | For type 'enum': list of allowed options the user can choose from |
| `inputDefs[].assetTypes` | enum("video", "audio", "image", "model3d", "vidova")[] | no | — | — | For type 'asset': accepted asset kinds. Defaults to video/audio/image/model3d/vidova. |
| `description` | string | no | — | — | Short description of what the component does |

### `action=createFromTemplate`

Renderer tool: `createComponentFromTemplate`.

Create a component from a premade template. Much faster than writing code from scratch. Use this when the user wants a standard component like simple text, a world map, typewriter text, progress ring, counter, pulsing dot, or lower third bar. You can customise the component by passing inputOverrides to set colours, text, sizes, and other parameters. Available templates:


| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `templateId` | string | yes | minLength 1 | — | ID of the template to use. Available templates:<br /> |
| `inputOverrides` | object | no | — | — | Override default input values. Keys must match the template's inputDef names. For example: { "highlightCountry": "Brazil", "landColor": "#1b4332" } |
| `name` | string | no | minLength 1 | — | Custom display name for the asset. Defaults to the template name. |
| `description` | string | no | — | — | Short description of this instance |

Catalog `templateId` values:

- `simple-text`
- `typewriter`
- `progress-ring`
- `counter`
- `pulsing-dot`
- `world-map-3d`
- `lower-third-bar`
- `fullscreen-overlay-a`
- `fullscreen-overlay-b`
- `fullscreen-overlay-c`
- `fullscreen-overlay-d`
- `fullscreen-overlay-e`
- `fullscreen-overlay-f`
- `callout-arrow`
- `keystroke-display`
- `code-block`
- `caption-pill`
- `caption-karaoke`
- `caption-highlight`

### `action=edit`

Renderer tool: `editComponent`.

Edit an existing Vidova custom component. Can update code, name, componentName, inputDefs, or description. inputDefs may include asset inputs: clip values store asset IDs; at preview/render, video/audio/image/model3d inputs become playback URLs, while assetTypes ['vidova'] becomes a VidovaClipData object. For image/video/audio signals use @initial('') — never put an asset ID in @initial. Pass the signal to `<Img src>` or `<Video src>` with explicit width and height. Place only the component clip; do not add a parallel image/video clip for the same asset. Import from @vidova/2d, @vidova/core, and @vidova/components. Shaders are SkSL, not GLSL: wrap content in a cached node and pass shaders={{ fragment, uniforms }}. Put `#include "@vidova/core/shaders/common.sksl"` at the top of the fragment, or wrap the body with withCommonShader() from @vidova/core. Entry point is half4 main(float2 coord); sample with sampleSource(uv). For embedded Video nodes, call videoRef().play() directly; never spawn(videoRef().play()) because Video.play() returns void. When updating code, provide the complete new source.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `assetId` | string | yes | minLength 1 | — | ID of the component asset to edit |
| `code` | string | no | — | — | Updated Vidova Motion TSX source code |
| `name` | string | no | — | — | Updated display name |
| `componentName` | string | no | — | — | Updated exported class name |
| `inputDefs` | object[] | no | — | — | Updated input definitions. For type 'asset', default/component input values are asset IDs; Vidova resolves them to playback URLs before passing props into the component. |
| `inputDefs[].name` | string | yes | — | — | — |
| `inputDefs[].type` | enum("string", "number", "boolean", "color", "enum", "asset", "font") | yes | — | — | — |
| `inputDefs[].default` | string \\| number \\| boolean | yes | — | — | — |
| `inputDefs[].label` | string | no | — | — | — |
| `inputDefs[].options` | string[] | no | — | — | For type 'enum': list of allowed options the user can choose from |
| `inputDefs[].assetTypes` | enum("video", "audio", "image", "model3d", "vidova")[] | no | — | — | For type 'asset': accepted asset kinds. Defaults to video/audio/image/model3d/vidova. |
| `description` | string | no | — | — | Updated description |

### `action=setSceneConfig`

Renderer tool: `setSceneConfig`.

Set project resolution, frame rate, background, wallpaper, name, caption/text defaults, or a complete project style. Only provided fields are updated; explicit fields are applied after styleState.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `width` | integer | no | min 320; max 9007199254740991 | — | Output width in pixels (min 320) |
| `height` | integer | no | min 240; max 9007199254740991 | — | Output height in pixels (min 240) |
| `fps` | integer | no | min 1; max 240 | — | Frames per second (1–240). Common: 24, 30, 60. |
| `background` | string | no | minLength 1 | — | Background color, gradient, or CSS value |
| `backgroundImage` | object \\| null | no | — | — | Wallpaper asset and dimensions. Pass null to clear the wallpaper. |
| `name` | string | no | minLength 1; maxLength 180 | — | Project name |
| `captionSettings` | object | no | strict | — | Project caption defaults; merges with current/default settings. |
| `captionSettings.enabled` | boolean | no | — | — | — |
| `captionSettings.fontFamily` | string | no | — | — | — |
| `captionSettings.fontWeight` | 400 \\| 500 \\| 700 | no | — | — | — |
| `captionSettings.fontSize` | number | no | — | — | — |
| `captionSettings.distanceFromBottom` | number | no | — | — | — |
| `captionSettings.style` | enum("pill", "karaoke-lime", "karaoke-magenta", "karaoke-cyan", "outlined", "bold-outline", "minimal", "word-highlight", "pink-pill", "dark-pill-lime", "cloud-blob", "amber-tape", "studio") | no | — | — | — |
| `captionSettings.textColor` | string | no | — | — | — |
| `captionSettings.highlightColor` | string | no | — | — | — |
| `captionSettings.backgroundColor` | string | no | — | — | — |
| `captionSettings.shadowColor` | string | no | — | — | — |
| `captionSettings.shadowBlur` | number | no | — | — | — |
| `captionSettings.maxCharsPerLine` | number | no | — | — | — |
| `textClipSettings` | object | no | strict | — | Defaults for newly created text clips; merges with current/default settings. |
| `textClipSettings.fontFamily` | string | no | — | — | — |
| `textClipSettings.fontWeight` | 400 \\| 500 \\| 700 | no | — | — | — |
| `textClipSettings.defaultFontSize` | number | no | — | — | — |
| `textClipSettings.defaultFill` | string | no | — | — | — |
| `styleState` | object | no | strict | — | Complete project style plus override keys. The style is applied to existing Vidova clips. |
| `styleState.style` | object | yes | strict | — | — |
| `styleState.style.id` | enum("launch", "demo-day", "tutorial", "social-cut", "deep-dive", "sales-demo", "parallax", "sunset", "pop", "terminal", "course", "mobile", "webinar", "mono", "plain") | yes | — | — | — |
| `styleState.style.background` | string | yes | minLength 1 | — | — |
| `styleState.style.padding` | number | yes | min 0; max 400 | — | — |
| `styleState.style.cornerRadius` | number | yes | min 0; max 200 | — | — |
| `styleState.style.shadowStrength` | number | yes | min 0; max 100 | — | — |
| `styleState.style.zoomIntensity` | 0 \\| 1 \\| 2 \\| 3 \\| 4 \\| 5 | yes | — | — | — |
| `styleState.style.zoomFeel` | enum("soft-spring", "snappy-spring", "soft-landing", "fast-settle", "gentle-curve") | no | — | "soft-spring" | — |
| `styleState.style.zoom3D` | boolean | no | — | false | — |
| `styleState.style.cursorStyle` | enum("default", "cartoon", "modern", "original", "banana", "capitaine-dark", "capitaine-light", "touch", "tahoe", "whitesur", "bibata", "bibata-original") | no | — | "default" | — |
| `styleState.style.cursorSize` | number | no | min 24; max 200 | 64 | — |
| `styleState.style.cursorSpotlight` | boolean | no | — | false | — |
| `styleState.style.cameraShape` | enum("default", "squircle", "circle") | yes | — | — | — |
| `styleState.style.cameraSize` | number | yes | min 0; max 1 | — | — |
| `styleState.style.showShortcuts` | boolean | yes | — | — | — |
| `styleState.style.captionsEnabled` | boolean | yes | — | — | — |
| `styleState.style.captionStyle` | enum("pill", "karaoke-lime", "karaoke-magenta", "karaoke-cyan", "outlined", "bold-outline", "minimal", "word-highlight", "pink-pill", "dark-pill-lime", "cloud-blob", "amber-tape", "studio") | yes | — | — | — |
| `styleState.style.captionFontSize` | number | yes | min 8; max 200 | — | — |
| `styleState.overrides` | enum("background", "padding", "cornerRadius", "shadowStrength", "zoomIntensity", "zoomFeel", "zoom3D", "cursor", "cameraShape", "cameraSize", "showShortcuts", "captions")[] | yes | — | — | — |

## Result window

Every local MCP tool accepts `resultStart` and `resultEnd` so large payloads can be paged.

- `resultStart` — first character offset. Default `0`.
- `resultEnd` — exclusive end offset. Default `8000`.
- `resultEnd - resultStart` must be at most **8000** characters.
- Increment `resultStart` by 8000 to read the next window.

---
URL: https://vidova.ai/docs/mcp/tools/branch_action.md

# branch_action MCP tool

Project branches.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

MCP name `branch_action` dispatches to renderer `branchAction`.

Does not use hosted quota. Local editor operation.

Project branches. action list shows branches and the current branch. action create makes a branch (branchName, optional sourceBranch, switchToBranch). action switch moves the editor (branchId). action merge merges sourceBranch into targetBranch (defaults to main). action mergeToMain merges the current feature branch into main. Merge actions require approval. Editor must be open. Does not use hosted quota. Local editor operation.

## Advertised MCP input

This tool is registered with **passthrough**. The fields below are what `listTools` advertises. The renderer still validates the child fields for the chosen action or kind. Extra advertised-only values are documented under Reachable behavior.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `action` | enum("list", "create", "switch", "merge", "mergeToMain") | yes | — | — | action for branch_action |
| `resultStart` | integer | no | min 0; max 9007199254740991 | 0 | First character offset to return. Use 0 for the first call. |
| `resultEnd` | integer | no | min 1; max 9007199254740991 | 8000 | Exclusive end offset. resultEnd - resultStart must be at most 8000. Increment resultStart by 8000 to page through large results. |

## Reachable behavior

Advertised action values match the renderer children: `list`, `create`, `switch`, `merge`, `mergeToMain`.

## Renderer child fields

These are the authoritative fields for each `action`. Send them on the same MCP call. Grouped MCP tools use passthrough, so these fields are not all listed in the advertised schema.

### `action=list`

Renderer tool: `listBranches`.

List project branches and identify the currently active branch. Use before creating, switching, or merging branches when branch names are unclear.

_No fields._

### `action=create`

Renderer tool: `createBranch`.

Create a project branch from the current branch or a specified source branch. By default this also switches the editor to the new branch.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `branchName` | string | yes | minLength 1; maxLength 80 | — | — |
| `sourceBranch` | string | no | minLength 1 | — | — |
| `switchToBranch` | boolean | no | — | true | — |

### `action=switch`

Renderer tool: `switchBranch`.

Switch the editor to an existing project branch. Use listBranches first if you do not know the branch ID.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `branchId` | string | yes | minLength 1 | — | — |

### `action=merge`

Renderer tool: `mergeBranch`.

Merge one project branch into another. Requires user approval before executing. Defaults to merging the current branch into main.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `sourceBranch` | string | no | minLength 1 | — | — |
| `targetBranch` | string | no | minLength 1 | "main" | — |
| `switchToTarget` | boolean | no | — | false | — |

### `action=mergeToMain`

Renderer tool: `mergeBranchToMain`.

Merge the current feature branch into the main branch so changes are persisted. Requires user approval before executing. Only works when on a feature branch (not main).

_No fields._

## Result window

Every local MCP tool accepts `resultStart` and `resultEnd` so large payloads can be paged.

- `resultStart` — first character offset. Default `0`.
- `resultEnd` — exclusive end offset. Default `8000`.
- `resultEnd - resultStart` must be at most **8000** characters.
- Increment `resultStart` by 8000 to read the next window.

---
URL: https://vidova.ai/docs/mcp/tools/project_history.md

# project_history MCP tool

Get edit history, or perform undo/redo.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

MCP name `project_history` dispatches to renderer `projectHistory`.

Does not use hosted quota. Local editor operation.

Get edit history, or perform undo/redo. Editor must be open. Does not use hosted quota. Local editor operation.

## Advertised MCP input

The MCP server validates this object with `.strict()`. Unknown fields are rejected.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `action` | enum("status", "undo", "redo") | no | — | "status" | 'status' lists history, 'undo'/'redo' perform the action |
| `steps` | integer | no | min 1; max 50 | — | Number of steps to undo/redo (default 1) |
| `resultStart` | integer | no | min 0; max 9007199254740991 | 0 | First character offset to return. Use 0 for the first call. |
| `resultEnd` | integer | no | min 1; max 9007199254740991 | 8000 | Exclusive end offset. resultEnd - resultStart must be at most 8000. Increment resultStart by 8000 to page through large results. |


## Renderer schema

Authoritative input the editor applies after MCP passthrough or dispatch.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `action` | enum("status", "undo", "redo") | no | — | "status" | — |
| `steps` | integer | no | min 1; max 50 | — | — |

## Result window

Every local MCP tool accepts `resultStart` and `resultEnd` so large payloads can be paged.

- `resultStart` — first character offset. Default `0`.
- `resultEnd` — exclusive end offset. Default `8000`.
- `resultEnd - resultStart` must be at most **8000** characters.
- Increment `resultStart` by 8000 to read the next window.

---
URL: https://vidova.ai/docs/mcp/tools/recipe.md

# recipe MCP tool

Reusable playbooks.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

MCP name `recipe` dispatches to renderer `recipe`.

Does not use hosted quota. Local editor operation.

Reusable playbooks. action search finds recipes by query. action get loads one recipeId. action create writes a private recipe. action update patches an existing private recipe. Editor must be open. Does not use hosted quota. Local editor operation.

## Advertised MCP input

This tool is registered with **passthrough**. The fields below are what `listTools` advertises. The renderer still validates the child fields for the chosen action or kind. Extra advertised-only values are documented under Reachable behavior.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `action` | enum("search", "get", "create", "update") | yes | — | — | action for recipe |
| `resultStart` | integer | no | min 0; max 9007199254740991 | 0 | First character offset to return. Use 0 for the first call. |
| `resultEnd` | integer | no | min 1; max 9007199254740991 | 8000 | Exclusive end offset. resultEnd - resultStart must be at most 8000. Increment resultStart by 8000 to page through large results. |

## Reachable behavior

Advertised action values match the renderer children: `search`, `get`, `create`, `update`.

## Renderer child fields

These are the authoritative fields for each `action`. Send them on the same MCP call. Grouped MCP tools use passthrough, so these fields are not all listed in the advertised schema.

### `action=search`

Renderer tool: `searchRecipes`.

Search semantic document playbooks that can raise output quality. Requires AI Search to be ready (embedding model + recipe index). In Agent Mode, try this before tackling substantive user tasks so existing recipes can guide the work. If unavailable because AI Search is still warming up, continue without recipes — do not retry until ready.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `query` | string | yes | minLength 1 | — | Natural language description of the needed reusable playbook. |
| `visibility` | enum("all", "private", "public") | no | — | "all" | — |
| `limit` | number | no | min 1; max 20 | 5 | — |

### `action=get`

Renderer tool: `getRecipe`.

Retrieve one recipe playbook as structured context and record basic usage. Use before applying a recipe.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `recipeId` | string | yes | minLength 1 | — | Recipe ID returned by searchRecipes. |
| `visibility` | enum("all", "private", "public") | no | — | "all" | — |

### `action=create`

Renderer tool: `createRecipe`.

Create a private reusable recipe playbook. Requires AI Search to be ready (embedding model + recipe index). Before creating, searchRecipes should be used to avoid duplicates and updateRecipe should be used for a close match. If AI Search is still warming up, skip creating a recipe.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `title` | string | yes | minLength 1; maxLength 200 | — | — |
| `summary` | string | yes | minLength 1; maxLength 2000 | — | — |
| `whenToUse` | string | yes | minLength 1; maxLength 8000 | — | — |
| `steps` | object[] | yes | minItems 1; maxItems 80 | — | — |
| `steps[].title` | string | yes | minLength 1; maxLength 200 | — | — |
| `steps[].detail` | string | yes | minLength 1; maxLength 8000 | — | — |
| `acceptanceCriteria` | string[] | yes | minItems 1; maxItems 80 | — | — |
| `tags` | string[] | no | maxItems 40 | [] | — |
| `document` | string | yes | minLength 1; maxLength 80000 | — | — |

### `action=update`

Renderer tool: `updateRecipe`.

Update an existing private recipe when a new reusable pattern overlaps it. Requires AI Search to be ready (embedding model + recipe index). Use after searchRecipes finds a close match. If AI Search is still warming up, skip updating recipes.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `recipeId` | string | yes | minLength 1 | — | — |
| `title` | string | no | minLength 1; maxLength 200 | — | — |
| `summary` | string | no | minLength 1; maxLength 2000 | — | — |
| `whenToUse` | string | no | minLength 1; maxLength 8000 | — | — |
| `steps` | object[] | no | minItems 1; maxItems 80 | — | — |
| `steps[].title` | string | yes | minLength 1; maxLength 200 | — | — |
| `steps[].detail` | string | yes | minLength 1; maxLength 8000 | — | — |
| `acceptanceCriteria` | string[] | no | minItems 1; maxItems 80 | — | — |
| `tags` | string[] | no | maxItems 40 | — | — |
| `document` | string | no | minLength 1; maxLength 80000 | — | — |

## Result window

Every local MCP tool accepts `resultStart` and `resultEnd` so large payloads can be paged.

- `resultStart` — first character offset. Default `0`.
- `resultEnd` — exclusive end offset. Default `8000`.
- `resultEnd - resultStart` must be at most **8000** characters.
- Increment `resultStart` by 8000 to read the next window.

---
URL: https://vidova.ai/docs/mcp/tools/sleep.md

# sleep MCP tool

Wait for a specified number of seconds before continuing.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

MCP name `sleep` dispatches to renderer `sleep`.

Does not use hosted quota. Local editor operation.

Wait for a specified number of seconds before continuing. Useful between polling calls. Does not use hosted quota. Local editor operation.

## Advertised MCP input

The MCP server validates this object with `.strict()`. Unknown fields are rejected.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `seconds` | number | yes | exclusiveMin 0 | — | Seconds to wait |
| `resultStart` | integer | no | min 0; max 9007199254740991 | 0 | First character offset to return. Use 0 for the first call. |
| `resultEnd` | integer | no | min 1; max 9007199254740991 | 8000 | Exclusive end offset. resultEnd - resultStart must be at most 8000. Increment resultStart by 8000 to page through large results. |


## Renderer schema

Authoritative input the editor applies after MCP passthrough or dispatch.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `seconds` | integer | no | min 1; max 60 | 5 | — |

## Result window

Every local MCP tool accepts `resultStart` and `resultEnd` so large payloads can be paged.

- `resultStart` — first character offset. Default `0`.
- `resultEnd` — exclusive end offset. Default `8000`.
- `resultEnd - resultStart` must be at most **8000** characters.
- Increment `resultStart` by 8000 to read the next window.

---
URL: https://vidova.ai/docs/mcp/schemas/camera-settings.md

# cameraSettings schema

Field specification for the cameraSettings object used by Vidova MCP tools.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

Export `cameraSettingsSchema` from the desktop Zod sources.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `position` | object | no | — | — | Whole-composition pan in scene pixels. |
| `position.x` | number | yes | — | — | — |
| `position.y` | number | yes | — | — | — |
| `zoom` | number | no | min 0.05 | — | Whole-composition camera zoom. 1 = default, 2 = 2x. |
| `rotation` | number | no | — | — | Whole-composition camera rotation in degrees. |

---
URL: https://vidova.ai/docs/mcp/schemas/caption-settings.md

# captionSettings schema

Field specification for the captionSettings object used by Vidova MCP tools.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

Export `captionSettingsUpdateSchema` from the desktop Zod sources.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `enabled` | boolean | no | — | — | — |
| `fontFamily` | string | no | — | — | — |
| `fontWeight` | 400 \\| 500 \\| 700 | no | — | — | — |
| `fontSize` | number | no | — | — | — |
| `distanceFromBottom` | number | no | — | — | — |
| `style` | enum("pill", "karaoke-lime", "karaoke-magenta", "karaoke-cyan", "outlined", "bold-outline", "minimal", "word-highlight", "pink-pill", "dark-pill-lime", "cloud-blob", "amber-tape", "studio") | no | — | — | — |
| `textColor` | string | no | — | — | — |
| `highlightColor` | string | no | — | — | — |
| `backgroundColor` | string | no | — | — | — |
| `shadowColor` | string | no | — | — | — |
| `shadowBlur` | number | no | — | — | — |
| `maxCharsPerLine` | number | no | — | — | — |

---
URL: https://vidova.ai/docs/mcp/schemas/chroma-key.md

# chromaKey schema

Field specification for the chromaKey object used by Vidova MCP tools.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

Export `chromaKeySchema` from the desktop Zod sources.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `color` | string | yes | pattern `^#[0-9a-fA-F]{3,6}$` | — | — |
| `threshold` | number | yes | min 0; max 1 | — | — |
| `smoothness` | number | no | min 0; max 1 | — | — |

---
URL: https://vidova.ai/docs/mcp/schemas/clip-transition.md

# clipTransition schema

Field specification for the clipTransition object used by Vidova MCP tools.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

Export `clipTransitionSchema` from the desktop Zod sources.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `type` | enum("none", "fade", "slide-left", "slide-right", "slide-up", "slide-down", "cross-dissolve", "zoom", "blur", "dip-to-black", "rgb-split-in", "rgb-split-out", "fisheye-in", "fisheye-out", "swoosh-left", "swoosh-right", "swoosh-up", "swoosh-down", "radial-blur-burst", "glitch-pop-in", "glitch-pop-out", "whip-pan-left", "whip-pan-right", "pixel-burst", "light-leak", "liquid-warp", "prism-split", "bounce-pop", "spin-zoom", "shake-pop", "flash-bang", "vortex-twist") | yes | — | — | Transition type. One of: none, fade, slide-left/right/up/down, cross-dissolve, zoom, blur, dip-to-black, rgb-split-in/out, fisheye-in/out, swoosh-left/right/up/down, radial-blur-burst, glitch-pop-in/out, whip-pan-left/right, pixel-burst, light-leak, liquid-warp, prism-split, bounce-pop, spin-zoom, shake-pop, flash-bang, vortex-twist. Use "none" to clear. |
| `duration` | number | yes | min 0.1; max 5 | — | Duration in seconds (0.1–5) |

---
URL: https://vidova.ai/docs/mcp/schemas/color-grading.md

# colorGrading schema

Field specification for the colorGrading object used by Vidova MCP tools.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

Export `colorGradingSchema` from the desktop Zod sources.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `exposure` | number | no | min -2; max 2 | — | Range -2 to 2 only |
| `contrast` | number | no | min -100; max 100 | — | Range -100 to 100. Use 15-50 for visible effect (not 0.1). |
| `saturation` | number | no | min -100; max 100 | — | Range -100 to 100. Use 15-50 for visible effect (not 0.15). |
| `temperature` | number | no | min -100; max 100 | — | Range -100 to 100 (cool to warm). Use 15-50 for visible effect (not 0.2). |
| `tint` | number | no | min -100; max 100 | — | Range -100 to 100 (green to magenta). Use 15-50 for visible effect. |
| `highlights` | number | no | min -100; max 100 | — | Range -100 to 100. Use 15-50 for visible effect. |
| `shadows` | number | no | min -100; max 100 | — | Range -100 to 100. Use 15-50 for visible effect. |

---
URL: https://vidova.ai/docs/mcp/schemas/cursor-spotlight.md

# cursorSpotlight schema

Field specification for the cursorSpotlight object used by Vidova MCP tools.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

Export `cursorSpotlightUpdateSchema` from the desktop Zod sources.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `enabled` | boolean | no | — | — | — |
| `radius` | number | no | — | — | — |
| `softness` | number | no | — | — | — |
| `dimOpacity` | number | no | — | — | — |
| `onlyOnClick` | boolean | no | — | — | — |
| `clickWindow` | number | no | min 0.05; max 4 | — | — |

---
URL: https://vidova.ai/docs/mcp/schemas/focus.md

# focus schema

Field specification for the focus object used by Vidova MCP tools.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

Export `focusSchema` from the desktop Zod sources.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `x` | number | yes | min 0; max 1 | — | — |
| `y` | number | yes | min 0; max 1 | — | — |
| `zoom` | number | yes | min 1 | — | — |

---
URL: https://vidova.ai/docs/mcp/schemas/keyframe-action.md

# keyframeAction schema

Field specification for the keyframeAction object used by Vidova MCP tools.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

Export `keyframeActionSchema` from the desktop Zod sources.

_No fields._

---
URL: https://vidova.ai/docs/mcp/schemas/mouse-indicator.md

# vidovaSettings.mouseIndicator schema

Field specification for the vidovaSettings.mouseIndicator object used by Vidova MCP tools.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

Export `vidovaMouseIndicatorSettingsSchema` from the desktop Zod sources.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `enabled` | boolean | no | — | — | — |
| `position` | object | no | — | — | Mouse indicator anchor grid position. Use -1, 0, or 1 for x/y. |
| `position.x` | number | yes | min -1; max 1 | — | — |
| `position.y` | number | yes | min -1; max 1 | — | — |
| `size` | number | no | min 40; max 180 | — | Mouse indicator size in px. |
| `opacity` | number | no | min 0; max 1 | — | — |
| `style` | enum("minimal", "dark", "light", "colored") | no | — | — | — |
| `highlightColor` | string | no | pattern `^#[0-9a-fA-F]{6}$` | — | — |
| `minActiveDuration` | number | no | min 0.02; max 0.5 | — | Minimum button/wheel highlight duration in seconds. |
| `globalPosition` | boolean | no | — | — | True anchors the mouse indicator to the scene instead of the clip. |

---
URL: https://vidova.ai/docs/mcp/schemas/normalized-vector.md

# normalizedVector schema

Field specification for the normalizedVector object used by Vidova MCP tools.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

Export `normalizedVectorSchema` from the desktop Zod sources.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `x` | number | yes | min -1; max 1 | — | — |
| `y` | number | yes | min -1; max 1 | — | — |

---
URL: https://vidova.ai/docs/mcp/schemas/perspective.md

# perspective schema

Field specification for the perspective object used by Vidova MCP tools.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

Export `perspectiveObjectSchema` from the desktop Zod sources.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `enabled` | boolean | yes | — | — | — |
| `rotateX` | number | yes | min -1.2; max 1.2 | — | — |
| `rotateY` | number | yes | min -1.2; max 1.2 | — | — |
| `rotateZ` | number | yes | min -3.14; max 3.14 | — | — |
| `perspective` | number | yes | min 0.1; max 4 | — | — |
| `depthShading` | number | yes | min 0; max 0.6 | — | — |
| `rim` | number | yes | min 0; max 1 | — | — |
| `sheen` | number | yes | min 0; max 1 | — | — |
| `depthBlur` | number | yes | min 0; max 10 | — | — |
| `shadow` | number | yes | min 0; max 0.6 | — | — |
| `debugGrid` | boolean | yes | — | — | — |

---
URL: https://vidova.ai/docs/mcp/schemas/set-scene-config.md

# setSceneConfig schema

Field specification for the setSceneConfig object used by Vidova MCP tools.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

Export `setSceneConfigSchema` from the desktop Zod sources.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `width` | integer | no | min 320; max 9007199254740991 | — | Output width in pixels (min 320) |
| `height` | integer | no | min 240; max 9007199254740991 | — | Output height in pixels (min 240) |
| `fps` | integer | no | min 1; max 240 | — | Frames per second (1–240). Common: 24, 30, 60. |
| `background` | string | no | minLength 1 | — | Background color, gradient, or CSS value |
| `backgroundImage` | object \\| null | no | — | — | Wallpaper asset and dimensions. Pass null to clear the wallpaper. |
| `name` | string | no | minLength 1; maxLength 180 | — | Project name |
| `captionSettings` | object | no | strict | — | Project caption defaults; merges with current/default settings. |
| `captionSettings.enabled` | boolean | no | — | — | — |
| `captionSettings.fontFamily` | string | no | — | — | — |
| `captionSettings.fontWeight` | 400 \\| 500 \\| 700 | no | — | — | — |
| `captionSettings.fontSize` | number | no | — | — | — |
| `captionSettings.distanceFromBottom` | number | no | — | — | — |
| `captionSettings.style` | enum("pill", "karaoke-lime", "karaoke-magenta", "karaoke-cyan", "outlined", "bold-outline", "minimal", "word-highlight", "pink-pill", "dark-pill-lime", "cloud-blob", "amber-tape", "studio") | no | — | — | — |
| `captionSettings.textColor` | string | no | — | — | — |
| `captionSettings.highlightColor` | string | no | — | — | — |
| `captionSettings.backgroundColor` | string | no | — | — | — |
| `captionSettings.shadowColor` | string | no | — | — | — |
| `captionSettings.shadowBlur` | number | no | — | — | — |
| `captionSettings.maxCharsPerLine` | number | no | — | — | — |
| `textClipSettings` | object | no | strict | — | Defaults for newly created text clips; merges with current/default settings. |
| `textClipSettings.fontFamily` | string | no | — | — | — |
| `textClipSettings.fontWeight` | 400 \\| 500 \\| 700 | no | — | — | — |
| `textClipSettings.defaultFontSize` | number | no | — | — | — |
| `textClipSettings.defaultFill` | string | no | — | — | — |
| `styleState` | object | no | strict | — | Complete project style plus override keys. The style is applied to existing Vidova clips. |
| `styleState.style` | object | yes | strict | — | — |
| `styleState.style.id` | enum("launch", "demo-day", "tutorial", "social-cut", "deep-dive", "sales-demo", "parallax", "sunset", "pop", "terminal", "course", "mobile", "webinar", "mono", "plain") | yes | — | — | — |
| `styleState.style.background` | string | yes | minLength 1 | — | — |
| `styleState.style.padding` | number | yes | min 0; max 400 | — | — |
| `styleState.style.cornerRadius` | number | yes | min 0; max 200 | — | — |
| `styleState.style.shadowStrength` | number | yes | min 0; max 100 | — | — |
| `styleState.style.zoomIntensity` | 0 \\| 1 \\| 2 \\| 3 \\| 4 \\| 5 | yes | — | — | — |
| `styleState.style.zoomFeel` | enum("soft-spring", "snappy-spring", "soft-landing", "fast-settle", "gentle-curve") | no | — | "soft-spring" | — |
| `styleState.style.zoom3D` | boolean | no | — | false | — |
| `styleState.style.cursorStyle` | enum("default", "cartoon", "modern", "original", "banana", "capitaine-dark", "capitaine-light", "touch", "tahoe", "whitesur", "bibata", "bibata-original") | no | — | "default" | — |
| `styleState.style.cursorSize` | number | no | min 24; max 200 | 64 | — |
| `styleState.style.cursorSpotlight` | boolean | no | — | false | — |
| `styleState.style.cameraShape` | enum("default", "squircle", "circle") | yes | — | — | — |
| `styleState.style.cameraSize` | number | yes | min 0; max 1 | — | — |
| `styleState.style.showShortcuts` | boolean | yes | — | — | — |
| `styleState.style.captionsEnabled` | boolean | yes | — | — | — |
| `styleState.style.captionStyle` | enum("pill", "karaoke-lime", "karaoke-magenta", "karaoke-cyan", "outlined", "bold-outline", "minimal", "word-highlight", "pink-pill", "dark-pill-lime", "cloud-blob", "amber-tape", "studio") | yes | — | — | — |
| `styleState.style.captionFontSize` | number | yes | min 8; max 200 | — | — |
| `styleState.overrides` | enum("background", "padding", "cornerRadius", "shadowStrength", "zoomIntensity", "zoomFeel", "zoom3D", "cursor", "cameraShape", "cameraSize", "showShortcuts", "captions")[] | yes | — | — | — |

---
URL: https://vidova.ai/docs/mcp/schemas/vector.md

# vector schema

Field specification for the vector object used by Vidova MCP tools.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

Export `vectorSchema` from the desktop Zod sources.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `x` | number | yes | — | — | — |
| `y` | number | yes | — | — | — |

---
URL: https://vidova.ai/docs/mcp/schemas/vidova-camera.md

# vidovaSettings.camera schema

Field specification for the vidovaSettings.camera object used by Vidova MCP tools.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

Export `vidovaCameraSettingsSchema` from the desktop Zod sources.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `size` | number | no | min 5; max 70 | — | — |
| `sizeDuringZoom` | number | no | min 5; max 100 | — | — |
| `roundedness` | number | no | min 0; max 100 | — | — |
| `shape` | enum("default", "squircle", "circle") | no | — | — | — |
| `hideCamera` | boolean | no | — | — | False shows the camera overlay. |
| `mirrorCamera` | boolean | no | — | — | — |
| `removeBackground` | boolean | no | — | — | True composites the baked person mask. The mask must already exist on the camera asset. |
| `position` | object | no | — | — | Camera anchor grid position. Use -1, 0, or 1 for x/y. |
| `position.x` | number | yes | min -1; max 1 | — | — |
| `position.y` | number | yes | min -1; max 1 | — | — |
| `alignment` | object | no | — | — | Crop alignment inside squircle/circle camera shapes. |
| `alignment.x` | number | yes | min -1; max 1 | — | — |
| `alignment.y` | number | yes | min -1; max 1 | — | — |
| `differentSizeDuringZoom` | boolean | no | — | — | — |
| `verticalPadding` | number | no | min 0; max 100 | — | — |
| `globalPosition` | boolean | no | — | — | True anchors the camera to the scene instead of the clip. |

---
URL: https://vidova.ai/docs/mcp/schemas/vidova-crop.md

# vidovaSettings.crop schema

Field specification for the vidovaSettings.crop object used by Vidova MCP tools.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

Export `vidovaCropSettingsSchema` from the desktop Zod sources.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `Top` | number | no | min 0; max 1 | — | — |
| `Bottom` | number | no | min 0; max 1 | — | — |
| `Left` | number | no | min 0; max 1 | — | — |
| `Right` | number | no | min 0; max 1 | — | — |

---
URL: https://vidova.ai/docs/mcp/schemas/vidova-settings.md

# vidovaSettings schema

Field specification for the vidovaSettings object used by Vidova MCP tools.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

Export `vidovaSettingsSchema` from the desktop Zod sources.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `layout` | enum("screen-and-cam", "screen-only", "cam-only", "half-half") | no | — | — | — |
| `crop` | object | no | — | — | Normalized crop edges for the screen recording: Left/Top/Right/Bottom in the 0..1 range. |
| `crop.Top` | number | no | min 0; max 1 | — | — |
| `crop.Bottom` | number | no | min 0; max 1 | — | — |
| `crop.Left` | number | no | min 0; max 1 | — | — |
| `crop.Right` | number | no | min 0; max 1 | — | — |
| `zoomLayerId` | string | no | — | — | Use a zoom layer ID from timeline_get_state. Pass an empty string to clear. |
| `blurLayerId` | string | no | — | — | Use an overlay/blur layer ID from timeline_get_state. Pass an empty string to clear. |
| `roundedness` | number | no | min 0; max 50 | — | — |
| `padding` | number | no | min 0; max 100 | — | — |
| `screenAudioVolume` | number | no | min 0; max 1 | — | — |
| `cameraAudioVolume` | number | no | min 0; max 1 | — | — |
| `muteScreenAudio` | boolean | no | — | — | — |
| `muteCameraAudio` | boolean | no | — | — | — |
| `zoomAnimationStyle` | enum("soft-spring", "snappy-spring", "soft-landing", "fast-settle", "gentle-curve") | no | — | — | Zoom feel: soft-spring (default), snappy-spring, soft-landing, fast-settle, gentle-curve. |
| `panAnimationStyle` | enum("heavy-camera", "quick-follow", "soft-lag") | no | — | — | Pan feel: heavy-camera (default), quick-follow, soft-lag. |
| `linkedZoomTransitionDuration` | number | no | min 0; max 2 | — | — |
| `useAutoLinkedZoomTransitionDuration` | boolean | no | — | — | Set true to clear the manual linked zoom handoff duration. |
| `trackingIntensity` | integer | no | min 0; max 5 | — | — |
| `trackingStyle` | enum("steadicam", "director", "anchor", "momentum") | no | — | — | Camera-path solver for cursor-following zooms: steadicam, director, anchor, or momentum. |
| `clickFollow` | object | no | strict | — | Keep out-of-view clicks in frame and near centre. Clicks already in view stay put. enabled (default true), tight 0.05-0.45 (default 0.35), zoom 1-6 (steadicam click-punch cap, default 3.5), window 0.2-1.6s (default 0.8), lead 0-0.8s (default 0.38), margin 0.35-1 (steadicam hold slack, default 0.85). Partial objects merge with the clip current values. |
| `clickFollow.enabled` | boolean | no | — | — | — |
| `clickFollow.tight` | number | no | min 0.05; max 0.45 | — | — |
| `clickFollow.window` | number | no | min 0.2; max 1.6 | — | — |
| `clickFollow.lead` | number | no | min 0; max 0.8 | — | — |
| `clickFollow.zoom` | number | no | min 1; max 6 | — | — |
| `clickFollow.margin` | number | no | min 0.35; max 1 | — | — |
| `motionBlurStrength` | number | no | min 0; max 2 | — | — |
| `cursorHidden` | boolean | no | — | — | False shows the cursor. |
| `cursorStyle` | enum("default", "cartoon", "modern", "original", "banana", "capitaine-dark", "capitaine-light", "touch", "tahoe", "whitesur", "bibata", "bibata-original") | no | — | — | — |
| `cursorSize` | number | no | min 16; max 256 | — | — |
| `smoothCursorChanges` | boolean | no | — | — | — |
| `hideCursorWhenStill` | boolean | no | — | — | — |
| `enableCursorMotionBlur` | boolean | no | — | — | — |
| `cursorMotionBlurStrength` | number | no | min 0; max 2 | — | — |
| `enableCursorTilting` | boolean | no | — | — | — |
| `returnToOriginalPosition` | boolean | no | — | — | — |
| `cursorSmoothingStyle` | enum("original", "steady", "soft", "fluid", "glide") | no | — | — | Cursor path: original, steady (default), soft, fluid, glide. |
| `pinCursorToClicks` | boolean | no | — | — | Pin the path through each click so the cursor lands on the button. |
| `cursorClickPinWindow` | number | no | min 0.04; max 0.4 | — | How long the cursor holds on each click, in seconds. Default 0.12. |
| `cursorSmoothingTime` | number | no | min 0.01; max 0.12 | — | Steady and Soft smoothness in seconds. Default 0.045. |
| `cursorSmoothingSpace` | number | no | min 4; max 80 | — | Steady: how strongly fast flicks are kept, in pixels. Default 18. |
| `cursorSmoothingTension` | number | no | min 40; max 400 | — | Fluid spring weight. Default 170. |
| `cursorSmoothingFriction` | number | no | min 4; max 40 | — | Fluid spring damping. Default 20. |
| `cursorSmoothingSimplify` | number | no | min 2; max 40 | — | Glide: how much jitter to drop before the curve. Default 8. |
| `clickEffectStyle` | enum("none", "default", "effect-1", "effect-2", "effect-3", "effect-4", "effect-5", "effect-6") | no | — | — | — |
| `clickEffectSize` | number | no | min 16; max 256 | — | — |
| `cursorSpotlight` | object | no | strict | — | — |
| `cursorSpotlight.enabled` | boolean | no | — | — | — |
| `cursorSpotlight.radius` | number | no | — | — | — |
| `cursorSpotlight.softness` | number | no | — | — | — |
| `cursorSpotlight.dimOpacity` | number | no | — | — | — |
| `cursorSpotlight.onlyOnClick` | boolean | no | — | — | — |
| `cursorSpotlight.clickWindow` | number | no | min 0.05; max 4 | — | — |
| `camera` | object | no | — | — | — |
| `camera.size` | number | no | min 5; max 70 | — | — |
| `camera.sizeDuringZoom` | number | no | min 5; max 100 | — | — |
| `camera.roundedness` | number | no | min 0; max 100 | — | — |
| `camera.shape` | enum("default", "squircle", "circle") | no | — | — | — |
| `camera.hideCamera` | boolean | no | — | — | False shows the camera overlay. |
| `camera.mirrorCamera` | boolean | no | — | — | — |
| `camera.removeBackground` | boolean | no | — | — | True composites the baked person mask. The mask must already exist on the camera asset. |
| `camera.position` | object | no | — | — | Camera anchor grid position. Use -1, 0, or 1 for x/y. |
| `camera.position.x` | number | yes | min -1; max 1 | — | — |
| `camera.position.y` | number | yes | min -1; max 1 | — | — |
| `camera.alignment` | object | no | — | — | Crop alignment inside squircle/circle camera shapes. |
| `camera.alignment.x` | number | yes | min -1; max 1 | — | — |
| `camera.alignment.y` | number | yes | min -1; max 1 | — | — |
| `camera.differentSizeDuringZoom` | boolean | no | — | — | — |
| `camera.verticalPadding` | number | no | min 0; max 100 | — | — |
| `camera.globalPosition` | boolean | no | — | — | True anchors the camera to the scene instead of the clip. |
| `mouseIndicator` | object | no | — | — | — |
| `mouseIndicator.enabled` | boolean | no | — | — | — |
| `mouseIndicator.position` | object | no | — | — | Mouse indicator anchor grid position. Use -1, 0, or 1 for x/y. |
| `mouseIndicator.position.x` | number | yes | min -1; max 1 | — | — |
| `mouseIndicator.position.y` | number | yes | min -1; max 1 | — | — |
| `mouseIndicator.size` | number | no | min 40; max 180 | — | Mouse indicator size in px. |
| `mouseIndicator.opacity` | number | no | min 0; max 1 | — | — |
| `mouseIndicator.style` | enum("minimal", "dark", "light", "colored") | no | — | — | — |
| `mouseIndicator.highlightColor` | string | no | pattern `^#[0-9a-fA-F]{6}$` | — | — |
| `mouseIndicator.minActiveDuration` | number | no | min 0.02; max 0.5 | — | Minimum button/wheel highlight duration in seconds. |
| `mouseIndicator.globalPosition` | boolean | no | — | — | True anchors the mouse indicator to the scene instead of the clip. |
| `quality` | number | no | min 0 | — | Motion-blur shader sample quality. 0 disables sampled motion blur. |
| `sharpenFactor` | number | no | min 0; max 5 | — | — |
| `shadowStrength` | number | no | min 0; max 100 | — | — |
| `inset` | number | no | min 0; max 50 | — | — |
| `isVertical` | boolean | no | — | — | — |
| `showShortcuts` | boolean | no | — | — | — |
| `shortcutsSize` | number | no | min 1; max 300 | — | — |
| `shortcutsDuration` | number | no | min 0.5; max 5 | — | — |
| `captionSettings` | object | no | strict | — | — |
| `captionSettings.enabled` | boolean | no | — | — | — |
| `captionSettings.fontFamily` | string | no | — | — | — |
| `captionSettings.fontWeight` | 400 \\| 500 \\| 700 | no | — | — | — |
| `captionSettings.fontSize` | number | no | — | — | — |
| `captionSettings.distanceFromBottom` | number | no | — | — | — |
| `captionSettings.style` | enum("pill", "karaoke-lime", "karaoke-magenta", "karaoke-cyan", "outlined", "bold-outline", "minimal", "word-highlight", "pink-pill", "dark-pill-lime", "cloud-blob", "amber-tape", "studio") | no | — | — | — |
| `captionSettings.textColor` | string | no | — | — | — |
| `captionSettings.highlightColor` | string | no | — | — | — |
| `captionSettings.backgroundColor` | string | no | — | — | — |
| `captionSettings.shadowColor` | string | no | — | — | — |
| `captionSettings.shadowBlur` | number | no | — | — | — |
| `captionSettings.maxCharsPerLine` | number | no | — | — | — |

---
URL: https://vidova.ai/docs/mcp/schemas/zoom-depth.md

# zoomDepth schema

Field specification for the zoomDepth object used by Vidova MCP tools.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

Export `zoomDepthInputSchema` from the desktop Zod sources.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `enabled` | boolean | no | — | — | — |
| `intensity` | number | no | min 0; max 2 | — | — |
| `focalLength` | number | no | min 24; max 120 | — | — |
| `tiltX` | number | no | min -0.35; max 0.35 | — | — |
| `tiltY` | number | no | min -0.35; max 0.35 | — | — |
| `roll` | number | no | min -0.35; max 0.35 | — | — |
| `dolly` | number | no | min -0.35; max 0.35 | — | — |
| `glideTiltX` | number | no | min -0.35; max 0.35 | — | — |
| `glideTiltY` | number | no | min -0.35; max 0.35 | — | — |
| `glideRoll` | number | no | min -0.35; max 0.35 | — | — |
| `glideDolly` | number | no | min -0.35; max 0.35 | — | — |
| `anchorInfluence` | number | no | min 0; max 1 | — | — |
| `depthShading` | number | no | min 0; max 0.6 | — | — |
| `rim` | number | no | min 0; max 0.5 | — | — |
| `sheen` | number | no | min 0; max 0.6 | — | — |
| `depthBlur` | number | no | min 0; max 10 | — | — |
| `shadow` | number | no | min 0; max 0.6 | — | — |

---
URL: https://vidova.ai/docs/mcp/schemas/zoom-segment.md

# zoomSegment schema

Field specification for the zoomSegment object used by Vidova MCP tools.

{/* Generated by landing/scripts/generate-mcp-docs.ts. Do not edit. */}

Export `zoomSegmentSchema` from the desktop Zod sources.

| Field | Type | Required | Constraints | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `start` | number | yes | min 0 | — | Zoom start time in seconds, relative to the vidova clip start |
| `duration` | number | yes | exclusiveMin 0 | — | Zoom duration in seconds |
| `factor` | number | no | min 1; max 10 | 1.5 | Zoom magnification (1 = no zoom, 1.5 = 1.5x, 2 = 2x, etc.) |
| `anchorX` | number | no | min -1; max 1 | — | Horizontal anchor -1 to 1 (manual zoom only) |
| `anchorY` | number | no | min -1; max 1 | — | Vertical anchor -1 to 1 (manual zoom only) |
| `zoomEffectType` | enum("tracking", "manual") | no | — | — | 'tracking' follows the cursor (default), 'manual' zooms to a fixed anchor |
| `trackType` | enum("cinematic", "centered") | no | — | — | 'cinematic' = smooth follow, 'centered' = lock to cursor |
| `name` | string | no | — | — | Label for this zoom region |
| `depth` | object | no | strict | — | Optional 3D zoom settings. Set enabled:true to re-project the frame onto a tilted plane with real perspective instead of a flat scale. Angles (tiltX/tiltY/roll and their glide* counterparts) are in RADIANS, range -0.35 to 0.35. focalLength is 24-120mm: short exaggerates depth, long flattens it. The zoom eases into the tilt/roll/dolly pose, glides to the glide* pose while held, then eases flat. Omitted fields keep their defaults. |
| `depth.enabled` | boolean | no | — | — | — |
| `depth.intensity` | number | no | min 0; max 2 | — | — |
| `depth.focalLength` | number | no | min 24; max 120 | — | — |
| `depth.tiltX` | number | no | min -0.35; max 0.35 | — | — |
| `depth.tiltY` | number | no | min -0.35; max 0.35 | — | — |
| `depth.roll` | number | no | min -0.35; max 0.35 | — | — |
| `depth.dolly` | number | no | min -0.35; max 0.35 | — | — |
| `depth.glideTiltX` | number | no | min -0.35; max 0.35 | — | — |
| `depth.glideTiltY` | number | no | min -0.35; max 0.35 | — | — |
| `depth.glideRoll` | number | no | min -0.35; max 0.35 | — | — |
| `depth.glideDolly` | number | no | min -0.35; max 0.35 | — | — |
| `depth.anchorInfluence` | number | no | min 0; max 1 | — | — |
| `depth.depthShading` | number | no | min 0; max 0.6 | — | — |
| `depth.rim` | number | no | min 0; max 0.5 | — | — |
| `depth.sheen` | number | no | min 0; max 0.6 | — | — |
| `depth.depthBlur` | number | no | min 0; max 10 | — | — |
| `depth.shadow` | number | no | min 0; max 0.6 | — | — |

---
URL: https://vidova.ai/docs/mcp/patterns.md

# Vidova MCP patterns

Preview-and-iterate, silence removal, zooms, vidovaSettings cursor, components, hosted image and speech polling, and recipe search.

## Preview-and-iterate

After a visible timeline or component change, call `preview` `captureFrame` before you report success. For motion, use `preview` `timeline` for timestamped contact sheets. A render error means the composition did not draw. Fix the cause. Do not trust an earlier frame.

## Silence removal

1. `asset` `transcribe` with the recording `assetId`.
2. `sleep` between polls.
3. `generate_asset` `kind` `status` with the `jobId`.
4. `asset` `captions` when the job completes.
5. `timeline_edit` `removeSilences` with **only** `assetId`.

Do not invent silence timestamps. `removeSilences` reads the transcript itself. Spec: [timeline_edit](/docs/mcp/tools/timeline_edit).

## Zooms

Screen-recording zooms live on a zoom layer. Use `clip_enhance` `addZoom`, or `manageZooms` with `zoomAction` `list` / `add` / `update` / `delete`. Factor `1` is no zoom. `zoomEffectType` `tracking` follows the cursor. `manual` uses a fixed anchor from -1 to 1.

Do not use camera clips for cursor zooms.

## Cursor, camera, layout

Patch `vidovaSettings` on `timeline_edit` `updateClip`. Example: `cursorStyle: "banana"`. Schema: [vidovaSettings](/docs/mcp/schemas/vidova-settings). Do not call `vidova_set_cursor`.

## Components

Prefer `component` `createFromTemplate` with `templateId` and `inputOverrides`. Then `timeline_edit` `addClip` with `type` `component` and the returned `assetId`. Never `type=text`.

If create or edit reports `FAILED TO RENDER`, fix the component before placing it.

Asset inputs: pass the asset ID in `componentInputs`. The clip stores IDs; the class receives a playback URL (or `VidovaClipData`). Use `@initial('')` on image/video signals. Do not add a parallel image clip for an asset the component already takes as an input. [Inputs](/docs/custom-elements/inputs).

Shaders are SkSL on a cached node, not GLSL. Include `@vidova/core/shaders/common.sksl` or use `withCommonShader()`. [Shaders](/docs/custom-elements/shaders).

Authoring a class from scratch: [Custom elements](/docs/custom-elements).

## Hosted image and speech

`generate_asset` `kind` `image` or `speech` returns a `jobId`. Poll `kind` `status`. Use `sleep` between polls. `kind` `music` and `kind` `video` are advertised and not reachable. See [Not in MCP](/docs/mcp/not-in-mcp).

## Recipes

In Agent Mode, search recipes before a substantive task. If search fails because embeddings are warming up, continue the user task. Do not retry until search is ready. Skip search for tiny chat or when the user says not to.

---
URL: https://vidova.ai/docs/mcp/use-cases.md

# Vidova MCP use cases

Product jobs for Vidova Local MCP: clean a screen recording, restyle a cursor, add zooms, place a title, and generate a still.

## Clean a talking-head screen recording

Transcribe the recording, wait for captions, then `removeSilences` with the asset id. Preview a still. Undo with `project_history` if a pause you wanted is gone.

## Restyle a tutorial cursor

Read `timeline_get_state`. Find the `vidova` clip. `updateClip` with `vidovaSettings.cursorStyle` (including `banana`) and `cursorSize`. Capture a frame where the pointer is on a button.

## Follow clicks with zooms

`clip_enhance` `addZoom` on that Vidova clip. Use tracking zooms for cursor follow. Keep camera clips for whole-composition moves only.

## Add a title without `type=text`

`component` `createFromTemplate` with `templateId` `typewriter` and `inputOverrides.fullText`. Place with `addClip` `type` `component`. Preview immediately and check clipping and text fit.

## Generate a still, then place it

`generate_asset` `kind` `image`, poll `status`, then `timeline_edit` `addClip` `type` `image` with the new `assetId`. Image generation uses the image-generation allowance.

## Switch projects from the agent

`list_projects`, `set_active_project`, open the editor if it is not already the active window, then `timeline_get_state`.

---
URL: https://vidova.ai/docs/mcp/dos-and-donts.md

# Vidova MCP dos and don'ts

Hard rules for Vidova Local MCP from editor skills and tests. Read timeline state before ids. Never invent silence timestamps. Never use type=text.

## Do

- Call `timeline_get_state` before you use clip or layer ids.
- Use `preview` after visible edits.
- Place typography as `type=component` after `createFromTemplate` or `create`.
- Pass `removeSilences` only `assetId`.
- Treat `REJECTED` or `ERROR` as unchanged project state.
- Use camera clips for whole-composition pan, zoom, and rotation.
- Use Vidova zoom clips for cursor zooms on screen recordings.
- Remember scene position is center origin. Preview crop rectangles are top-left origin in scene pixels.

## Do not

- Invent silence timestamps or call `removeTimeRanges` to fake silence removal.
- Use `type=text`.
- Place a component that failed to render.
- Work around a rejection by resizing other clips unless the user asked.
- Hide a clip by shrinking duration. Use `deleteClip`.
- Use camera clips for screen-recording cursor zooms.
- Call `web_research`, `vidova_set_cursor`, `detectBeatGrid`, or other [retired names](/docs/mcp/not-in-mcp).
- Call `generate_asset` `kind` `music` or `video`. They are advertised and not wired.
- Claim completion from tool success alone.

## Coordinates

Vidova scene positions use a center origin. X increases to the right. Y increases downward. Preview `crop` uses top-left origin in scene pixels. Convert before you copy a crop into `position.x` / `position.y`.

---
URL: https://vidova.ai/docs/mcp/quotas.md

# Vidova MCP quotas

Local Vidova MCP tools do not use hosted quota. generate_asset image is metered. Speech and transcription use included rolling quotas.

Local editor operations do not use Vidova hosted quota. The intelligence that decided to call the tool is the connected agent, not a Vidova hosted model.

## Local

`timeline_edit`, `preview`, `clip_enhance`, project tools, components, branches, recipes, and the other non-metered tools are local. See each tool page for the credit sentence from `mcpToolCreditNotice`.

## Metered or included hosted jobs

| Call | What it uses |
| --- | --- |
| `generate_asset` `kind` `image` | Image-generation allowance |
| `generate_asset` `kind` `speech` | Included speech quota (characters) |
| `asset` `transcribe` | Included transcription quota (started minutes) |
| `sfx` search / import | Local search against the sound library. Import stores a file in the project. |
| `import_asset` `vectorize` | Hosted vectorize. Requires sign-in. |

`generate_asset` `kind` `status` only polls. It does not start a new billed job.

Plan numbers and rolling windows for speech, captions, and chapters are on the public [Quota usage](/quotas) page. Local editing stays unlimited.

---
URL: https://vidova.ai/docs/mcp/not-in-mcp.md

# Tools not in Vidova MCP

Retired and advertised-but-unreachable names. Do not call web_research, vidova_set_cursor, or generate_asset kinds music and video.

Agents invent tools that used to exist in the in-app agent, or that MCP still lists but the renderer does not run. This page is the stop list.

## Advertised, not reachable

[generate_asset](/docs/mcp/tools/generate_asset) advertises `kind` values `music` and `video`. The renderer only wires `image`, `speech`, and `status`. Those music and video calls fail.

## Never an MCP tool

`vidova_set_cursor` is not published. Set the cursor with `timeline_edit` `updateClip` and `vidovaSettings.cursorStyle`.

`type=text` is not a supported way to add titles. Use `component` then `addClip` `type` `component`.

## Retired renderer tools

These remain in source with `retired: true`. MCP `listTools` omits them. `executeTool` treats them as absent.

- `indexVideoAsset` / `searchVideoAsset`
- `analyzeAsset`
- `detectObjects`
- `locateInPreview`
- `understandVideoMoment`
- `analyzeVideo`
- `trackObjects`
- `backgroundJob`
- `mediaEffect`
- `webResearch` (do not call `web_research`)
- `detectBeatGrid` (do not invent beat times to pass `snapTo`)
- `loadSkill` / `manageSkill`

Skills text may still mention a retired name. The MCP catalog wins. If a skill says `manageSkill` or `detectBeatGrid`, skip it.

## Published catalog

The only local MCP names are listed in [Tools](/docs/mcp/tools). If a name is not on that page, do not call it.

