Morpha
REMOTE · MORPHAREELS.AI · SCANNED SEP 21
AI editor to build, animate & export layered short-form video projects via one tool catalog.
Available components
How this component scores in each security and reliability category. Every signal is checked automatically against the live server, and we only credit what we can confirm. How we score → Why this is hard to score →
Endpoint Security97
- The endpoint's TLS certificate is valid, in date, and uses a strong key. View diagnostics → Pass
- Authorisation is enforced on tool calls, advertised via RFC 9728 protected-resource metadata. Discovery is public, which costs nothing: no tool can be invoked without a token. View diagnostics → Pass
- HTTPS is enforced; there's no plaintext access path. View diagnostics → Pass
- The HSTS (Strict-Transport-Security) header is present. View diagnostics → Pass
- DNSSEC check failed: this domain isn't protected by DNSSEC. See how to fix → View diagnostics → Fail
- The authorisation server supports Client ID Metadata Documents, the current MCP client-registration mechanism. View diagnostics → Pass
Transport & Reachability100
- Verified streamable-http transport via a live MCP handshake. View diagnostics → Pass
Schema Quality & AI Usability64
- AI-judged instruction clarity (excellent).Pass
- Context-footprint check failed: tool/resource definitions use about 24965 tokens (~254/item across 98 items; 98 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
- Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management45
- Stability check failed: schema churn in the 14 days we've observed: 2 tool removals, 0 breaking changes, 0 auth/transport breaks, 5 additions. See how to fix → Fail
Tool Coverage97
- 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
- 91% of tool parameters carry a description.Partial
- Structured output schemas are declared (100% of tools); any adoption earns full credit.Pass
Tool Safety100
- No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
- All 11 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation.Pass
- An AI judge read all 99 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
- Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.Pass
How do I install the Morpha MCP server?
Morpha is a hosted endpoint at https://morphareels.ai/mcp, so there is nothing to install locally. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.
remote · morphareels.ai
claude mcp add --transport http ai-morphareels-morpha 'https://morphareels.ai/mcp'
{
"mcpServers": {
"ai-morphareels-morpha": {
"url": "https://morphareels.ai/mcp"
}
}
} {
"servers": {
"ai-morphareels-morpha": {
"type": "http",
"url": "https://morphareels.ai/mcp"
}
}
} [mcp_servers.ai-morphareels-morpha] url = "https://morphareels.ai/mcp"
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"ai-morphareels-morpha": {
"type": "remote",
"url": "https://morphareels.ai/mcp",
"enabled": true
}
}
} openclaw mcp add ai-morphareels-morpha --url 'https://morphareels.ai/mcp' --transport streamable-http
mcp_servers:
ai-morphareels-morpha:
url: "https://morphareels.ai/mcp" {
"McpServers": {
"ai-morphareels-morpha": {
"Transport": "http",
"Url": "https://morphareels.ai/mcp"
}
}
} assistant mcp add ai-morphareels-morpha -t streamable-http -u 'https://morphareels.ai/mcp'
{
"mcpServers": {
"ai-morphareels-morpha": {
"type": "http",
"url": "https://morphareels.ai/mcp"
}
}
} The mcpServers block is a cross-client convention. Remote transports vary, so check your client's docs.
Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.
- 20 Sept 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 38 to 41.
- 19 Sept 26 0
- Server version: 1.0.372 → 1.0.373 functional
- 18 Sept 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 31 to 35.
- 17 Sept 26 +4
- Tool “create_anonymous_account” was removed ▼ security
- The server rewrote its instructions, which are the text every model session reads security
- Tool “add_audio_overlay” rewrote its description, which is the text the model reads security
- Tool “add_image_layer” rewrote its description, which is the text the model reads security
- Tool “add_video_layer” rewrote its description, which is the text the model reads security
- Tool “create_upload_link” rewrote its description, which is the text the model reads security
- Tool “set_custom_font” rewrote its description, which is the text the model reads security
- Tool “set_image_filename” rewrote its description, which is the text the model reads security
- Tool “set_video_clip” rewrote its description, which is the text the model reads security
- Tool “upload_audio” rewrote its description, which is the text the model reads security
- Tool “upload_image” rewrote its description, which is the text the model reads security
- “create_upload_link” added a required parameter “name”, so existing callers break ▼ functional
- “create_upload_link” dropped the required parameter “filename” ▼ functional
- “add_audio_overlay” dropped the required parameter “anonymousToken” ▼ functional
- “add_caption_track” dropped the required parameter “anonymousToken” ▼ functional
- “add_color_keyframe” dropped the required parameter “anonymousToken” ▼ functional
- “add_curve” dropped the required parameter “anonymousToken” ▼ functional
- “add_embed_origin” dropped the required parameter “anonymousToken” ▼ functional
- “add_from_collection” dropped the required parameter “anonymousToken” ▼ functional
- “add_image_layer” dropped the required parameter “anonymousToken” ▼ functional
- “add_keyframe” dropped the required parameter “anonymousToken” ▼ functional
- “add_keyframes” dropped the required parameter “anonymousToken” ▼ functional
- “add_morpha_layer” dropped the required parameter “anonymousToken” ▼ functional
- “add_page” dropped the required parameter “anonymousToken” ▼ functional
- “add_shape” dropped the required parameter “anonymousToken” ▼ functional
- “add_speed_keyframe” dropped the required parameter “anonymousToken” ▼ functional
- “add_text_layer” dropped the required parameter “anonymousToken” ▼ functional
- “add_to_collection” dropped the required parameter “anonymousToken” ▼ functional
- “add_video_layer” dropped the required parameter “anonymousToken” ▼ functional
- “apply_preset” dropped the required parameter “anonymousToken” ▼ functional
- “apply_preset_stagger” dropped the required parameter “anonymousToken” ▼ functional
- “clip_processing_status” dropped the required parameter “anonymousToken” ▼ functional
- “create_project” dropped the required parameter “anonymousToken” ▼ functional
- “create_upload_link” dropped the required parameter “anonymousToken” ▼ functional
- “create_workspace” dropped the required parameter “anonymousToken” ▼ functional
- “cut_range” dropped the required parameter “anonymousToken” ▼ functional
- “delete_page” dropped the required parameter “anonymousToken” ▼ functional
- “delete_project” dropped the required parameter “anonymousToken” ▼ functional
- “delete_version” dropped the required parameter “anonymousToken” ▼ functional
- “describe_video” dropped the required parameter “anonymousToken” ▼ functional
- “detect_text_regions” dropped the required parameter “anonymousToken” ▼ functional
- “duplicate_layer” dropped the required parameter “anonymousToken” ▼ functional
- “duplicate_project” dropped the required parameter “anonymousToken” ▼ functional
- “fade_layer” dropped the required parameter “anonymousToken” ▼ functional
- “fit_duration_to_content” dropped the required parameter “anonymousToken” ▼ functional
- “freeze_frame” dropped the required parameter “anonymousToken” ▼ functional
- “group_layers” dropped the required parameter “anonymousToken” ▼ functional
- “inspect_layers” dropped the required parameter “anonymousToken” ▼ functional
- “list_collection” dropped the required parameter “anonymousToken” ▼ functional
- “list_fonts” dropped the required parameter “anonymousToken” ▼ functional
- “list_projects” dropped the required parameter “anonymousToken” ▼ functional
- “list_versions” dropped the required parameter “anonymousToken” ▼ functional
- “list_workspaces” dropped the required parameter “anonymousToken” ▼ functional
- “merge_caption_lines” dropped the required parameter “anonymousToken” ▼ functional
- “move_band” dropped the required parameter “anonymousToken” ▼ functional
- “move_layer” dropped the required parameter “anonymousToken” ▼ functional
- “move_project_to_workspace” dropped the required parameter “anonymousToken” ▼ functional
- “open_project” dropped the required parameter “anonymousToken” ▼ functional
- “reid_project” dropped the required parameter “anonymousToken” ▼ functional
- “remove_audio_overlay” dropped the required parameter “anonymousToken” ▼ functional
- “remove_color_keyframe” dropped the required parameter “anonymousToken” ▼ functional
- “remove_embed_origin” dropped the required parameter “anonymousToken” ▼ functional
- “remove_from_collection” dropped the required parameter “anonymousToken” ▼ functional
- “remove_keyframe” dropped the required parameter “anonymousToken” ▼ functional
- “remove_layer” dropped the required parameter “anonymousToken” ▼ functional
- “remove_speed_keyframe” dropped the required parameter “anonymousToken” ▼ functional
- “rename_group” dropped the required parameter “anonymousToken” ▼ functional
- “rename_layer” dropped the required parameter “anonymousToken” ▼ functional
- “rename_project” dropped the required parameter “anonymousToken” ▼ functional
- “rename_version” dropped the required parameter “anonymousToken” ▼ functional
- “rename_workspace” dropped the required parameter “anonymousToken” ▼ functional
- “render_status” dropped the required parameter “anonymousToken” ▼ functional
- “render_video” dropped the required parameter “anonymousToken” ▼ functional
- “reorder_layer” dropped the required parameter “anonymousToken” ▼ functional
- “reorder_pages” dropped the required parameter “anonymousToken” ▼ functional
- “restore_version” dropped the required parameter “anonymousToken” ▼ functional
- “safe_zones” dropped the required parameter “anonymousToken” ▼ functional
- “save_version” dropped the required parameter “anonymousToken” ▼ functional
- “select_page” dropped the required parameter “anonymousToken” ▼ functional
- “set_canvas_size” dropped the required parameter “anonymousToken” ▼ functional
- “set_clip_speed” dropped the required parameter “anonymousToken” ▼ functional
- “set_custom_font” dropped the required parameter “anonymousToken” ▼ functional
- “set_duration” dropped the required parameter “anonymousToken” ▼ functional
- “set_embed_origins” dropped the required parameter “anonymousToken” ▼ functional
- “set_group_box” dropped the required parameter “anonymousToken” ▼ functional
- “set_group_parent” dropped the required parameter “anonymousToken” ▼ functional
- “set_group_window” dropped the required parameter “anonymousToken” ▼ functional
- “set_image_filename” dropped the required parameter “anonymousToken” ▼ functional
- “set_keyframes_batch” dropped the required parameter “anonymousToken” ▼ functional
- “set_layer_block” dropped the required parameter “anonymousToken” ▼ functional
- “set_layer_fill” dropped the required parameter “anonymousToken” ▼ functional
- “set_layer_text” dropped the required parameter “anonymousToken” ▼ functional
- “set_layer_transition” dropped the required parameter “anonymousToken” ▼ functional
- “set_layer_visible” dropped the required parameter “anonymousToken” ▼ functional
- “set_loop” dropped the required parameter “anonymousToken” ▼ functional
- “set_matte_source” dropped the required parameter “anonymousToken” ▼ functional
- “set_pivot” dropped the required parameter “anonymousToken” ▼ functional
- “set_style” dropped the required parameter “anonymousToken” ▼ functional
- “set_text_background” dropped the required parameter “anonymousToken” ▼ functional
- “set_track_loop” dropped the required parameter “anonymousToken” ▼ functional
- “set_video_clip” dropped the required parameter “anonymousToken” ▼ functional
- “set_video_layer_muted” dropped the required parameter “anonymousToken” ▼ functional
- “set_video_layer_trim” dropped the required parameter “anonymousToken” ▼ functional
- “shift_group” dropped the required parameter “anonymousToken” ▼ functional
- “shift_track” dropped the required parameter “anonymousToken” ▼ functional
- “split_caption_line” dropped the required parameter “anonymousToken” ▼ functional
- “transcribe_clip” dropped the required parameter “anonymousToken” ▼ functional
- “ungroup_layers” dropped the required parameter “anonymousToken” ▼ functional
- “update_audio_overlay” dropped the required parameter “anonymousToken” ▼ functional
- “upload_audio” dropped the required parameter “anonymousToken” ▼ functional
- “upload_image” dropped the required parameter “anonymousToken” ▼ functional
- Schema quality: 280 → 250 ▲ functional
- Server version: 1.0.371 → 1.0.372 functional
- Server version: 1.0.370 → 1.0.371 functional
- Server version: 1.0.367 → 1.0.370 functional
- Server version: 1.0.365 → 1.0.367 functional
- Server version: 1.0.364 → 1.0.365 functional
- Server version: 1.0.362 → 1.0.364 functional
- Server version: 1.0.359 → 1.0.362 functional
- “add_audio_overlay” added an optional parameter “name” cosmetic
- “add_image_layer” added an optional parameter “name” cosmetic
- “set_image_filename” added an optional parameter “name” cosmetic
- “set_video_clip” added an optional parameter “name” cosmetic
- “update_audio_overlay” added an optional parameter “name” cosmetic
- “upload_audio” added an optional parameter “name” cosmetic
- “upload_image” added an optional parameter “name” cosmetic
- “add_audio_overlay” reworded the description of “filename” cosmetic
- “add_image_layer” reworded the description of “filename” cosmetic
- “add_video_layer” reworded the description of “clip” cosmetic
- “add_video_layer” reworded the description of “name” cosmetic
- “set_image_filename” reworded the description of “filename” cosmetic
- “set_video_clip” reworded the description of “clip” cosmetic
- “update_audio_overlay” reworded the description of “filename” cosmetic
- “upload_audio” dropped the optional parameter “filename” cosmetic
- “upload_image” dropped the optional parameter “filename” cosmetic
- 16 Sept 26 0
- The server rewrote its instructions, which are the text every model session reads security
- New tool “create_upload_link”, which the server declares destructive security
- Tool “add_embed_origin” rewrote its description, which is the text the model reads security
- Tool “remove_embed_origin” rewrote its description, which is the text the model reads security
- Tool “render_video” rewrote its description, which is the text the model reads security
- Tool “set_custom_font” rewrote its description, which is the text the model reads security
- Tool “set_embed_origins” rewrote its description, which is the text the model reads security
- Tool “create_anonymous_account” rewrote its description, which is the text the model reads security
- Tool “clip_processing_status” rewrote its description, which is the text the model reads security
- Tool “set_matte_source” rewrote its description, which is the text the model reads security
- Tool “set_duration” rewrote its description, which is the text the model reads security
- Tool “upload_audio” rewrote its description, which is the text the model reads security
- Tool “upload_image” rewrote its description, which is the text the model reads security
- Tool “select_page” no longer declares itself destructive security
- Tool “add_color_keyframe” is now declared destructive security
- Tool “add_keyframe” is now declared destructive security
- Tool “add_keyframes” is now declared destructive security
- Tool “add_speed_keyframe” is now declared destructive security
- Tool “render_video” is now declared destructive security
- Tool “save_version” is now declared destructive security
- Server version: 1.0.353 → 1.0.359 functional
- Server version: 1.0.347 → 1.0.353 functional
- Server version: 1.0.346 → 1.0.347 functional
- Server version: 1.0.340 → 1.0.346 functional
- Server version: 1.0.339 → 1.0.340 functional
- Server version: 1.0.337 → 1.0.339 functional
- “set_duration” reworded the description of “seconds” cosmetic
- 15 Sept 26 0
We did not load change detail this far back for this component, so this day may have recorded more than is shown.
- Tool “add_audio_overlay” now declares an output schema ▲ functional
- Tool “add_caption_track” now declares an output schema ▲ functional
- Tool “add_color_keyframe” now declares an output schema ▲ functional
- Tool “add_curve” now declares an output schema ▲ functional
- Tool “add_embed_origin” now declares an output schema ▲ functional
- Tool “add_from_collection” now declares an output schema ▲ functional
- Tool “add_image_layer” now declares an output schema ▲ functional
- Tool “add_keyframe” now declares an output schema ▲ functional
- Tool “add_keyframes” now declares an output schema ▲ functional
- Tool “add_morpha_layer” now declares an output schema ▲ functional
- Tool “add_page” now declares an output schema ▲ functional
- Tool “add_shape” now declares an output schema ▲ functional
- Tool “add_speed_keyframe” now declares an output schema ▲ functional
- Tool “add_text_layer” now declares an output schema ▲ functional
- Tool “add_to_collection” now declares an output schema ▲ functional
- Tool “add_video_layer” now declares an output schema ▲ functional
- Tool “apply_preset” now declares an output schema ▲ functional
- Tool “apply_preset_stagger” now declares an output schema ▲ functional
- Tool “clip_processing_status” now declares an output schema ▲ functional
- Tool “create_anonymous_account” now declares an output schema ▲ functional
- Tool “create_project” now declares an output schema ▲ functional
- Tool “create_workspace” now declares an output schema ▲ functional
- Tool “cut_range” now declares an output schema ▲ functional
- Tool “delete_page” now declares an output schema ▲ functional
- Tool “delete_project” now declares an output schema ▲ functional
- Tool “delete_version” now declares an output schema ▲ functional
- Tool “describe_video” now declares an output schema ▲ functional
- Tool “detect_text_regions” now declares an output schema ▲ functional
- Tool “duplicate_layer” now declares an output schema ▲ functional
- Tool “duplicate_project” now declares an output schema ▲ functional
- First check of Tool coverage: 100 functional
- Server version: 1.0.335 → 1.0.337 functional
- Server version: 1.0.334 → 1.0.335 functional
- 11 Sept 26 −2
We did not load change detail this far back for this component, so this day may have recorded more than is shown.
- 10 Sept 26 +2
We did not load change detail this far back for this component, so this day may have recorded more than is shown.
Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.
Captured 21 Sept 2026 · Probed https://morphareels.ai/mcp
TLS valid
Negotiated TLS 1.3 with TLS_AES_128_GCM_SHA256 .
| Subject | Issuer | Valid from | Valid until | Key | Signature | Serial |
|---|---|---|---|---|---|---|
| CN=morphareels.ai | CN=WE1,O=Google Trust Services,C=US | 17 Aug 2026 | 15 Nov 2026 | ECDSA 256 | ECDSA-SHA256 | 3bf1f601a759df49133489fba5c7cc0b |
| SANs: morphareels.ai, *.morphareels.ai | ||||||
| CN=WE1,O=Google Trust Services,C=US (CA) | CN=GTS Root R4,O=Google Trust Services LLC,C=US | 13 Dec 2023 | 20 Feb 2029 | ECDSA 256 | ECDSA-SHA384 | 7ff31977972c224a76155d13b6d685e3 |
| CN=GTS Root R4,O=Google Trust Services LLC,C=US (CA) | CN=GlobalSign Root CA,OU=Root CA,O=GlobalSign nv-sa,C=BE | 15 Nov 2023 | 28 Jan 2028 | ECDSA 384 | SHA256-RSA | 7fe530bf331343bedd821610493d8a1b |
Background: What to check on a remote MCP endpoint →
DNSSEC insecure
Validation of morphareels.ai. — Not signed
| Zone | DS | Keys | Algorithms | Outcome |
|---|---|---|---|---|
| . | trust_anchor | 20326, 38696 | 8, 8 | Verified |
| ai. | present | 3799 | 8 | Verified |
| morphareels.ai. | absent | Unsigned (proven) parent-signed NSEC/NSEC3 proves an unsigned delegation |
Authentication Enforced and verified
The endpoint asked for a token and published valid RFC 9728 metadata describing how to get one.
| Result | Enforced and verified |
|---|---|
| Enforced | On tool calls |
| HTTP status | 200 |
WWW-Authenticate challenge Bearer resource_metadata="https://morphareels.ai/.well-known/oauth-protected-resource"
Bearer resource_metadata="https://morphareels.ai/.well-known/oauth-protected-resource" | Header | Value |
|---|---|
| strict-transport-security | max-age=31536000; includeSubDomains |
Protected resource metadata
| Document | https://morphareels.ai/.well-known/oauth-protected-resource |
|---|---|
| Retrieved | Yes |
| Resource | https://morphareels.ai/mcp |
| Authorisation server | https://morphareels.ai |
Background: How OAuth 2.1 works in the 2026 MCP spec →
Transports 2 probes
| Transport | URL | Outcome | Status | Location |
|---|---|---|---|---|
| streamable-http | https://morphareels.ai/mcp | Verified | 200 | |
| http (plaintext) | http://morphareels.ai/mcp | HTTPS enforced | 301 | https://morphareels.ai/mcp |
The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →
list_versions List versions ~196
List every saved version of a project, newest-first. Returns summaries (id, name, timestamp, source, kind, version_number, cp) — not the inner project JSON. `kind` is `"bookmark"` (deliberate save, gets a v<N> label, partner-pinnable in the <morpha-video> embed) or `"auto"` (editor auto-snapshot every ~10 mutations, restore-only). `version_number` is bookmark-only and stable for the lifetime of that version — deletes leave gaps, numbers never re-shuffle. `cp` names which pages the version changed (comma-joined 8-char page-id prefixes; `"*"` = page order only; absent = unknown, treat as all pages). Use the returned `id` (or `v<version_number>` shorthand) with restore_version / rename_version / delete_version.
| Name | Type | Req | Description |
|---|---|---|---|
| projectId | string | yes | Project whose versions to list. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
list_workspaces List workspaces ~149
List the workspaces (shared team spaces) the account belongs to, as { id, name, role, memberCount } entries. `role` is the caller's role in that workspace (owner / admin / editor / viewer) — only owner/admin/editor can add projects. Use the `id` as the `workspaceId` argument to create_project, move_project_to_workspace, and list_projects; refer to the workspace by its `name` when talking to the user (never paste the id). Returns an empty list when the account has no email (workspace membership is email-based, so a keyless/dev identity sees none). Call this to discover a workspace before placing a project into it.
Input schema present but exposes no named parameters.
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
merge_caption_lines Merge caption lines ~135
Merge two or more caption lines into one. The earliest line survives with the union window and the time-ordered texts joined by spaces; the others are removed. All lines must share one flavour — every one welded to the SAME clip, or every one standalone — and no other caption line on that track may sit inside the merged span (move or include it first).
| Name | Type | Req | Description |
|---|---|---|---|
| elementIds | array | yes | Two or more caption lines, each "text.<id>". |
| projectId | string | yes | Opaque project id (a v4 UUID, from list_projects/create_project). Selects which existing project this call mutates. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
move_band Move band ~187
Place an embedded morpha band on the host timeline: set its TIME ORIGIN (the frame it starts). The band's whole inner reel plays relative to this frame, so its intro animations fire when the band appears instead of at 0:00 (the fix for 'the embedded intro doesn't animate'). Keeps the band's current window length; if it had none, the band spans from start to the composition end. Pass the band group's id (from describe_video — a group with morpha:true).
| Name | Type | Req | Description |
|---|---|---|---|
| bandId | string | yes | The embedded band's group id (group.<id> or the bare <id>). |
| projectId | string | yes | Opaque project id (a v4 UUID, from list_projects/create_project). Selects which existing project this call mutates. |
| start | number | yes | Host-timeline frame where the band begins (0-indexed, 30 fps). |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
move_layer Move layer ~483
Set a layer's static base transform. Writes x/y/w/h/rotation directly on image.<id>, video.<id>, and shapes.<id>; for group.<id> sets pivotX/pivotY (no width/height/rotation — use add_keyframe for group rotation). Also sets `scale` and `opacity`, which every layer kind carries. Note: when a layer has a keyframe track for a property, the track OVERRIDES the static value at every frame — use add_keyframe to animate, move_layer to set the un-animated default. A scale/opacity write over an existing track is REFUSED for that reason; pass clear_animation:true to replace the animation with the static value.
| Name | Type | Req | Description |
|---|---|---|---|
| clear_animation | boolean | – | Only meaningful when setting `scale` / `opacity` on a layer where that property is animated. true = the static value REPLACES the keyframe track. Omitted / false = the call is refused rather than wri… |
| elementId | string | yes | video.<id>, image.<id>, shapes.<id>, or group.<id>. |
| height | number | – | Height in px (must be > 0). |
| opacity | number | – | Layer opacity, 0..1 (values outside are allowed and clamp at paint time). Composes with any ancestor group's opacity. |
| projectId | string | yes | Opaque project id (a v4 UUID, from list_projects/create_project). Selects which existing project this call mutates. |
| rotation | number | – | Rotation in degrees, clockwise. |
| scale | number | – | Uniform scale multiplier about the layer's pivot. 1 = natural size. Every layer kind carries it. |
| width | number | – | Width in px (must be > 0). |
| x | number | – | Centre x in the element's OWN frame. At root that is canvas coords (1080 wide); INSIDE A GROUP it is the group's space, so it is not where the layer sits on the canvas. inspect_layers reports both —… |
| y | number | – | Centre y in the element's OWN frame — canvas coords (1920 tall) at root, the group's space inside a group. See `x`. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
move_project_to_workspace Move project to workspace ~156
Move a project into a workspace, or back to the caller's personal space. Pass `workspaceId` (from list_workspaces) to place the project in that workspace — every member then sees it, with their workspace role deciding edit vs view. Pass `workspaceId: null` to detach it back to personal. Requires an edit-capable role (owner/admin/editor) in the TARGET workspace and write access to the project. Switching a project from one workspace to another cleanly drops the old membership.
| Name | Type | Req | Description |
|---|---|---|---|
| projectId | string | yes | Id of the project to move. |
| workspaceId | string|null | yes | Target workspace id (from list_workspaces), or null to move the project back to the caller's personal space. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
open_project Open project ~115
Get a tappable link that opens a project directly in the editor (the editor loads exactly this project from the URL). Returns { name, editorUrl }. Use this whenever the user wants to view their work — after you make a change, or when they say "show me" / "open it" — then give them the editorUrl and invite them to tap it. Refer to the project by its name in your reply; the link is the tap target.
| Name | Type | Req | Description |
|---|---|---|---|
| projectId | string | yes | Id of the project to open. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object | – | The project, as a person would refer to it. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
reid_project Re-id project ~163
Change a project's id LOSSLESSLY — re-keys its JSON, every saved version, and all assets + clips, then deletes the old id. Unlike create_project (clone), version history is preserved. Enforces the id policy: the new id is always a v4 UUID — pass `newId` to choose one, or omit to mint a fresh UUID. A project's `name` (the only user-facing label) is untouched, so the picker/editor are unchanged. The editor won't auto-refresh — reload to see the new id in URLs.
| Name | Type | Req | Description |
|---|---|---|---|
| newId | string | – | Optional new id — must be a v4 UUID. Omit to mint a fresh UUID automatically. |
| projectId | string | yes | Current id of the project to re-key. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
remove_audio_overlay Remove audio overlay ~65
Delete an audio overlay by id.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | Overlay id (e.g. audio_1). |
| projectId | string | yes | Opaque project id (a v4 UUID, from list_projects/create_project). Selects which existing project this call mutates. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
remove_color_keyframe Remove color keyframe ~124
Remove the colour keyframe at an exact frame on a fill track. No-op when no track or no matching keyframe exists. Removing the last keyframe drops the track entry.
| Name | Type | Req | Description |
|---|---|---|---|
| elementId | string | yes | Element id. The canvas backdrop is the pinned is_background image_layer; 'background.canvas' is accepted as a synonym. |
| frame | number | yes | – |
| projectId | string | yes | Opaque project id (a v4 UUID, from list_projects/create_project). Selects which existing project this call mutates. |
| property | string | yes | – |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
remove_embed_origin Remove embed origin ~145
Remove one hostname from the project's embed allowlist. Idempotent — removing an entry that isn't present is a no-op. Removing the last entry turns embedding OFF (the public embed endpoint 404s the project). Morpha sends that website no request; a page on it stops loading the project. Reference: https://morphareels.ai/docs/tools#removeembedoriginorigin
| Name | Type | Req | Description |
|---|---|---|---|
| origin | string | yes | Hostname or URL to remove. Normalized the same way as add_embed_origin before matching. |
| projectId | string | yes | Opaque project id (a v4 UUID, from list_projects/create_project). Selects which existing project this call mutates. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
remove_from_collection Remove from collection ~109
Remove a layer from the user's Collection so it's no longer offered for reuse. Pass the element id that was added with add_to_collection. Copies already placed in other projects are unaffected (they're self-contained). No-op if the id isn't in the collection.
| Name | Type | Req | Description |
|---|---|---|---|
| elementId | string | yes | The element id to remove from the Collection. |
| projectId | string | yes | Opaque project id (a v4 UUID, from list_projects/create_project). Selects which existing project this call mutates. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
remove_keyframe Remove keyframe ~96
Remove the keyframe at frame N on a layer's track. Removing the last keyframe from a track restores the layer's static base value across the timeline.
| Name | Type | Req | Description |
|---|---|---|---|
| elementId | string | yes | – |
| frame | number | yes | – |
| projectId | string | yes | Opaque project id (a v4 UUID, from list_projects/create_project). Selects which existing project this call mutates. |
| property | string | yes | – |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
remove_layer Remove layer ~151
Delete a video, image, text, or shape LEAF layer. Errors on a group.<id> (dissolve it with ungroup_layers instead) and on a pinned layer such as the canvas backdrop. Deleting a video layer also takes everything welded to that clip: its welded audio overlay(s) and its welded caption lines, both of which derive their timing from the clip's trim and have no meaning without it.
| Name | Type | Req | Description |
|---|---|---|---|
| elementId | string | yes | video.<id>, image.<id>, text.<id>, or shapes.<id>. |
| projectId | string | yes | Opaque project id (a v4 UUID, from list_projects/create_project). Selects which existing project this call mutates. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
remove_speed_keyframe Remove speed keyframe ~121
Remove the speed-ramp keyframe at `frame` (a PROJECT-timeline frame — the same value add_speed_keyframe and inspect_layers report) on a video layer. Removing the last keyframe clears the speed_keyframes array entirely (restoring 1× playback).
| Name | Type | Req | Description |
|---|---|---|---|
| elementId | string | yes | video.<id>. |
| frame | number | yes | Project-timeline frame number. |
| projectId | string | yes | Opaque project id (a v4 UUID, from list_projects/create_project). Selects which existing project this call mutates. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
rename_group Rename group ~73
Rename a group. Pure cosmetic — labels appear in the Inspector and describe_video output.
| Name | Type | Req | Description |
|---|---|---|---|
| groupId | string | yes | – |
| name | string | yes | – |
| projectId | string | yes | Opaque project id (a v4 UUID, from list_projects/create_project). Selects which existing project this call mutates. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
rename_layer Rename layer ~159
Set the human-readable name of a video / image / shape / text layer — the label shown in the Inspector, and the basis for the layer's auto-derived <morpha-video> embed attribute (so renaming a layer to "caption" makes the embed attribute `caption`). Pass an empty string to clear the name. For groups use rename_group.
| Name | Type | Req | Description |
|---|---|---|---|
| elementId | string | yes | video.<id>, image.<id>, shapes.<id>, or text.<id>. |
| name | string | yes | New label. Empty string clears it (callers fall back to the filename stem). |
| projectId | string | yes | Opaque project id (a v4 UUID, from list_projects/create_project). Selects which existing project this call mutates. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
rename_project Rename project ~88
Update a project's human-readable name (shown in the editor's project picker). Pass an empty string to clear the name and fall back to the id. Doesn't touch any layers, animations, or styles — only the picker label.
| Name | Type | Req | Description |
|---|---|---|---|
| name | string | yes | New human-readable label. Empty string clears the name and reverts to the id fallback. |
| projectId | string | yes | Project to rename. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
rename_version Rename version ~120
Rename a saved version's human-readable label (what the user sees in the picker). The `v<N>` partner-facing identifier is unaffected — only the display name changes. Accepts the version's UUID `id` or the `v<N>` shorthand. Empty / whitespace-only names are rejected.
| Name | Type | Req | Description |
|---|---|---|---|
| name | string | yes | New human-readable label. Must be a non-empty string. |
| projectId | string | yes | Project whose version to rename. |
| versionId | string | yes | Version to rename. UUID `id` or `v<N>` shorthand. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
rename_workspace Rename workspace ~91
Rename an existing workspace. Requires an owner or admin role in it (the same roles that may change its membership); an editor or viewer is refused. Takes the workspace id from list_workspaces. Touches only the label — membership, projects and roles are unchanged.
| Name | Type | Req | Description |
|---|---|---|---|
| name | string | yes | New human-readable name. |
| workspaceId | string | yes | Id of the workspace to rename (from list_workspaces). |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
render_status Render status ~179
Check a server render started by render_video, and get its download link. Returns { ok: true, status: 'not-ready' } while it is still rendering (wait and call again), or { ok: true, status: 'ready', data: { downloadUrl, editorUrl, expiresAt, videoSeconds, scale, chargedCents } } once the MP4 is ready. `downloadUrl` is a plain https link needing no Morpha account — give it to the person; it stops working when the render is deleted at `expiresAt` (7 days). `chargedCents` is what the render cost the subscription. A render that failed answers ok:false with a plain reason and is never charged. Only the account that started a render can read it.
| Name | Type | Req | Description |
|---|---|---|---|
| renderId | string | yes | The renderId render_video returned. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
render_video Render video ~456
Render the project to an MP4 on Morpha's servers, for an agent that has no browser to drive (a chat app, a Linux box). Returns { renderId, status: 'rendering', next } — call render_status with that renderId after about 30 seconds. THIS COSTS THE ACCOUNT MONEY and needs a subscription: the render is charged to the subscription's credits at Morpha's measured compute cost, so a longer composition and a larger scale both cost more. Two free routes exist and are usually better — give the person the editorUrl every project result carries and they choose Share, then Download (Render MP4 on a phone) in the editor, free and with no watermark; or a script runs the morphareels-sdk npm client's client.renderVideo(projectId) on macOS or Windows. Renders at 2x the canvas by default, the same as the editor and the npm client; pass scale: 1 for the canvas's own size, which is faster and cheaper. The cost is reserved against the subscription's credits before the render starts, so a render is refused up front when the credit to pay for it is not there rather than discovered afterwards; you are then billed the real measured cost, never more than the amount reserved. Refused for a composition longer than 30 minutes, when the remaining credit will not cover it, or while 3 renders are already running for this account. The finished file stays downloadable for 7 days, then it is deleted; the project stays and can be rendered again. The render downloads the project's fonts from their hosts, including a custom font's own URL (set_custom_font). Reference: https://morphareels.ai/docs/tools#rendervideopage-scale
| Name | Type | Req | Description |
|---|---|---|---|
| page | number | – | Optional 0-based page index for a multi-page project. Omit for the project's active page; render one page per call. |
| projectId | string | yes | Project to render. |
| scale | number | – | Optional output scale: 2 (the default) renders at twice the canvas, roughly 4K for a portrait project; 1 renders at the canvas's own size for a faster, cheaper file. Nothing else is accepted. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
reorder_layer Reorder layer ~111
Move a layer within its parent's siblings. newIndex is 0-based among siblings (root list when ungrouped, or the parent group's children when nested). 0 = bottom of that subtree; last = top.
| Name | Type | Req | Description |
|---|---|---|---|
| elementId | string | yes | – |
| newIndex | number | yes | 0-based index among siblings of the same parent. |
| projectId | string | yes | Opaque project id (a v4 UUID, from list_projects/create_project). Selects which existing project this call mutates. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
reorder_pages Reorder pages ~122
Move a page from `from_index` to `to_index`. The remaining pages shift to fill the gap; active_index is rewritten so it keeps pointing at the same page it did before the move. Fails on out-of-range indices.
| Name | Type | Req | Description |
|---|---|---|---|
| from_index | number | yes | 0-based index of the page to move. |
| projectId | string | yes | Opaque project id (a v4 UUID, from list_projects/create_project). Selects which existing project this call mutates. |
| to_index | number | yes | 0-based destination index for the page. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
restore_version Restore version ~290
Load a saved version over the live project. Accepts either the version's UUID `id` or the `v<N>` shorthand (e.g. `"v6"` finds the bookmark with version_number=6); auto-snapshots are addressable by UUID only. Without `page_index` this replaces the ENTIRE project (every page) — an auto checkpoint named `before restore: …` is saved first whenever the current state has unsaved changes, so the overwritten state stays recoverable. With `page_index` it restores ONLY that page: the page is matched across versions by its stable id and replaced verbatim (canvas size and name included); other pages are untouched and the write is compare-and-swapped against concurrent edits. Errors if the version predates that page — restore the whole version instead. A restored page may reference assets deleted since the snapshot; those render as missing. An open editor reconciles the result into the live project within a few seconds — no refresh needed.
| Name | Type | Req | Description |
|---|---|---|---|
| page_index | number | – | Optional. 0-based index into the project's CURRENT pages (same indexing as select_page / delete_page). Restores only that page from the version; omit to restore the whole project. |
| projectId | string | yes | Project to restore into. |
| versionId | string | yes | Version to restore. UUID `id` or `v<N>` shorthand (partner-facing bookmark number). |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
safe_zones Safe zones ~270
Return horizontal 'safe band' y-ranges of the canvas where a clip's burned-in video text (subtitles, lower thirds, titles) does NOT appear, plus the inverse 'text bands' (where it does). Reads the OCR cache built at clip-upload time (see detect_text_regions). Coordinates returned in BOTH source pixels and CANVAS pixels — canvas coords already account for the video layer's fit/anchor/position. Use to lay out captions, titles, callouts so they never collide with the video's own text. This is about the clip's own burned-in text: where TikTok and Instagram Reels cover the canvas with their UI is describe_video's platform_safe_area. Returns { ok: true, status: 'ready' | 'not-ready', data: { bands, safeBands, textBands } }.
| Name | Type | Req | Description |
|---|---|---|---|
| bandHeight | number | – | Vertical granularity in source pixels (default 32). |
| clip | string | yes | Clip filename (video.<id>.clip). |
| minConfidence | number | – | OCR confidence floor (0–100) for considering a text region (default 70). |
| occupancyThreshold | number | – | Fraction of frames that must contain text in a band to mark it occupied (default 0.10). |
| projectId | string | yes | – |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
save_version Save version ~150
Save a version of the current project state. ALWAYS call this once after each meaningful set of changes you make on the user's behalf — the user flicks between versions to compare or roll back, so an unsaved edit is one they can't easily revisit. Use a short descriptive `name` (e.g. "add slide-in animation"); the user sees this verbatim in the picker. One version per logical change-set, not one per individual tool call.
| Name | Type | Req | Description |
|---|---|---|---|
| name | string | – | Short label describing what this set of changes accomplished. Defaults to a timestamp if omitted, but a description is much more useful to the user. |
| projectId | string | yes | Project to save a version of (filename stem). |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
select_page Select page ~128
Switch which page is ACTIVE — the page the content tools target. Subsequent describe_video / inspect_layers / all content tools read and write this page until the active page changes again. Pages are addressed by 0-based index from describe_video's pages block. Selecting the already-active page is a harmless no-op; fails on an out-of-range index.
| Name | Type | Req | Description |
|---|---|---|---|
| index | number | yes | 0-based index of the page to make active. |
| projectId | string | yes | Opaque project id (a v4 UUID, from list_projects/create_project). Selects which existing project this call mutates. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
set_canvas_size Set canvas size ~270
Resize the ACTIVE page's canvas to width × height pixels. The composition is scaled UNIFORMLY to fit the new frame (a single factor s = min(newW/oldW, newH/oldH), so nothing distorts — a circle stays a circle) and then re-centred so the old composition centre maps to the new canvas centre. Every layer's position, size, group pivots, and x/y/width/height keyframes follow this fit+recentre; same-aspect resizes scale exactly, aspect changes letterbox the content centred. Each page owns its size, so this leaves sibling pages untouched — select_page then set_canvas_size again to resize another one. Common sizes: 1080×1920 (9:16 Reels/TikTok/Shorts), 1080×1350 (4:5 Instagram), 1080×1080 (1:1 square), 1920×1080 (16:9 YouTube).
| Name | Type | Req | Description |
|---|---|---|---|
| height | number | yes | Canvas height in px (positive integer). |
| projectId | string | yes | Opaque project id (a v4 UUID, from list_projects/create_project). Selects which existing project this call mutates. |
| width | number | yes | Canvas width in px (positive integer). |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
set_clip_speed Set clip speed ~204
Play a clip slower or faster at a CONSTANT rate — the normal way to retime a clip. 1 = source speed, 0.5 = half speed, 2 = double speed; range [0.1, 8]. The trim is unchanged, so the clip's length on the timeline changes to suit: at 0.5x it occupies twice as many frames, at 2x half as many. Audio is time-stretched with pitch preserved. Use add_speed_keyframe instead only when the rate must CHANGE over the clip (a ramp).
| Name | Type | Req | Description |
|---|---|---|---|
| elementId | string | yes | video.<id>. |
| projectId | string | yes | Opaque project id (a v4 UUID, from list_projects/create_project). Selects which existing project this call mutates. |
| speed | number | yes | Constant playback rate (1 = source speed, 0.5 = half, 2 = double), in [0.1, 8]. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
set_custom_font Set custom font ~410
Register a typeface Morpha does NOT ship, so text layers can use it by family name via font_family (exactly like a built-in family). Families already in the built-in catalogs (anything list_fonts returns from google/bunny/fontshare/fontsource/velvetyne) are REJECTED — they need no registration; just set font_family to them directly. `src` is EITHER a full URL (https://…) OR a font file already uploaded to the project's asset bucket (create_upload_link, or POST /api/upload-asset/<projectId> with raw bytes + an X-Upload-Name header; .woff2/.woff/.ttf/.otf): pass the filename the upload returned. Like add_image_layer, this does NOT verify an uploaded filename exists. Dedupes by family+weight+style, replacing a matching face. After registering, set a text layer's font_family to this family (add_text_layer / set_layer_text). NOTE: a pasted URL only loads if that host sends permissive CORS headers — uploading the font (served same-origin) is the robust path. A URL is not fetched when this tool runs: Morpha's renderer and every browser that opens the project download it later. Reference: https://morphareels.ai/docs/tools#setcustomfontfamily-src-weight-style
| Name | Type | Req | Description |
|---|---|---|---|
| family | string | yes | Family name text layers will reference via font_family, e.g. "Mylius Modern". |
| projectId | string | yes | Opaque project id (a v4 UUID, from list_projects/create_project). Selects which existing project this call mutates. |
| src | string | yes | A full font URL (https://…/font.woff2) OR an uploaded asset filename in the project's bucket. |
| style | string | – | Optional face style. Defaults to normal. |
| weight | number | – | Optional specific weight (1-1000) this src provides. Omit for the 400/normal baseline. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
set_duration Set duration ~203
Author an EXPLICIT composition length in seconds, pinning it (duration_authored=true) so the auto-fit no longer drives it. Morpha normally DERIVES the comp length from content (the furthest keyframe / video window / audio end); this overrides that with a fixed length — the stage becomes a fixed canvas you author into, and content past the end is kept but not played or exported. 1-second floor, no ceiling. Use it to shorten a comp to a target length (e.g. a 15-second cut) or to reserve a longer stage than the current content fills. Call fit_duration_to_content to release the pin.
| Name | Type | Req | Description |
|---|---|---|---|
| projectId | string | yes | Opaque project id (a v4 UUID, from list_projects/create_project). Selects which existing project this call mutates. |
| seconds | number | yes | Composition length in seconds (1-second floor, no ceiling). 30 fps; durationInFrames = ceil(seconds*30). |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
set_embed_origins Set embed origins ~250
Replace the project's embed allowlist — the hostnames permitted to load this project through the public <morpha-video> embed. Pass the full desired list; it overwrites the previous one. An empty array turns embedding OFF (the public embed endpoint 404s the project). Each entry is normalized to a bare lowercased hostname (scheme, port, and path stripped, e.g. "https://example.com/x" → "example.com"); duplicates are dropped. Morpha sends the listed websites no request: the list decides which of them may load the project, so any page on an allowed host can show it. The embed serves only saved bookmarks (save_version), never unsaved edits, and leaves out who the project is shared with. Reference: https://morphareels.ai/docs/tools#setembedoriginsorigins
| Name | Type | Req | Description |
|---|---|---|---|
| origins | array | yes | Full desired allowlist. Each entry may be a bare hostname or a URL; it is normalized to a bare lowercased hostname. Empty array disables embedding. |
| projectId | string | yes | Opaque project id (a v4 UUID, from list_projects/create_project). Selects which existing project this call mutates. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
set_group_box Set group box ~124
Set a group's backdrop rect size. The rect is centred on (pivotX, pivotY) in group-local space and transforms with the group. Either dimension at 0 hides the backdrop entirely.
| Name | Type | Req | Description |
|---|---|---|---|
| box_height | number | yes | Backdrop height in px (non-negative). |
| box_width | number | yes | Backdrop width in px (non-negative). |
| elementId | string | yes | group.<id>. |
| projectId | string | yes | Opaque project id (a v4 UUID, from list_projects/create_project). Selects which existing project this call mutates. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
set_group_parent Set group parent ~138
Move an element into a group (or out to root). Refuses to place a group inside its own descendants.
| Name | Type | Req | Description |
|---|---|---|---|
| elementId | string | yes | Full element id: video.<id>, image.<id>, shapes.<id>, or group.<id>. |
| index | number | – | 0-based insert position among the new parent's children. Defaults to end. |
| parentGroupId | string|null | yes | Bare group id of the new parent, or null to move to root. |
| projectId | string | yes | Opaque project id (a v4 UUID, from list_projects/create_project). Selects which existing project this call mutates. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
set_group_window Set group window ~268
TRIM a group's own visible window — the [start, start+duration) range over which the group and its subtree are drawn. The contents are NOT moved or deleted: this clips what is shown, so use it to hide the head or tail of a whole section. Writing a window overrides the group's derived contents-hull from then on. Two safety corrections apply automatically: the group's OWN keyframes are compensated for the change in start so its animation doesn't jump (reported as keyframesCompensatedBy), and the duration is grown if needed so the window can never hide one of the group's own authored keyframes (reported as grownToCoverKeyframes). To MOVE the group and its contents instead, use shift_group.
| Name | Type | Req | Description |
|---|---|---|---|
| duration | number | yes | How many frames the group stays drawn for (≥ 1). Grown automatically if it would hide the group's own keyframes. |
| elementId | string | yes | The group's id (group.<id> or the bare <id>). |
| projectId | string | yes | Opaque project id (a v4 UUID, from list_projects/create_project). Selects which existing project this call mutates. |
| start | number | yes | First frame the group is drawn on, in its parent timeline (0-indexed, 30 fps). |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
set_image_filename Set image filename ~256
Repoint an existing image layer at a different uploaded asset — keeps the layer's id, position, size, animations, and styles; only the bitmap changes. The asset must already exist at users/<userId>/assets/<projectId>/<filename> (the editor's drag-drop, upload_image, create_upload_link, or POST /api/upload-asset/<projectId> with the raw bytes and an X-Upload-Name header); pass the `filename` the upload returned, and its `name` as the label. Use this to swap a layer's image WITHOUT losing its keyframes — `remove_layer` + `add_image_layer` would mint a new id and drop the animations.
| Name | Type | Req | Description |
|---|---|---|---|
| elementId | string | yes | Image layer id, image.<id>. |
| filename | string | yes | The uploaded file's id: the `filename` its upload returned. |
| name | string|null | – | Optional label people see for the layer: pass the upload's returned `name`. Omit to keep the current label; null or an empty string clears it. |
| projectId | string | yes | Opaque project id (a v4 UUID, from list_projects/create_project). Selects which existing project this call mutates. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
set_keyframes_batch Set keyframes batch ~150
Add or overwrite MANY keyframes across MANY layers in ONE call — functionally equivalent to N add_keyframe calls but with one HTTP/MCP round-trip. Pass an array of entries; each entry has the same fields as add_keyframe. Validated atomically: any invalid entry rejects the whole batch. Use this whenever you'd call add_keyframe more than a couple of times (rippling grids, twinkling starfields, staggered text reveals).
| Name | Type | Req | Description |
|---|---|---|---|
| keyframes | array | yes | One or more keyframe entries to apply. |
| projectId | string | yes | Opaque project id (a v4 UUID, from list_projects/create_project). Selects which existing project this call mutates. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
set_layer_block Set layer block ~258
Set (or replace) a layer's timeline BLOCK — the [start, start+duration) window it exists for. The layer is drawn ONLY inside that window, and its animation keyframes are sampled RELATIVE to the block start, so moving or trimming the block re-anchors its intro instead of leaving it behind. This is how a layer 'starts' at a point like an iMovie clip rather than being present for the whole composition. Works on any leaf or group. Frames are in the layer's parent timeline (composition frames at root; band-local inside an embedded morpha band). To place a whole embedded reel, use move_band.
| Name | Type | Req | Description |
|---|---|---|---|
| duration | number | yes | How many frames the layer lasts (≥ 1). Hidden outside [start, start+duration). |
| elementId | string | yes | Element id of the layer (image.<id>, video.<id>, text.<id>, shapes.<id>, or group.<id>). |
| projectId | string | yes | Opaque project id (a v4 UUID, from list_projects/create_project). Selects which existing project this call mutates. |
| start | number | yes | First frame the layer appears (0-indexed, 30 fps), in its parent timeline. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
set_layer_fill Set layer fill ~469
Set a layer's fill. The canvas backdrop is the pinned is_background image_layer (its element id is exposed via describe_video as background.elementId; the literal 'background.canvas' is also accepted as a synonym); null is rejected on the backdrop. Shapes require a Fill (null/missing is rejected). Image / video / text / group layers accept a Fill object (or `#rrggbb` hex) to paint a backdrop, or `null` to clear it — clearing removes the layer's fill colour keyframes too, so an animated backdrop really does go away. Shapes paint their body; image/video paint behind the bitmap; groups paint a rect centred on the pivot sized by (box_width, box_height). REFUSED on a layer whose fill is ANIMATED (it has colour keyframes): the track wins at every frame, so a plain fill write would be invisible. Change it at a frame with add_color_keyframe, or pass clear_animation:true to replace the animation with this fill.
| Name | Type | Req | Description |
|---|---|---|---|
| clear_animation | boolean | – | Only meaningful on a layer whose fill is animated. true = this fill REPLACES the colour animation (its keyframes are deleted). Omitted / false = the call is refused rather than writing a fill the ani… |
| elementId | string | yes | shapes.<id> / image.<id> / video.<id> / group.<id>. The pinned is_background image_layer is the canvas backdrop; the literal 'background.canvas' is accepted as a synonym. |
| fill | string|object|null | yes | Either '#rrggbb' (promoted to solid) or a Fill object: {type:"solid",color} / {type:"linear",stops:[{pos:0..1,color}],angle?} / {type:"radial",stops:[{pos:0..1,color}],cx?,cy?,radius?} / {type:"mask"… |
| projectId | string | yes | Opaque project id (a v4 UUID, from list_projects/create_project). Selects which existing project this call mutates. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|array|string|number|boolean|null | – | The payload, shaped by the tool. |
| editorUrl | string | – | Opens this project in the editor. |
| error | string | – | Why it failed. |
| note | string | – | What to do next when not ready. |
| ok | boolean | yes | Whether the call succeeded. |
| status | string | – | For cache-backed readers: whether the answer was ready. |
No examples provided.
What is the Morpha MCP server?
Morpha is an MCP server listed in the public MCP registry as ai.morphareels/morpha. AI editor to build, animate & export layered short-form video projects via one tool catalog. This page covers its hosted endpoint (https://morphareels.ai/mcp).
Is the Morpha MCP server safe to use?
Morpha scores 84 out of 100 on VerifyMCP. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.
What tools does the Morpha MCP server expose?
Morpha exposes 98 tools: list_projects, list_workspaces, create_workspace, rename_workspace, open_project, and 93 more. Their descriptions and schemas cost roughly 24,541 tokens of context every time the server is loaded.
Does the Morpha MCP server require authentication?
Yes. Morpha asked us for credentials when we connected, so you will need to authorise it in your MCP client before it can do anything.
Is the Morpha MCP server still maintained?
Morpha is still listed as active in the MCP registry. We last reached this channel on 21 September 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.