MCP Tool Reference
Complete reference for the tools exposed by the Nodaro MCP server.
Scopes
Each tool requires one or more OAuth scopes. Grant the relevant scopes when authorizing the connector; missing scopes cause tools to be omitted entirely (they never appear in the tool list).
| Scope | Controls |
|---|---|
workflows:read |
list_projects, get_project, list_workflows, get_workflow, get_workflow_json, export_workflow, list_components, get_component_inputs, get_recast_status, validate_studio_plan, list_studio_productions, get_studio_production, plan_studio_export |
workflows:write |
create_workflow, delete_workflow, update_workflow_json, import_workflow, import_recast_script, create_studio_production, import_studio_production, edit_studio_production, share_studio_production, clone_studio_production |
workflows:execute |
run_workflow, all generation verbs (image/video/audio/Suno/character/location/object), run_component, run_app, delete_app_run, analyze_prompt, generate_prompt, enhance_prompt, reduce, forced_alignment, video_analysis, video_audit, silence_detect, apply_edl, resolve_shot_sequence, render_shot_sequence, create_explainer, create_launch_video, start_recast, resolve_recast_gate; with workflows:write also describe_studio_production, generate_studio_still, generate_studio_keyframe, generate_studio_clip, new_studio_shot_from_frame, voice_studio_shot, revoice_studio_clip, score_studio_production |
jobs:read |
list_jobs, get_job, diagnose_run |
assets:read |
browse_gallery, browse_uploads, list_favorites, get_asset, display_asset, get_app_run, list_characters, get_character, list_locations, get_location, list_objects, get_object, list_creatures, get_creature |
assets:write |
favorite_asset, create_character, update_character, approve_portrait, recaption_character, create_location, update_location, approve_main_image, recaption_location, approve_object_main_image, recaption_object, upload_image_widget, upload_audio_widget, upload_video_widget, request_image_upload, request_audio_upload, request_video_upload, prepare_image_upload, prepare_audio_upload, prepare_video_upload |
credits:read |
check_balance, credit_transactions |
apps:read |
list_apps, get_app_inputs |
pipelines:read |
get_pipeline_stage_chat, get_pipeline_status, pipeline_pending_approvals |
pipelines:execute |
branch_pipeline, start_pipeline |
pipelines:approve |
chat_pipeline_stage, apply_chat_proposal |
presets:read |
list_node_presets, get_node_preset |
workspaces:read |
list_workspaces |
workspaces:write |
select_workspace |
Ungated (always visible): ping, list_models, start_film_director, start_video_director, start_workflow_editor, get_node_skill, get_picker_catalog, list_shot_shapes, get_shot_shape, list_brand_presets, get_recipe, get_studio_production_skill
The workspace scopes are deliberately not granted to tokens issued before organizations existed: consenting to an app back then could not have meant agreeing to let it choose where your work lands. Re-authorize to grant them.
Workspace tools
Only on instances with organizations. Everywhere else these tools are absent rather than present-and-empty, so a client discovers there is no such concept here instead of finding a switch that does nothing.
A browser picks a workspace from a switcher and every request carries the choice. An MCP client has neither a switcher nor a header it controls, so the same two questions become tools.
list_workspaces
The organizations and workspaces this account belongs to, and which workspace the session is working in.
Scope: workspaces:read
Input: none
An empty result means the account belongs to no organization — normal, not an error.
Response shape:
{
"workspaces": [
{ "id": "uuid", "orgId": "uuid", "name": "Class 1", "slug": "class-1", "role": "member", "memberStatus": "active", "archived": false }
],
"organizations": [
{ "id": "uuid", "slug": "kent-high", "name": "Kent High", "kind": "school", "status": "active", "role": "owner" }
],
"selectedWorkspaceId": "uuid"
}
select_workspace
Work in a workspace for the rest of the session, and remember it for the next
one. Pass workspace_id: null to go back to the personal space.
Scope: workspaces:write
Input: workspace_id (uuid or null)
The tool does not decide whether a workspace is selectable — it proposes one and the server either resolves it or refuses. Only what actually resolved is remembered: a preference that was never valid costs every later session a lookup.
The stored selection is re-validated at every session, never trusted. A preference is written once and read for months, and membership can end in between; a client that kept working inside a workspace it had been removed from is the one failure the tenancy axis exists to prevent, and unlike a browser there is nobody watching a switcher who would notice. A selection that no longer resolves is cleared and the session continues in the personal space, rather than refusing every tool to someone whose only mistake was being removed from a class.
Selecting records where the session’s work belongs. It grants nothing and moves nothing, so selecting the wrong one wastes a step rather than exposing anything.
Job cards
Generation tools render an inline tool card in MCP-Apps hosts (claude.ai):
live progress, then the finished result. Media tools (generate_image,
generate_video, generate_music, …) have media-specific cards. All remaining
job tools — entity motion clips (generate_*_motion), render_shot_sequence,
create_explainer, create_launch_video, run_component, and the
text-output tools (image_to_text, generate_script, transcribe,
suno_lyrics, suno_style_boost, forced_alignment, video_analysis, video_audit) — share the universal
job card, which auto-detects the output: video/image/audio players, inline
text with a Copy button (scripts, lyrics, transcripts, alignment JSON), or a
component’s stacked outputs.
Result-text contract: job tools respond with "<label> started (id <jobId>)"
plus card-first guidance. Clients without card support poll get_job with the
job id (run_app returns an execution id — poll get_app_run instead). The
result is always also saved to your Nodaro library.
The “mcp” project
In the app’s dashboard these workflows are listed under their own MCP Workflows tab (next to My Workflows / My Projects / Studio Workflows), so flows an MCP client creates never crowd your hand-made list. From that tab you can open, move to another project, or delete them like any other workflow.
All workflow tools that create or modify workflows operate inside a single project named “mcp”. This project is created automatically on first use — agents do not need to set it up.
Scope of the boundary:
| Tool | Scope |
|---|---|
list_projects, get_project |
Sees all of your projects (read-only discovery) |
list_workflows, get_workflow, get_workflow_json |
Only sees workflows in the mcp project |
create_workflow, delete_workflow, update_workflow_json, import_workflow |
Only touches the mcp project |
export_workflow |
Can read any of your workflows (use it to pull work from a personal project into the mcp project via export → import) |
run_workflow |
Only runs workflows in the mcp project |
This isolation keeps agent-managed workflows out of your personal projects.
Project tools
list_projects
Returns all projects in your account, ordered by name.
Scope: workflows:read
Input: none
Response shape:
{
"data": [
{
"id": "uuid",
"name": "mcp",
"description": "Workflows managed via MCP",
"workflowCount": 3,
"createdAt": "2026-01-15T10:00:00.000Z"
}
]
}
get_project
Returns a single project by UUID or by name (case-sensitive exact match).
Scope: workflows:read
Input:
| Field | Type | Notes |
|---|---|---|
project_id |
string | A project UUID or a project name |
Example: { "project_id": "My Feature Film" } resolves by name.
Example: { "project_id": "550e8400-e29b-41d4-a716-446655440000" } resolves by UUID.
Response shape:
{
"data": {
"id": "uuid",
"name": "My Feature Film",
"description": null,
"workflowCount": 12,
"createdAt": "2026-03-01T09:00:00.000Z"
}
}
Workflow tools
list_workflows
Lists workflows in the mcp project, newest first.
Scope: workflows:read
Input:
| Field | Type | Notes |
|---|---|---|
limit |
integer (1–100) | Default 20 |
cursor |
string | ISO created_at from a prior response’s next_cursor; use for pagination |
include_sub_workflows |
boolean | Default false. When false, hides workflows with parent_workflow_id (child sub-workflows owned by another container). Pass true to surface them. |
By default, list_workflows returns only top-level workflows — child sub-workflows
(those owned by a parent container via parent_workflow_id) are hidden so the list
reflects what you would see in the editor’s project view. Set
include_sub_workflows: true if you need to enumerate every workflow in the mcp
project regardless of nesting.
Response shape:
{
"data": [
{
"id": "uuid",
"project_id": "uuid",
"name": "My Workflow",
"description": null,
"version": 1,
"thumbnail_url": null,
"created_at": "2026-05-01T12:00:00.000Z",
"updated_at": "2026-05-01T12:00:00.000Z"
}
],
"next_cursor": "2026-04-30T08:00:00.000Z"
}
Pass next_cursor as cursor in the next call to get the next page. When
next_cursor is null, you’ve reached the last page.
get_workflow
Returns metadata for a single workflow in the mcp project.
Scope: workflows:read
Input:
| Field | Type | Notes |
|---|---|---|
workflow_id |
UUID string | Must be in the mcp project |
create_workflow
Creates a new workflow in the mcp project. You can seed it with an initial node graph or leave it empty.
Scope: workflows:write
Input:
| Field | Type | Notes |
|---|---|---|
name |
string (1–200) | Required |
description |
string (max 2000) | Optional |
nodes |
array of objects | Optional; React Flow node objects |
edges |
array of objects | Optional; React Flow edge objects |
settings |
object | Optional; workflow-level settings |
Response: Returns the new workflow’s id and name in structured content.
delete_workflow
Deletes a workflow from the mcp project. This is permanent.
Scope: workflows:write
Input:
| Field | Type | Notes |
|---|---|---|
workflow_id |
UUID string | Must be in the mcp project |
Returns an error if the workflow doesn’t exist in the mcp project.
get_workflow_json
Returns the full React Flow graph for a workflow in the mcp project: nodes,
edges, settings, name, and updated_at.
Scope: workflows:read
Input:
| Field | Type | Notes |
|---|---|---|
workflow_id |
UUID string | Must be in the mcp project |
Response shape:
{
"name": "My Workflow",
"nodes": [ ... ],
"edges": [ ... ],
"settings": {},
"updated_at": "2026-05-10T15:30:00.000Z"
}
Save updated_at and pass it as expected_updated_at to update_workflow_json
to enable optimistic concurrency control.
update_workflow_json
Updates a workflow in the mcp project: its node graph (nodes + edges), its
settings, and/or its thumbnail_url. All content fields are optional — pass
only thumbnail_url, for example, to set the preview image without re-sending
the graph.
Any AI prompt node’s data may carry promptPrefix / promptSuffix — pre/post
text wrapped around that node’s prompt at run time (settings-only; see
Prompt pre & post text).
Scope: workflows:write
Input:
| Field | Type | Notes |
|---|---|---|
workflow_id |
UUID string | Must be in the mcp project |
nodes |
array of objects | Optional; replaces the current nodes. Must be sent together with edges. |
edges |
array of objects | Optional; replaces the current edges. Must be sent together with nodes. |
settings |
object | Optional; if provided, replaces current settings |
thumbnail_url |
string (URL) or null | Optional; sets the workflow’s thumbnail image, or null to clear it. Must be an already-hosted image URL. |
expected_updated_at |
string (ISO 8601) | Optional; enables optimistic concurrency |
expected_version |
integer | Optional; integer CAS from get_workflow_json (preferred over expected_updated_at) |
delta |
object | Optional; id-keyed partial update applied atomically against delta.base_version (from get_workflow_json): upsert_nodes, delete_node_ids, upsert_edges, delete_edge_ids, set: { name?, settings? }. Mutually exclusive with every other content field. Prefer it over re-sending the graph. |
Studio productions: a workflow whose stored settings.studio exists is a
Studio production (its shots, results and plan live there). A settings
replace — full-body or delta.set.settings — that changes or drops
settings.studio is refused; echo it back unchanged (copy it from
get_workflow_json) or leave settings out.
Optimistic concurrency: Pass the updated_at value from a prior
get_workflow_json call as expected_updated_at. If the workflow has been
modified since you read it, the call returns a conflict error:
“Workflow was modified since you last read it. Fetch the latest JSON with get_workflow_json and retry.”
This prevents accidental overwrites when two agents or sessions edit the same
workflow concurrently. Omit expected_updated_at to skip the check and
overwrite unconditionally.
Model parameters are corrected, not rejected. Image nodes
(generate-image, image-to-image) carry model-specific levers — aspectRatio,
resolution, quality — and the allowed values differ sharply per provider.
GPT Image 1.5 (gpt-image) renders 1:1 / 3:2 / 2:3 and has no resolution
setting at all, while gpt-image-2 accepts auto / 1:1 / 16:9 / 9:16 / 4:3 /
3:4 at 1K–4K. Rather than failing the write, a value the selected model does
not accept is snapped to a valid one (or dropped, when the model has no such
lever), and the response tells you exactly what changed:
Updated workflow 4f0c… (12 nodes).
Adjusted 2 parameter(s) the selected model does not accept:
- node_8 (gpt-image): aspectRatio "16:9" → "1:1" — GPT Image 1.5 does not
support aspect_ratio "16:9". Supported: 1:1, 3:2, 2:3.
- node_8 (gpt-image): resolution "2K" → removed — GPT Image 1.5 has no
resolution setting.
The structured payload carries the same information under adjustments. Read
it: the stored value is not what you sent, and re-sending the original pair on
the next turn just repeats the correction. Use list_models to see each
model’s supported values up front, or pick the sibling model that supports what
you want. The same correction applies to create_workflow and
import_workflow.
Nodes configured with multiple providers at once are left untouched — the valid set there is the intersection across every selected provider, and no single replacement is correct for all of them.
export_workflow
Exports a workflow as a portable JSON bundle. Unlike other workflow tools,
export_workflow is not restricted to the mcp project — it can read any of
your workflows. Use it to pull an existing personal workflow into the mcp
project via export → import.
Scope: workflows:read
Input:
| Field | Type | Notes |
|---|---|---|
workflow_id |
UUID string | Any of your workflows |
with_assets |
boolean | Default false. When true, bundles character, object, and location entity data alongside the node graph |
Two export modes:
- Template mode (
with_assets: false, default) — exports the node graph with asset-specific content stripped. Useful for sharing workflow structures as reusable templates. - Full mode (
with_assets: true) — exports the node graph plus all referenced character, object, and location records. Useful for moving a complete production workflow between accounts or instances.
Response: A JSON string in the WorkflowExport format (version 1). Pass
the full string directly to import_workflow.
Portability note. When nodes reference media another instance cannot
fetch — a self-hosted install’s own storage on localhost, a LAN address, an
.internal name — the bundle carries portability.unreachableMedia
({ nodeId, nodeLabel, field, url } per reference). Such a bundle still
imports, but those nodes will not run elsewhere until the media is re-uploaded
there. Absent when every media URL is publicly reachable.
import_workflow
Imports a workflow from a JSON bundle produced by export_workflow. Always
imports into the mcp project. If the bundle includes asset data
(with_assets: true), new character, object, and location records are created
under your account with fresh IDs; node references are remapped automatically.
Media the bundle references on other hosts is copied onto this instance’s storage where reachable (up to 25 distinct files for the graph’s media and 25 more for the bundled entities’ — separate budgets, so neither starves the other; images up to 20 MB, video/audio up to 50 MB), so the workflow runs from local copies.
Scope: workflows:write
Input:
| Field | Type | Notes |
|---|---|---|
workflow_json |
string | The full JSON string from export_workflow |
Response: Returns the new workflow’s id and name in structured content,
plus importReport — { rehosted, unreachable[], skipped[], assetIdMap?,
assetsSkipped? } — saying which media was copied, which points at a private
host this instance cannot reach (left as-is), and which was skipped with the
reason. The text reply repeats the same, naming the affected nodes.
Bundled entities (characters, objects, creatures, locations) are re-created
under the caller, and both the entity nodes and every @-chip — in the graph or
in the workflow’s freeform settings — are re-pointed at the new rows. URLs in
settings follow the copies the graph and the entities paid for, but never
trigger a copy of their own. An entity’s images are copied into the caller’s own
storage even when they already sit on this instance — they are the exporter’s
bytes — so the copies count against the caller’s quota; assetIdMap maps each
bundled entity id to the row created for it, and assetsSkipped names any
entity the quota left uncreated (the workflow still lands).
run_workflow
Runs a saved workflow from the mcp project. Returns an execution_id and
registers an async task for progress tracking.
Scope: workflows:execute
Input:
| Field | Type | Notes |
|---|---|---|
workflow_id |
UUID string | Must be in the mcp project |
client_request_id |
string | Optional retry token (8–128 chars of letters, digits, _ - . :). Reuse the same value when retrying after a timeout or dropped connection so the run is not started or charged twice; use a fresh value for a new run |
inputs |
object | Optional; per-node input overrides keyed by node id |
Response: { executionId: "...", name: "..." } — use executionId with
the jobs/executions tools or the SDK to poll for completion. MCP clients that
support the tasks/* API and widget rendering will show live progress inline.
Prompt tools
AI assistance for writing prompts for generation nodes. All three delegate to
POST /v1/prompt-helper/wizard (the same endpoint as the SDK
client.promptHelper and the CLI nodaro prompt commands) and reserve credits
per call.
Scope (all three): workflows:execute
analyze_prompt
Turns a rough idea into guided questions with options for a target node type
(e.g. generate-image, image-to-video, generate-music). Pair with
generate_prompt.
Input:
| Field | Type | Notes |
|---|---|---|
nodeType |
string | Required. Target node type. |
prompt |
string (max 5000) | Optional. The rough idea. Omit to build from scratch. |
provider / style / aspectRatio / duration / llmModel |
— | Optional. |
advanced_mode / temperature / max_tokens |
— | Optional. Gemini models only — runs on the provider’s own API so the sampling levers and the full reasoning range actually apply. Bills one credit tier up; another model returns 400 advanced_mode_unsupported. |
Response: { jobId, questions } — each question is
{ category, label, options[], selected, allowCustom, multi? }.
generate_prompt
Builds a single optimized prompt from analyze_prompt selections.
Input:
| Field | Type | Notes |
|---|---|---|
nodeType |
string | Required. |
selections |
array | Required. One { category, value, isCustom } per answered question. |
originalPrompt |
string (max 5000) | Optional. Woven into the result. |
provider / style / aspectRatio / duration / llmModel |
— | Optional. |
advanced_mode / temperature / max_tokens |
— | Optional. Gemini models only — runs on the provider’s own API so the sampling levers and the full reasoning range actually apply. Bills one credit tier up; another model returns 400 advanced_mode_unsupported. |
Response: { jobId, prompt, recommendedModel? }.
enhance_prompt
One-shot “improve this prompt” — rewrites a rough idea into one optimized prompt with no questions round-trip.
Input:
| Field | Type | Notes |
|---|---|---|
nodeType |
string | Required. |
prompt |
string (max 5000) | Optional. The rough idea to improve. |
provider / style / aspectRatio / duration / llmModel |
— | Optional. |
advanced_mode / temperature / max_tokens |
— | Optional. Gemini models only — runs on the provider’s own API so the sampling levers and the full reasoning range actually apply. Bills one credit tier up; another model returns 400 advanced_mode_unsupported. |
Response: { jobId, prompt, recommendedModel? }.
Image generation tools
Scope (all): workflows:execute
| Tool | Description |
|---|---|
generate_image |
Text-to-image generation. Accepts prompt, model, aspect_ratio, resolution, quality, negative_prompt, reference_image_urls (up to 14 URLs or asset ids for identity/style/composition guidance — the response text confirms how many were attached), and optional structured fields. Advanced callers can also pass connected_references (the editor’s structured wired-reference shape) + reference_order — labeled/ordered references the route assembles into @image_N directives and {image:N} token resolution — and described_references (up to 10 {name, description} entries for a subject you can name but have no picture for: no url, nothing attached, each rendered as a <Name> — <description>. line so a name in your prompt reaches the model as a described subject). Also accepts presetId (from list_node_presets) to apply a built-in or saved preset’s config server-side; any explicit field above overrides the preset, and prompt may be omitted when the preset supplies one. A preset’s promptPrefix / promptSuffix wrap your prompt. |
modify_image |
Image-to-image transformation — apply a style, change colors, swap backgrounds. Accepts image_url, prompt, and strength controls. |
image_to_image |
Structural image-to-image (i2i) using a dedicated i2i model. Distinct from modify_image in that it uses models optimized for structural transfer. Supports multi-reference composition via reference_image_urls (up to 13). |
edit_image |
Targeted edits: remove background, upscale, inpaint (nano-banana-edit), or Grok task-chained ops — free segment maps (grok-2-segment) and region-targeted edits (grok-2-edit) of a prior grok-2 generation. |
generate_mask |
Generate or refine a segmentation mask for inpainting workflows. |
image_collage |
Composite 2–30 images into one 2K/4K image with a smart (justified) or grid layout — no image is ever cropped (smart floats the output height; grid letterboxes). Accepts images[] (url or asset_id, each with an optional size hint: 0 auto / 1 big / 2 medium / 3 small — relative sizing for the smart layout), layout, resolution (default 4K), aspect_ratio (any W:H, default 4:3), gap, background_color. For storyboards it also accepts a per-image label (caption shown after the number, ≤ 80 chars) top-level numbered (stamp 1-based sequence numbers at each image’s corner in images order) and badge_position (top-left, the default, or top-right). |
image_overlay |
Place 1–12 layers on a base image, pixel-exactly — local, deterministic, no AI. Base as image_url or image_asset_id; each layers[] item has a kind (image — url or asset_id; text — a text object: content, fontId, fontWeight, fontSize as % of base height, colour, align, outline, background box; qr — a qr object; shape — a shape object: rect / rounded / pill / circle / ribbon / triangle / diamond / hexagon / star / burst / arrow) plus anchor (9 positions, default center), x / y (offset in % of the base width / height; negative on a right / bottom anchor moves inward), width (% of base width, default 25; height follows the layer’s aspect unless height is set), opacity, rotation (degrees), blend (over / multiply / screen), fit, shadow, rounded_corners, z_index (stacking order; default = array order). Optional canvas (width, height, background_color) + base_fit change the output size; variants renders extra platform sizes (any of the 12 platform ids, all at once if you like; 2 credits each on top of the 10-credit base) and the job’s output carries them as variants[] ({ id, label, width, height, url }); qr_text fills every QR layer with qr.fromInput: true (the node’s QR link handle — a List column gives one code per row); mask_mode (around default / layers / outside / none) + mask_spread shape the mask the job also emits as maskUrl (white = may change — the ring an AI finish repaints); the output also carries width / height; output_format png (default) / jpg / webp. SVG logos are rasterised crisp at the target size. |
suggest_overlay_placement |
Ask a vision model WHERE one overlay layer should sit on a base image (image_url or image_asset_id): it reads the picture and keeps the element off the faces, the subject and the busiest texture. Answers anchor, x / y and width in image_overlay’s own percent units plus a one-sentence reason — apply it by passing those values on a layer to image_overlay; nothing is composited here. Optional intent (what the element is, in words), layer_aspect (its width / height, 1 = square) and safe_area (x, y, w, h as fractions of the canvas — a platform preset’s always-visible region, which the placement is kept inside). Billed as one image-to-text call. |
image_to_text |
Extract a text description (caption/transcription) from an image using a vision model. Accepts llmModel, reasoning_effort, and the Advanced-mode trio (advanced_mode / temperature / max_tokens) — Advanced mode is Gemini-only and bills one credit tier up. |
generate_script |
Generate a short video script from a prompt (LLM-backed; outputs scene-by-scene copy). |
save_image_defaults |
Persist preferred model, aspect_ratio, and quality values so they become the defaults for subsequent generate_image calls in the same session. |
Video generation tools
Scope (all): workflows:execute
| Tool | Description |
|---|---|
generate_video |
Text-to-video generation. Accepts prompt, model, duration, aspect_ratio, resolution, sound, negative_prompt, seed, and optional structured fields. Advanced callers can also pass connected_references + reference_order (structured wired-reference shape) for labeled/ordered references on reference-capable models (Seedance 2, Gemini Omni, VEO 3.1 Fast / Lite, Kling 3 Omni, Grok i2v, HappyHorse Ref2V — not VEO 3.1 Quality, which has no reference-to-video mode), and described_references (up to 10 {name, description} entries for a subject you can name but have no picture for — no url, nothing attached, rendered as a <Name> — <description>. line). reference_video_captions describes the clips you attached: one caption per reference_video_urls entry in the same order, rendered into the prompt as @video_N: <caption>. — the seat to say what a reference clip is FOR and what to ignore (a Scene3D clay render needs exactly that; see 3D scenes). Captions past the last attached clip are dropped rather than binding a seat the model never receives. Also accepts presetId (from list_node_presets { nodeType: "generate-video" }) to apply a built-in or saved preset’s config server-side; any explicit field above overrides the preset, and prompt may be omitted when the preset supplies one. To animate from a still or use start/end frames, use animate_image. A preset’s promptPrefix / promptSuffix wrap your prompt. |
animate_image |
Image-to-video animation — bring a still image to life. Accepts image_url / image_asset_id, optional prompt, model, duration, aspect_ratio, sound, and end_frame_url (start/end-frame animation). Advanced callers can also pass connected_references + reference_order for labeled/ordered identity references, and described_references for a named subject with no picture (rendered as a <Name> — <description>. line, nothing attached). |
extend_video |
Extend an existing video clip forward in time. Accepts video_url, prompt, model, duration, and (seedance-2-extend only) reference_image_urls — up to 8 reference images, mentioned as @image_1…@image_N in the prompt; one Seedance reference seat is reserved for the continuation anchor. |
loop_video |
Create a seamless looping clip from a short video segment. Accepts video_url and optional loop-trim parameters. |
modify_video |
Video-to-video transformation — apply a style or prompt transformation to an existing clip. Accepts video_url/video_asset_id, prompt, model, resolution, seed plus per-model levers (duration, aspect_ratio, audio, multi_shots, reference_image_url). seedance-2-5 is a whole-clip EDIT: your prompt is sent as edit @video_1 as follows: …, the result keeps the source clip’s length and aspect ratio (clip must be 4–30 s), and reference_image_urls (up to 30) attaches images you cite positionally as {image:1}, {image:2} in the prompt. It is billed like a Generate Video Seedance 2.5 reference-video run — input + output seconds on the -ref ladder, reserved for the longest clip and settled to the delivered length (see Video to Video). |
relight_video |
Relight & switch/composite a clip from its own pixels (Beeble SwitchX). Accepts video_url/video_asset_id + prompt and/or reference_image_url, alpha_mode (auto/fill/select/custom), mask_url, alpha_keyframe_index, max_resolution (720/1080), seed. |
trim_video |
Trim a video to a start/end timestamp. Accepts video_url, start, end. |
combine_videos |
Concatenate multiple video clips with optional transitions. Accepts video_urls[], transition, transition_duration. |
assemble_narrated_video |
Fit N ordered (clip, voice) blocks into one narrated MP4 — a shorter voice is centered over its clip with silence padding, a longer voice slows the clip to fit (capped, holding the last frame beyond the cap); audio is never cropped. Accepts blocks[] (1–60, each video_url/video_asset_id + optional audio_url/audio_asset_id), voice_volume (default 100), clip_audio_volume (default 40), max_slowdown (default 1.5), trim_start_frames, trim_end_frames. |
merge_video_audio |
Merge a video track and an audio track into a single output file. |
still_to_video |
One still image + one audio track → MP4 (local FFmpeg, zero credits). The output length is the audio’s length — no duration parameter. Optional motion (zoom / pan / ken-burns) + intensity, resolution, aspect_ratio, fps, fit/pad_color. |
gif_to_video |
Animated GIF → H.264 MP4 (local FFmpeg, zero credits). Bridges a GIF into the video pipeline as a motion reference for models that reject GIF input (e.g. Seedance). Accepts gif_url/gif_asset_id; optional loop_to_minimum + target_duration (seam-aware looping), interpolate, alpha_background. |
slideshow |
2–100 images + one optional audio track → MP4 slideshow (local FFmpeg, zero credits). Audio-anchored timing (equal split / image_durations pins with disclosed proportional scaling); silent without audio. transition + transition_duration, motion incl. alternate, resolution/aspect/fps/fit levers. |
add_captions |
Burn subtitles/captions onto a video. Accepts video_url and caption style options. Kinetic styles (word-highlight, karaoke, tiktok-words, word-pop, bouncy) take a look preset — outline (Montserrat 900, UPPERCASE, black outline, yellow spoken word — the TikTok read) or clean — where on the kinetic styles an UNSET look renders as outline. The styling levers font_family, font_weight, stroke_color/stroke_width, uppercase, position_y and look now also apply to the static subtitle style (a styled subtitle renders via Remotion and bills at the kinetic price; a bare plain-text subtitle stays on the cheap FFmpeg path). Only highlight_color (the spoken-word colour) and animate stay kinetic-only and are rejected on subtitle. animate (default true): set false to freeze the per-word motion while keeping grouping, line-holding and the highlight colour (set highlight_color=color too for a fully static line). segments[] applies different treatments to non-overlapping time ranges in one call (a segment that names its own look does not inherit the top-level explicit levers). |
extract_frame |
Extract a single frame from a video at a given timestamp. Returns an image URL. |
lip_sync |
Drive lip-sync on a video or portrait image from an audio track. Accepts video_url / image_url + audio_url, plus model (kling-avatar, kling-avatar-pro, infinitalk, omnihuman-1-5, seedance-2(-fast), minimax-h3, latentsync, wav2lip, video-retalking, sadtalker), prompt, resolution, and (omnihuman-1-5) seed / fast_mode. |
speech_to_video |
Generate a talking-head video from a portrait + speech audio. |
motion_transfer |
Transfer the motion pattern from one video onto a target image or video. |
face_swap |
Swap a face in a source image/video with a reference face. |
video_upscale |
AI upscale a video to a higher resolution (powered by Topaz via KIE). |
stop_video_pro |
Gracefully stop a RUNNING generate-video-pro job (the segmented long-video engine): the in-flight segment is abandoned (still billed), the rest are skipped, everything completed is stitched into the job’s final video, and the untouched reserve refunds. A not-yet-started job is cancelled with a full refund. Accepts job_id. |
continue_video_pro |
Continue a stopped / failed / completed generate-video-pro run as a NEW job — delivered segments below from_segment (1-based; default = first missing) are reused, the rest regenerate; billed only for the regenerated part. Accepts job_id, from_segment?. Returns the new job id. |
video_analysis |
Scene-by-scene analysis of a video for AI re-creation — ≤8s scenes with prompt-ready visualResolved descriptions, layered audio, and castable entity slots. Exactly one source: video_asset_id / video_url / youtube_url (max 10 minutes, no live streams). See video_analysis below. |
video_audit |
Re-watch a video against its analysis and fix what’s wrong — a fix-and-disclose pass: corrections are applied under guards and every one is reported, nothing is silently rewritten. Pass analysis from a prior video_analysis/video_audit call to re-verify it, or omit it to auto-run a fast analysis first. See video_audit below. |
silence_detect |
Detect the silent ranges in a recording — one ffmpeg pass over the source’s audio, no transcript and no pixels. audio_url accepts an audio OR a video source. Tune threshold_db (dBFS, at or below 0), min_silence_ms, pad_ms. Returns a job id — the silence result is the job’s output_data.json ({ ranges, durationMs }); pass THAT object (not the whole output_data) as plan_edit’s silence, or read ranges for a hand-cut EDL. |
apply_edl |
Render an edit-decision list (EDL) into a finished cut. Pass edl (object or JSON string) — the plan from a plan_edit step, or hand-written to the @nodaro/shared Edl contract (integer-ms segments on a master clock, each naming a sources[].id; a video render needs a video source on every segment). Media resolves from each source’s url; sources optionally overrides those URLs positionally. output: video (default) or audio; optional transcript is remapped through the cut. A malformed EDL is rejected up front naming the offending segment and rule. Returns a job id — the rendered file is the job result. Priced per rendered minute. |
plan_edit |
(Cloud only) Turn a timed transcript into an edit-decision-list (EDL) plan for a recording — mode: tighten (clean up the whole recording), clips (find N short clips), or chapters (mark chapters with titles). Reads the transcript, never pixels; pass 1–6 media sources. Returns a job id — the EDL plan is in the job’s output_data, ready to feed an Apply EDL render. |
get_recast_authoring_skill |
(Cloud only) The authoring guide for writing a movie as JSON — the preferred lane for end-to-end “make me a video of X” requests. Generated from the platform’s own planner doctrine. Ungated. See Recast authoring. |
validate_recast_script |
(Cloud only) FREE validation of an authored script; returns { valid, errors (path+hint), warnings } for the repair loop. Ungated, never charges. |
import_recast_script |
(Cloud only) Turn a validated script into a real recast project (visible at recast.nodaro.ai). Free. Requires rights_attested: true, which must reflect the user’s own confirmation of ownership — authored recasts render Faithful, exactly as written. workflows:write. |
start_recast |
(Cloud only) Quote (no confirm) then render (confirm: true after the user accepts the credits) an imported recast; called again it advances a planned or interactive run. Pass interactive: true to choose the cast at pick-1-of-3 gates (priced surcharge — it rides the quote). Optional anchor_mode picks the keyframes anchor discipline — "progressive" (each part’s start still chains off the previous render) or "none" (no frame conditioning; the quote drops the anchor-still surcharge); omitted, the server default applies. workflows:execute. |
resolve_recast_gate |
(Cloud only) Record the user’s pick at an interactive gate (cast / identity sheet / scene stills / music) and advance the run — the pick is free, pure state. picks serves the two pick-1-of-3 gates: bare it answers the CAST gate; with gate: "sheet" it answers the identity-sheet gate (person slots only, opens after the cast pick — the face panel is identical across the 3 sheets, so the pick chooses body & wardrobe). finish_auto: true resolves every remaining gate with the critic’s top candidate. workflows:execute. |
get_recast_status |
(Cloud only) Progress of a recast run — planning / planned / generating (segments, live preview) / completed (result URL) — plus the recast.nodaro.ai deep link. workflows:read. |
get_studio_production_skill |
(Cloud only) How to author and operate a Nodaro Studio production — the lane for “make me a film/short/ad of X” when the user wants scenes they can keep editing at studio.nodaro.ai. part: operating (the tool map, the loop and the edit vocabulary — the default), authoring (the plan format), catalog (every picker/model/enum), schema (the JSON Schema). Ungated, free. |
validate_studio_plan |
(Cloud only) FREE validation of an authored nodaro-studio-production plan; returns { valid, errors (path+message), warnings, summary }, where the summary says how many cast names bound to a row in the user’s own library. Never charges, persists nothing. workflows:read — it resolves every cast name against the caller’s own characters, locations, objects and creatures, exactly as its route does. |
list_studio_productions |
(Cloud only) The user’s studio productions, newest first — id, name, version, thumbnail, shared flag and scene count. Archived rows are hidden, as on the dashboard. Pages with cursor. workflows:read. |
get_studio_production |
(Cloud only) One production: film look, cast, folders, cuts, bin, what is running, and its scenes in timeline order. The keys are the document’s, the user’s words are not: a shots[] entry is a scene to them, its still the scene’s frame, its clip its motion, and the shots they talk about are the beats[] inside a motion — see the two vocabularies. detail: "summary" (default) is counts + each scene’s current frame; "full" adds every past result with its restore context. shot_id narrows to one scene. Address a result by its key (job id, or url when no job made it) — never by position. THIS READ IS ALSO THE WRITE: with workflows:write it first lands whatever has finished since the last read, and it is the only step that does — get_job / wait_for_job report a job’s status and land nothing, so a job that says completed is not in the film until you read it here. workflows:read. |
plan_studio_export |
(Cloud only) What exporting a production would run, and what it would cost — the ordered steps plus a credit estimate. Starts nothing and charges nothing: the quote to show the user first. upscale: true adds the 4K pass. workflows:read. |
create_studio_production |
(Cloud only) Create a production in the user’s own Studio project — visible at studio.nodaro.ai immediately. With a plan, every scene, cast binding and film look lands with it; without one, an empty production. Free: it writes a document, it generates nothing. workflows:write. |
import_studio_production |
(Cloud only) Add a validated plan’s scenes to a production that already exists — the “Add scenes” lane. Appending adds scenes and enrolls whoever is new in the cast; it never renames, re-briefs or re-looks the production. Takes plan, or plan_job_id of a FINISHED llm-structured run whose schema is studio_production (a running one is refused with not_finished). Free. If the user has the production open in the studio editor, that tab writes the whole document back on a debounce and overwrites an append — ask them to reload the editor before the import and again after. workflows:write. |
edit_studio_production |
(Cloud only) Change a production by sending a batch of 1–100 operations — rename a scene (rename_shot: operation names are the document’s), reorder the timeline, select a take, set the shots inside a scene’s motion (set_beats), enroll a cast member, empty the bin. The operation vocabulary and its argument shapes live in get_studio_production_skill (part: "operating"). Applied atomically under a compare-and-swap: a refused operation is answered with its index and nothing is written, and a batch composed against a slightly older version still applies (rebased: true says it did). expected_version + strict: true refuses instead of rebasing. Free. workflows:write. |
share_studio_production |
(Cloud only) Publish a production to a share link, or take it back private (shared: false). Publishing makes it readable by anyone holding the link, so ask the user first — the tool is marked as a publish action. Reversible, and the only way sharing changes: no edit operation can touch it. Free. workflows:write. |
clone_studio_production |
(Cloud only) Copy a production — the user’s own, or one shared with them — into their Studio project. The copy starts private and un-archived and carries the graph and every landed result. Free. workflows:write. |
describe_studio_production |
(Cloud only) Hand a brief to the Director and let it write scenes, cast and looks into an existing production. Costs an LLM run, not a render; returns a job id and marks the production; the draft is written into the document by your next get_studio_production and by nothing else (get_job / wait_for_job land nothing). mode: append (default) or replace. Needs both workflows:write and workflows:execute. |
generate_studio_still |
(Cloud only) Generate a scene’s frame (the document’s still): count candidate images from what the scene already says, plus per-call overrides. Spends credits per candidate — dry_run: true prices it and starts nothing. Returns job ids; a finished image joins the scene’s takes only on your next get_studio_production (get_job / wait_for_job report status and land nothing). Generating again ADDS takes, it never replaces one. Needs both workflows:write and workflows:execute. |
generate_studio_keyframe |
(Cloud only; requires a backend with dependent-frame support) Generate one candidate for a planned frame (a keyframe, keyframe_id — not a scene’s frame, which is generate_studio_still) at expected_revision. A derived frame requires an accepted parent. Description-only cast works without portraits; generating a portrait later does not change that choice. Spends credits; quoting is unavailable and dry_run: true is rejected before submission. The candidate reaches the frame only on your next get_studio_production (get_job / wait_for_job land nothing), and landing it neither accepts it nor starts another frame. Accept explicitly through edit_studio_production after review. Needs both workflows:write and workflows:execute. |
generate_studio_clip |
(Cloud only) Generate a scene’s motion (the document’s clip) from its frame, start/end frames and direction; the lane is chosen from the inputs unless mode forces one. Spends credits — dry_run: true prices it and starts nothing. Returns a job id and marks the scene as rendering; the finished take reaches the scene only on your next get_studio_production (get_job / wait_for_job land nothing). Framing and directing can be in flight at once. Needs both workflows:write and workflows:execute. |
new_studio_shot_from_frame |
(Cloud only) Grab a frame out of a scene’s current motion and put it to work — target: "new-shot" (default) opens the next scene on it, "start-frame" / "end-frame" pin it as this scene’s endpoint, "still" adds it as a take of its frame. mode: first / last / timestamp (with timestamp in seconds). Costs a frame extraction; the route waits and answers with the updated production. Needs both workflows:write and workflows:execute. |
voice_studio_shot |
(Cloud only) Speak a line over a scene — the voiceover lane. Give the text; pick a voice_id from list_voices or let the scene’s own voice settings stand. Costs a text-to-speech run; the route waits and answers with the updated production. Needs both workflows:write and workflows:execute. |
revoice_studio_clip |
(Cloud only) Replace the voices inside a scene’s current motion — the dialogue is re-performed and mixed back over the same picture. Takes a plan naming which speaker gets which voice (see the operating skill). Spends credits and returns a job id; the new mix reaches the scene only on your next get_studio_production (get_job / wait_for_job land nothing). Needs both workflows:write and workflows:execute. |
score_studio_production |
(Cloud only) Write the film a soundtrack from a prompt describing the music — one track for the whole production, not per scene. Spends credits and returns a job id; the track reaches the production only on your next get_studio_production (get_job / wait_for_job land nothing). Needs both workflows:write and workflows:execute. |
Seedance 2 (model: "seedance-2") accepts resolution: "4k" and aspect_ratio: "adaptive" (plus "21:9") on generate_video / animate_image — both fields are free strings, forwarded to the route unaltered. The other variants are resolution-capped: seedance-2-fast and seedance-2-mini are 480p / 720p only (no 1080p, no 4K), while seedance-2-5 spans 480p / 720p / 1080p (no 4K; 1080p added 2026-08-17). seedance-2-5 also trades 4K for length — up to 30s in one call vs 15s — and accepts 30 image / 10 video / 10 audio references. Frame inputs and references coexist — when any reference (image / video / audio) is wired alongside image_url / end_frame_url, the frames become prompt-directed Image N references rather than pinned endpoints; the resolver decides the mode, so there is no toggle. Reference videos are billed unit × (input + output) duration — the per-second -ref rate (see the Generate Video node pricing) is scaled by the probed input-video duration plus the output duration, so longer source clips reserve more.
MiniMax Hailuo 3 (model: "minimax-h3") takes the same reference_image_urls / reference_video_urls / reference_audio_urls fields on generate_video / animate_image with the same 9 / 3 / 3 caps, through the same frames-fold-into-references resolver. Output is resolution: "2K" (default) or "768P" (the cheaper per-second rate) — any other resolution value renders and bills as 2K — and audio is always on. aspect_ratio: "adaptive" is the default (reference / i2v runs); a pure text-to-video call needs a concrete ratio (adaptive renders 16:9). Reference videos are 2–15s each (≤ 15s combined) and bill unit × (input + output) duration at the selected resolution’s per-second rate; input images beyond the first 5 (counting folded frames) add a per-image surcharge; reference audio is free but must accompany an image or video reference.
Wan 3.0 (model: "wan-3" / "wan-3-prime") takes reference_image_urls (≤ 10), reference_video_urls (≤ 5) and reference_audio_urls (≤ 5) on generate_video / animate_image, each reference video and audio clip 1–15 s with a ≤ 15 s combined cap per type. Its references are mutually exclusive with image_url / end_frame_url on the provider’s wire, so — exactly as on Seedance 2 and Hailuo 3 — the platform folds instead of failing: with any reference wired, a start/end frame is appended to reference_image_urls after your own images (their ordinals unchanged) and named in the prompt as the opening/closing frame. The pair is never sent together, and the call is not rejected. duration is a whole number of seconds from 2 to 30 (default 5); with a reference video wired, input duration + output duration must be ≤ 30 s. resolution is "480p" / "720p" / "1080p" — send the lowercase display value (the platform normalizes to the provider’s uppercase enum), and an omitted or unsupported value renders and bills at 720p. aspect_ratio defaults to "adaptive"; the model’s set is adaptive / 16:9 / 4:3 / 1:1 / 3:4 / 9:16 (no 21:9). Audio is on by default and can be switched off. Reference-video runs bill output seconds only — no input-duration surcharge. wan-3-prime is the high-speed SKU: faster, priced above wan-3, identical schema.
Gemini Omni Flash (model: "gemini-omni-flash") is the cheaper, faster sibling of gemini-omni-video on an identical request shape: the same image_urls reference surface under a 7-unit quota (each image 1 unit, a source video 2), the same video-edit mode through the same handle, duration one of "4" / "6" / "8" / "10" (an omitted duration renders and bills as 8 s), aspect_ratio restricted to "16:9" or "9:16", and resolution "720p" / "1080p" / "4k" (4K is not available on the free tier). Like the Pro SKU it forwards no audio_ids: the model still generates its own audio track (steer it in the prompt), but there is no platform-managed voice on this path, so both SKUs are excluded from character voice.
video_analysis
Scope: workflows:execute
Analyze a video into a scene-by-scene breakdown built for AI re-creation.
Scenes are cut at natural boundaries, each at most 8 seconds (one
image/video generation per scene). Every scene carries visualResolved — a
self-contained, prompt-ready visual description and the field downstream
consumers read — plus shot type, camera movement, an array of concurrent
audio layers (speech quoted verbatim; music/sfx as generation-ready
descriptions; an empty array [] means silence), and recurring
people/objects/places extracted as castable entity
slots so they can be re-cast with your own characters. Returns a job_id —
poll get_job; the full analysis JSON (meta + slots + scenes[]) is in
the job’s output_data.
Input:
| Field | Type | Description |
|---|---|---|
video_asset_id |
uuid, optional | Nodaro video job id or uploaded-asset id. |
video_url |
string, optional | Direct URL of a video file. |
youtube_url |
string, optional | YouTube video URL (youtube.com / youtu.be). |
llm_model |
enum, optional | Analysis quality tier: fast (economy), pro (default, higher fidelity), or mixed / mixed-fast (advanced tiers — maximum completeness and accuracy). |
selection_mode |
enum, optional | Result strategy: choose (default — standard result) or combine (enhanced, verified result with maximum detail; slightly slower, recommended). |
variations |
boolean, optional | Cast-variations opt-in: the analysis also detects per-entity appearance looks — a plain wardrobe change between scenes counts exactly as much as a dream / flashback / disguise / era look — and binds each look to its scenes (slots[].variations + scenes[].slotVariations). Default false: the result keeps the pre-variations shape. |
music_video |
boolean, optional | Declare the clip a music video: the song IS the piece, so all sung lyrics are transcribed verbatim as per-scene speech layers (the instrumental bed stays its own music layer). Default false: soundtrack vocals nobody on screen performs are folded into the music layer’s description, and speech carries only words uttered inside the story world. |
translate_speech_to_english |
boolean, optional | Spoken and sung words come back in English. Default false: speech is quoted verbatim in the language actually spoken. Independent of the on-screen-text flag. |
translate_on_screen_text_to_english |
boolean, optional | Signs, captions, and titles come back in English (they live in visual, the generation prompt — a regenerated shot renders the English wording). Default false: transcribed verbatim in the original script. Brand, product, person, and place names keep their original form under both flags. |
analysis_focus |
string ≤2000, optional | Steer the analysis (e.g. “focus on the product shots and on-screen text”). |
Pass exactly one of video_asset_id / video_url / youtube_url —
passing zero or more than one returns a tool error naming what was provided.
Maximum duration is 10 minutes (600s) for any source; YouTube live streams
are rejected.
Pricing — duration-bucketed credits per quality tier. The bucket is the smallest of 60s / 180s / 360s / 600s that fits the video’s probed duration. The values below are the shared pricing formula’s current outputs:
| Tier | ≤60s | ≤180s | ≤360s | ≤600s |
|---|---|---|---|---|
fast (economy) |
180 | 185 | 514 | 846 |
pro (default) |
215 | 231 | 636 | 1050 |
mixed / mixed-fast |
268 | 289 | 724 | 1169 |
smart (highest accuracy) |
410 | 500 | 1259 | 2064 |
The live tool description carries these same numbers — it is generated from the shared pricing table at server start, so it is always current. This table is hand-maintained; if the two ever disagree, the tool description is right.
video_audit
Scope: workflows:execute
Re-watch a video against its analysis and fix what’s wrong — a fix-and-disclose
pass, not a silent rewrite. Corrections are applied under guards and every one
is reported: the job’s output_data carries a disclosed report of what was
checked, what changed, and what was left open (flagged, not auto-fixed).
Returns a job_id — poll get_job for the report.
Input:
| Field | Type | Description |
|---|---|---|
video_url |
string, required | Direct URL of the video to audit. |
analysis |
object, optional | The analysis JSON (meta + slots + scenes[]) from a prior video_analysis or video_audit call, passed through verbatim. Wiring this prices the cheaper video-audit family; omit it and the tool auto-runs a fast analysis first (the pricier video-audit:auto family). |
Pricing — duration-bucketed credits, selected by whether analysis was
passed. The bucket is the smallest of 60s / 180s / 360s / 600s that fits the
video’s probed duration. The values below are the shared pricing formula’s
current outputs:
| Family | ≤60s | ≤180s | ≤360s | ≤600s |
|---|---|---|---|---|
video-audit (analysis wired) |
213 | 289 | 659 | 1066 |
video-audit:auto (no analysis — auto-runs one first) |
393 | 474 | 1173 | 1912 |
The live tool description carries these same numbers — it is generated from the shared pricing table at server start, so it is always current. This table is hand-maintained; if the two ever disagree, the tool description is right.
Audio generation tools
Scope (all): workflows:execute
| Tool | Description |
|---|---|
generate_music |
Text-to-music generation (Suno via KIE). Accepts prompt, genre, mood, duration, model — suno-v6 (default; greater musical expression, more natural vocals, richer details), suno-v6_wild (bolder, more distinctive, less predictable), suno-v6_mini (lightweight and fast), suno-v5_5 (alias suno-v5-5), suno-v5, suno; minimax for short instrumental loops. Also accepts presetId (from list_node_presets { nodeType: "generate-music" }) to apply a built-in or saved preset’s config server-side; any explicit field above overrides the preset, and prompt may be omitted when the preset supplies one. A preset’s promptPrefix / promptSuffix wrap your prompt. |
generate_speech |
Text-to-speech. Accepts text, voice_id, model. Supports ElevenLabs v3 (default), turbo, and multilingual v2. Also accepts presetId (from list_node_presets { nodeType: "text-to-speech" }) to apply a built-in delivery preset (speed/stability/style) server-side; explicit fields override it, and text is always required (presets tune delivery; a preset’s promptPrefix / promptSuffix wrap your text). |
generate_dialogue |
Multi-speaker dialogue as ONE audio file (ElevenLabs Dialogue v3, direct API). Accepts dialogue — an ordered array of { text, voice_id } lines (premade names or cloned/library UUIDs, mixed casts fine; [audio tags] allowed in line text) — plus optional stability (0 / 0.5 / 1), language_code, seed, apply_text_normalization. Limits: 5,000 chars total across lines, 10 unique voices. Use it instead of stitching per-line generate_speech calls. |
text_to_audio |
Text-to-sound-effect (ElevenLabs SFX). Accepts prompt and optional duration. Also accepts presetId (from list_node_presets { nodeType: "text-to-audio" }) to apply a built-in or saved preset’s config server-side; any explicit field overrides the preset, and prompt may be omitted when the preset supplies one. A preset’s promptPrefix / promptSuffix wrap your prompt. |
list_voices |
List the available premade voices (id + name, plus any gender/accent/description metadata) so you can pick a voice_id for generate_speech, voice_changer, or voice_changer_pro — all of which require a voice id. Read-only; returns the catalog as JSON. |
voice_design |
Design a new synthetic voice from text descriptors (ElevenLabs /v1/text-to-voice/design). Accepts text, voice_description, model (default eleven_ttv_v3; eleven_multilingual_ttv_v2 is the legacy model), loudness, guidance_scale, seed, quality, should_enhance. Returns a voice_id. |
voice_changer |
Transform the speaker identity in an audio clip — or a whole talking video — to a target voice. Accepts audio_url/audio_asset_id or video_url/video_asset_id (video is demuxed, revoiced, remuxed), voice_id (premade name or clone UUID; required), model, stability, similarity_boost, style, remove_background_noise. |
voice_changer_pro |
Detect each speaker in a multi-speaker clip and convert each to a chosen voice, preserving words and timing (Cloud only). Accepts audio_url/audio_asset_id or video_url/video_asset_id; ordered_voices (required, positional: speaker N → entry N; each entry a voice id, a per-voice settings object with engine ("sts" default recast / "v3" Re-speak — regenerates the performance from the transcript with eleven_v3, [audio tags] supported, stability 0/0.5/1 only), stability/similarity_boost/style/use_speaker_boost/seed/volume_mode/volume, or null); analysis (a prior analyze run’s output_data — the recast works from the exact speaker list you mapped against; its segments[].text is the required transcript for a "v3" speaker, and omitting analysis re-speaks from the engine’s own transcription); voice_fx (preset + wet_dry_mix/delay_ms/decay); model; preserve_background; separation_quality (fast/best); music_volume_mode (match/normalize/manual) + music_volume; remove_background_noise; output (video default / stems). A null entry in ordered_voices is a keep-slot — that speaker keeps their original voice while later speakers are still recast. output: "stems" returns the dry per-track stems for interactive mixing instead of a finished video. |
voice_changer_pro_analyze |
Detect the speakers in a clip WITHOUT recasting (Cloud only) — the first step of the interactive flow. Accepts audio_url/audio_asset_id or video_url/video_asset_id, separation_quality, suggest_title. The job output carries the separated stems + the detected speaker list (id, segments, first-appearance, word count, snippet) + language — inspect it to choose each speaker’s voice (and spot non-person “speakers” like applause) before committing to a recast. |
voice_changer_pro_export |
Render a finished video from a mixed set of stems (Cloud only) — the last step of the interactive flow. Accepts video_url/video_asset_id (the source video) + tracks (stem url, gain 0–200, muted, kind voice/background; ≤16, at least one un-muted) + optional voice_fx, which lands on the voice tracks at render time. Stream-copied (never re-encoded). |
voice_remix |
Re-stylize or re-arrange an existing audio clip. |
dubbing |
Dub audio OR video into a target language with voice preservation. One source: audio_url/audio_asset_id, video_url/video_asset_id (delivers the dubbed VIDEO + audio track), or source_url (public YouTube/TikTok/direct link ElevenLabs fetches itself). Options: num_speakers (0=auto), disable_voice_cloning, drop_background_audio, start_time/end_time window, highest_resolution, use_profanity_filter, target_accent, watermark. Priced per minute of the dubbed span; max 30 minutes. |
transcribe |
Speech-to-text transcription on the elevenlabs-stt engine. Returns a transcript, and per-word timings (ms) are always in output_data.json.words — this engine is word-level, so word_timestamps is accepted but changes nothing. Supports diarize and tag_audio_events. To caption a video with your own corrected text, map json.words into add_captions captions[] (one entry per word). |
audio_isolation |
Isolate and clean the primary voice from a mixed clip (removes background music/noise). Returns one clean voice track. |
separate_audio |
Separate ANY audio into vocals + instrumental, or full stems (drums/bass/other/guitar/piano), via Demucs. Works on non-Suno audio. |
apply_audio_fx |
Apply a creative audio effect — scenario reverbs (room/hall/church/cave/arena/outdoor…) to place a voice in a space, plus telephone/megaphone/echo/custom (delay+EQ). |
trim_audio |
Trim an audio file to a start/end timestamp. |
download_youtube_audio |
Download the audio track from a YouTube URL. Returns an audio asset URL. |
Suno music tools
All Suno tools require workflows:execute.
| Tool | Description |
|---|---|
suno_generate |
Generate a new song from a prompt or lyrics using Suno (model: V6 default, V6_WILD, V6_MINI, V5_5, V5, V4_5PLUS, V4_5ALL, V4_5, V4). |
suno_lyrics |
Generate song lyrics from a prompt. |
suno_extend |
Extend an existing Suno song clip. |
suno_cover |
Generate a cover version of a song. |
suno_upload_extend |
Upload an audio clip and extend it with Suno. |
suno_music_video |
Generate a music video from a Suno song clip. |
suno_mashup |
Blend two audio clips into a mashup. |
suno_replace_section |
Replace a section of a Suno song with new generated audio. |
suno_style_boost |
Apply a style transfer / boost to a Suno song. |
suno_add_instrumental |
Add an instrumental track to a Suno song. |
suno_add_vocals |
Add a vocal layer to an instrumental track. |
suno_separate_stems |
Separate a song into vocal + instrumental stems. |
suno_convert_wav |
Convert a Suno output to WAV format. |
Character tools
Character tools surface the caller’s saved characters from Character Studio so an LLM client can pick the right asset URL to pass as a reference image into a subsequent generation call.
list_characters
Scope: assets:read
Lists the caller’s characters with summary fields, ordered by most recently updated.
Input: { search?: string, limit?: integer } — search is a case-insensitive substring of the name; limit defaults to 50, max 100.
get_character
Scope: assets:read
Returns full asset detail for one character including every expression / pose / motion / angle / lighting variant with its URL.
Input: { id: uuid }
create_character
Scope: assets:write
Creates a new character row with identity fields. No portrait — call
generate_character (kind="main") afterwards.
Input: name, description, gender, style (realistic/anime/3d-pixar/illustration), base_outfit, seed_prompt, identity_lock (off/soft/strict — face-preservation strength for Studio assets, default off)
update_character
Scope: assets:write
Patches an existing character. Only the fields you supply are written.
Supports optimistic concurrency via expected_updated_at.
approve_portrait
Scope: assets:write
Approves a completed generate_character job as the character’s canonical
portrait. Fires an LLM caption inline to populate canonical_description.
Input: { character_id: uuid, candidate_job_id: uuid }
recaption_character
Scope: assets:write
Re-runs the LLM caption against the character’s current portrait and
persists the new canonical_description.
Input: { id: uuid }
generate_character
Scope: workflows:execute
Generates either a fresh portrait (kind: "main") or an asset variant
(kind: "asset") for a named character. The single tool covers two routes:
POST /v1/generate-character (main portrait) and
POST /v1/generate-character-asset (variants — expressions, poses, head
angles, body angles, lighting, custom).
Input (main): kind, name, description, gender, style, base_outfit, model
Input (asset): kind, name, asset_type, variant, attach_to_character_id, attach_to_column, attach_name, source_image_url
generate_character_motion
Scope: workflows:execute
Animates a character into a motion clip via image-to-video. When
attach_to_character_id is set, the source frame is auto-resolved from
the character row and the resulting clip is appended to the motions[] bucket.
Input: motion_prompt, name, attach_to_character_id, source_image_url, description, motion_description, provider
Location tools
Eight tools for the location lifecycle — identity edits, establishing-shot
generation, atmospheric motion clips, and LLM-captioned approval. Mirrored on
the SDK at client.locations.
list_locations
Scope: assets:read
Summary list (name, main image URL, asset counts, identity copy).
Input: { search?: string, archived?: boolean } — search is a case-insensitive substring of the name; archived lists the archive instead.
get_location
Scope: assets:read
Full detail including all asset arrays + reference photos + pendingJobs.
Input: { id: uuid }
create_location
Scope: assets:write
Create a new row with name + optional description / category / style.
Input: name, description, category, style
update_location
Scope: assets:write
Update identity fields (name, description, category, style,
styleLock, canonicalDescription). Supports optimistic concurrency via
expected_updated_at.
approve_main_image
Scope: assets:write
Approve a completed generate_location candidate as the location’s main
image. Fires the LLM caption inline.
Input: { location_id: uuid, candidate_job_id: uuid }
recaption_location
Scope: assets:write
Re-run the LLM caption against the current main image.
Input: { id: uuid }
generate_location
Scope: workflows:execute
Generate a main image (kind: "main") or a variant asset (kind: "asset" + asset_type + variant).
generate_location_motion
Scope: workflows:execute
Animate the location’s establishing shot into an atmospheric motion clip
(image-to-video). Pass refine_from_video_url to route through video-to-video
for iterating on an existing clip.
Object tools
Six tools for the object (prop / product / vehicle / etc.) lifecycle — listing,
detail, main-image approval, LLM recaption, motion clips, and verb-style
generation.
Mirrored on the SDK at client.objects.
list_objects
Scope: assets:read
Lists the caller’s objects — props, accessories and physical items reused across shots. Each row carries the name,
description, main image and a COUNT of each variant bucket rather than the
asset URLs themselves; call get_object for those. Newest first.
Input: { search?: string, limit?: integer } — search is a
case-insensitive substring of the name; limit defaults to 50, max 100.
get_object
Scope: assets:read
Returns full detail for one object — every variant asset with its name and URL, plus reference photos. Errors if the object is not found or not owned by the caller.
Input: { id: uuid }
generate_object
Scope: workflows:execute
Generate a main image or variant asset for an object. Parallel to generate_character / generate_location.
approve_object_main_image
Scope: assets:write
Approve a completed generate_object candidate as the object’s main
image. Fires the LLM caption inline.
Input: { object_id: uuid, candidate_job_id: uuid } + optional expected_updated_at
recaption_object
Scope: assets:write
Re-run the LLM caption against the current main image.
Input: { id: uuid }
generate_object_motion
Scope: workflows:execute
Animate the object’s main image into a motion clip (image-to-video).
Provider defaults to "kling-turbo", aspect ratio defaults to "1:1".
Pass refine_from_video_url to use video-to-video refinement.
Input: motion_prompt, source_image_url (required), name, attach_to_object_id, provider, aspect_ratio, refine_from_video_url
Creature tools
Six tools for the creature / animal lifecycle — listing, detail, main-image
approval, LLM recaption, motion clips, and verb-style generation. Mirrors the Object tools
with the Animal/Creature delta (free-text species / category / style).
list_creatures
Scope: assets:read
Lists the caller’s creatures — animals and non-human beings with a locked look. Each row carries the name,
description, main image and a COUNT of each variant bucket rather than the
asset URLs themselves; call get_creature for those. Newest first.
Input: { search?: string, limit?: integer } — search is a
case-insensitive substring of the name; limit defaults to 50, max 100.
get_creature
Scope: assets:read
Returns full detail for one creature — every variant asset with its name and URL, plus reference photos and the stored voice. Errors if the creature is not found or not owned by the caller.
Input: { id: uuid }
generate_creature
Scope: workflows:execute
Generate a creature/animal main image (kind: "main") or a variant asset
(kind: "asset" + asset_type + variant). Parallel to generate_object;
species (free text, e.g. "dragon", "wolf") is the creature delta vs
objects.
Input (main): kind, name, description, species, category, style, source_image_url, model
Input (asset): kind, name, asset_type (angles/poses/variations/custom), variant, species, category, style, source_image_url, model
approve_creature_main_image
Scope: assets:write
Approve a completed generate_creature candidate as the creature’s main
image. Fires the LLM caption inline.
Input: { creature_id: uuid, candidate_job_id: uuid } + optional expected_updated_at
recaption_creature
Scope: assets:write
Re-run the LLM caption against the current main image.
Input: { creature_id: uuid }
generate_creature_motion
Scope: workflows:execute
Animate the creature’s main image into an ambient motion clip
(image-to-video). Provider defaults to "kling-turbo", aspect ratio defaults
to "1:1". Pass refine_from_video_url to use video-to-video refinement.
Input: motion_prompt, source_image_url (required), name, canonical_description, category, style, attach_to_creature_id, attach_name, provider, aspect_ratio, refine_from_video_url
Gallery and asset tools
browse_gallery
Scope: assets:read
Browse your gallery or the public gallery. Renders an interactive grid widget in compatible clients.
Input: scope ("mine" default / "public"), limit, cursor, kinds[], query
browse_uploads
Scope: assets:read
Browse assets you’ve uploaded (source files — distinct from generated outputs). Use to retrieve existing upload URLs to feed into generation tools.
Input: kind, limit, cursor
list_favorites
Scope: assets:read
List your favorited gallery items, most recent first.
Input: limit, cursor
get_asset
Scope: assets:read
Fetch metadata for a single asset (job) by id, including output URL, prompt,
provider. Visible for your own jobs (any status) and any user’s public
completed jobs. For a failed job it returns the failure reason plus a
retryable flag, a guidance sentence, and — when the provider’s safety
filter blocked the output and the catalog offers a fallback model —
suggestedProvider. retryable: false (a content-policy block, or a
provider that refused the request outright — see below) means the same request
will fail again unchanged; when suggestedProvider is
present, retry the SAME prompt and references with that model id instead of
guessing at a new one.
A job whose error_message says the provider rejected these settings for
this model is the request-reject case: the provider answered the submission
with a 4xx, so the combination of settings and input media is invalid for that
model. It comes back retryable: false — change the settings or the input
media (duration, aspect ratio, resolution, or the reference image/video/audio)
before re-running, or pick a model whose list_models capability sheet allows
the combination. A provider 5xx is the opposite case and stays retryable,
even when its wording reads like a validation complaint. For a job in pending_review (a deployment’s job
policy held the output for human review) it returns status: "pending_review",
outputUrl: null, retryable: false and a guidance sentence: the status is
in-flight, so keep polling and do not re-run the request — a duplicate
would be held too.
Input: { job_id: string }
display_asset
Scope: assets:read
Render an asset visually in chat (the user sees the media, not JSON).
Renders image, video, and audio assets inline via the universal job-auto
widget; image assets also surface Animate / Edit / Recreate follow-up
buttons and click-to-zoom fullscreen. For purely-programmatic metadata (no
rendering) prefer get_asset.
Input: { job_id: string }
get_app_run
Scope: assets:read
Fetch status of a workflow / published-app execution by id. Returns per-node states and output URLs produced so far. Used by widgets to poll progress.
Input: { execution_id: string }
favorite_asset
Scope: assets:write
Mark or unmark a gallery asset as a favorite.
Input: { job_id: string, favorited: boolean }
Jobs tools
list_jobs
Scope: jobs:read
List your recent jobs with status, job type, and output URL. Supports cursor pagination.
Input: limit, cursor, status, job_type
get_job
Scope: jobs:read
Fetch full metadata for a single job by id, including output_url,
status, progress, provider, and output_data. On a failed or
cancelled job the payload also carries retryable, a guidance
sentence, and — when available — suggestedProvider: see
get_asset for what these mean and when the fallback model
appears.
A job may also report status: "pending_review" on a deployment that registers
a job policy: the output exists but a human is reviewing it. That is an
in-flight status, not a terminal one — keep polling rather than treating it
as a failure. The payload then carries retryable: false and a guidance
sentence saying so: do not re-run the request, since a duplicate would be
held too. The job later resolves to completed (approved), failed
(rejected, with error_hint.kind === "policy-block" and a user-safe
reason) or cancelled.
A client driving the same job through the MCP tasks/* API sees that state as
task status input_required. The decision belongs to a human reviewer, not
to you: do not prompt the user for more parameters and do not re-run the job —
call tasks/result again later, and it completes on approval or fails with a
policy reason if the review rejects it.
Input: { job_id: uuid }
Job envelope (structuredContent): jobId, status, progress, jobType,
assetKind (image / video / audio / null), outputUrl, outputData,
errorMessage, credits, createdAt, startedAt, completedAt, plus
retryable, guidance and suggestedProvider on a failed, cancelled or held
job. get_asset and wait_for_job return the same envelope. Poll every 5–10 s
(an image usually finishes within a minute, a video in 2–10 minutes), or call
wait_for_job to block.
wait_for_job
Scope: jobs:read
Block until one of your jobs finishes and return the job envelope above.
Input: job_id, timeout_s? (seconds to wait, default 60, max 120)
If the job is still running at the deadline the result has status: "timeout"
— it is not an error; call wait_for_job again or poll get_job. A held
job answers pending_review at once (do not re-run it). For a long video
render prefer polling get_job every 5–10 s over repeated waits.
—
diagnose_run
Scope: jobs:read
Diagnose why a workflow run or single job failed. Pass a workflow execution
id or a job id; the tool tries the execution first and falls back to the
job. For an execution it walks node_states, surfacing each failed node with
its error message, provider, and the credits actually charged. Each failure
gets a best-effort class — content_policy, validation, rate_limited,
timeout, post_processing, provider_error, or unknown — and a
remediation hint. Classes are heuristic (derived from the stored error string,
not the error type), so treat them as guidance. Reserved credits are
auto-refunded except for post_processing (post-delivery) failures; check
creditsActual per node.
Input: { id: string } (a workflow execution id or a job id)
Apps tools
list_apps
Scope: apps:read
List published apps. Supports scope: "public" | "mine" and ordering by
recency.
Input: scope, limit, cursor
get_app_inputs
Scope: apps:read
Returns the typed input schema for a published app (the same schema the
published-app page renders). Use this before run_app to learn the
available input keys and their types.
Input: { slug: string }
run_app
Scope: workflows:execute
Run a published app by slug. inputs is a FLAT object keyed by the schema
input keys (from get_app_inputs). Returns an execution_id.
inputOverrides (advanced) sets raw node fields such as promptPrefix /
promptSuffix per run.
Input: slug, inputs?, inputOverrides?, client_request_id? (retry token — reuse it when retrying after a timeout so the run is not started or charged twice)
delete_app_run
Scope: workflows:execute
Soft-delete (archive) a published-app run. The run can be restored or
permanently deleted from the Nodaro web UI at /archived-runs.
Input: { slug: string, runId: uuid }
Component tools
list_components
Scope: workflows:read
List your saved workflow components (reusable sub-graphs). Ordered by most recently updated.
Input: limit, cursor
get_component_inputs
Scope: workflows:read
Returns the typed input schema for a saved component. Use before
run_component to learn available input keys.
Input: { component_id: uuid }
run_component
Scope: workflows:execute
Execute a saved component by id. inputs is a FLAT object keyed by the
component’s input schema keys. Returns an execution_id.
Input: component_id, inputs?, client_request_id? (retry token — reuse it when retrying after a timeout so the run is not started or charged twice)
Models and credits tools
list_models
Scope: none (always visible)
Browse AI models available on this Nodaro instance. Returns grouped JSON
with per-model capability sheets (aspect ratios, resolutions, qualities,
durations, features, and — on editions with a credit system — per-variant
credit pricing; community/business installs omit pricing) and a
recommendations array. Models with model-family prompting guidance (e.g. Seedance 2.0)
also carry a promptTips array — short prompting rules worth applying
before calling generate_video / animate_image — and every model
carries doctrineCovered: true only when a sourced per-family prompt
doctrine exists for it. Gate “vendor doctrine · real rewrite” badges on
that flag and show a generic label otherwise — never overclaim.
Input: kind (image/video/audio), mode, family, featuredOnly
check_balance
Scope: credits:read (cloud edition only)
Returns your current credit balance split by pool (subscription vs
topup, with total = subscription + topup), plus tier and
effectiveTier — "payg" means pay-as-you-go: no subscription, but
purchased credits (all models unlocked, no watermark, no daily cap).
Top-up credits are valid for 12 months from purchase; subscription
credits reset each billing cycle and are spent first.
On a deployment with a billing account (billing.payerAccount in the
surface profile), this tool and credit_transactions refuse a session that
acts as that account through a token — the deployment’s pool balance is
visible only to the billing account’s own browser session and its in-app
Copilot, never to a connected client — with the error
payer_balance_jwt_only. Every other user sees their own figures as usual.
Input: none
credit_transactions
Scope: credits:read (cloud edition only)
Lists recent purchase-ledger rows (subscriptions, top-ups, refunds):
type, amount_usd, credits_granted, tier, created_at, and
receipt_url (the Stripe receipt link, when present). Note this is the
purchase history — per-generation credit spend is a different ledger,
served by REST GET /v1/credits/transactions, not by this tool.
Input: limit, cursor
list_node_presets
Scope: presets:read
List saved node presets — reusable named node configurations. Returns
names, ids, and descriptions for discovery; fetch the full config data via
the REST API / SDK (GET /v1/node-presets, GET /v1/node-presets/factory).
Input:
| Field | Type | Notes |
|---|---|---|
nodeType |
string | Filter to one node type, e.g. "generate-image". Required when source includes factory. |
source |
enum custom / factory / all |
Which presets to return. Default custom (your own saved presets). |
get_node_preset
Scope: presets:read
Fetch ONE preset’s full saved configuration by id — the provider/model, prompt,
aspect ratio, resolution, quality, and negative prompt it ships. Use it to apply
a preset faithfully: get the id from list_node_presets, then either read these
fields and pass them to the matching generate_* tool, or pass presetId
directly to generate_image. Works for built-in (factory) and your own custom
presets. Returns isError when the id resolves to neither.
Input:
| Field | Type | Notes |
|---|---|---|
nodeType |
string | Required. Node type, e.g. "generate-image". |
presetId |
string | Required. Preset id from list_node_presets (factory slug like generate-image/location-board, or a custom uuid). |
Upload tools
All upload tools require assets:write. Three upload strategies are provided
— prefer the one suited to your client environment.
Widget uploads (preferred for Claude.ai web)
| Tool | Description |
|---|---|
upload_image_widget |
Opens an in-chat file picker for images. Supports max_files (1–10). Auto-announces the resulting URL(s) back to the chat. |
upload_audio_widget |
Opens an in-chat file picker for audio. |
upload_video_widget |
Opens an in-chat file picker for video. |
Browser-handoff uploads (works everywhere)
| Tool | Description |
|---|---|
request_image_upload |
Returns an upload_page_url the user opens in their browser to drop the file, plus the deterministic public_url. Works in all MCP clients including Claude.ai web/Android. |
request_audio_upload |
Browser-handoff for audio. |
request_video_upload |
Browser-handoff for video. |
Presigned-URL uploads (CLI clients with unrestricted bash)
| Tool | Description |
|---|---|
prepare_image_upload |
Returns a presigned R2 PUT URL. Stream the file via curl -X PUT --data-binary @file -H 'Content-Type: <mime>'. Use in Cursor / Cline / Claude Desktop / Claude Code only — fails on Claude.ai web/Android. |
prepare_audio_upload |
Presigned upload for audio. |
prepare_video_upload |
Presigned upload for video. |
Pipeline tools
Pipeline tools appear only when your authorization grants the relevant
pipelines:read / pipelines:execute / pipelines:approve scopes (the
enterprise Story-to-Video pipeline engine; Cloud/Business).
| Tool | Scope | Description |
|---|---|---|
branch_pipeline |
pipelines:execute |
Create a branch of an existing pipeline from a given stage. |
start_pipeline |
pipelines:execute |
Start a new Story→Video pipeline from a prompt. Mode "auto" runs end-to-end unattended; "manual"/"guided" pause at approval gates. |
chat_pipeline_stage |
pipelines:approve |
Send a chat message to the Showrunner Refinement Director for a stage awaiting approval (guided mode). Returns the assistant reply and an optional proposed_change JSON Patch. |
apply_chat_proposal |
pipelines:approve |
Accept a proposed edit from a prior chat_pipeline_stage reply and advance the stage to approved. |
get_pipeline_stage_chat |
pipelines:read |
List all chat turns for a pipeline stage ordered by turn number. |
get_pipeline_status |
pipelines:read |
Get current pipeline state: status, current_stage, credit counters, mode, failure_reason. Poll after start_pipeline to track an Auto run. |
pipeline_pending_approvals |
pipelines:read |
List stages currently awaiting approval with their output snapshots. |
Shot-sequence tools
Tools for authoring narrated, time-coded motion-graphics videos (HyperFrames
methodology on the Remotion engine). The execution tools (forced_alignment,
resolve_shot_sequence, render_shot_sequence) require workflows:execute.
The catalog discovery tools (list_shot_shapes, get_shot_shape) are ungated.
list_shot_shapes
Scope: none — always visible (all editions, free).
Return the catalog of all registered shot-sequence blueprints (id, roles, description,
defaultDurationFrames). Blueprints are text/shape only and carry no pricing or
credit information. Use before authoring a ShotSequenceBrief to pick the
right blueprint for each beat role. Zero credits.
Input: none
get_shot_shape
Scope: none — always visible (all editions, free).
Return detailed information for one blueprint: its metadata (roles, description, defaultDurationFrames), a JSON-schema descriptor of the params it accepts, and a filled worked example. Unknown id returns an error with the list of known ids. Zero credits.
Input: id (string) — blueprint id, e.g. "titlecard-reveal". Call
list_shot_shapes to browse all ids.
list_brand_presets
Scope: none — always visible (all editions, free).
Return the catalog of all 8 brand-token presets (id, label, mood, description,
palette summary, fonts). A brand preset is a named palette+font pairing (e.g.
midnight-violet, editorial-cream) passed as the brand param to the video
director so every blueprint accent and text style stays consistent across the
video. Use before authoring a brief that specifies a brand to pick the right
preset id. Zero credits.
Beyond the font family, a preset’s fonts.headingType / fonts.bodyType can
each carry a weight (100–900), a casing ("uppercase" / "lowercase" /
"none"), and a tracking (letter-spacing, in em, -0.2 to 0.5) — independent
levers for headings vs. body text. Precedence: an explicit value on the
element itself wins, otherwise the brand’s headingType/bodyType applies,
otherwise the blueprint’s own hardcoded default. Two edge cases to know before
authoring: letter-spacing is never applied to Arabic text (it breaks cursive
letter joining — Hebrew is unaffected since it doesn’t join), and a weight
only renders if that weight is actually loaded for the chosen font family —
requesting an unloaded weight silently snaps to the nearest one that is
loaded. See Brand Typography Ramp for
the full model.
Input: none
forced_alignment
Scope: workflows:execute
Align a known transcript to an audio clip (ElevenLabs forced alignment),
returning per-word start/end timings. Returns a job_id; the alignment array
is in output_data.alignment. Use the result to drive element reveals in
resolve_shot_sequence.
Input: audio_url or audio_asset_id, transcript
resolve_shot_sequence
Scope: workflows:execute
Bake an authored shot-sequence brief together with forced_alignment word
timings into a render-ready plan. Pure and synchronous — returns the plan
inline (no job). Feed the plan directly to render_shot_sequence.
Input: brief (a ShotSequenceBrief), audio_url, alignment (from forced_alignment)
render_shot_sequence
Scope: workflows:execute
Render a resolved shot-sequence plan to an MP4 on Nodaro’s Remotion engine.
Returns a job_id; in hosts with interactive tool cards (claude.ai),
progress and the finished video render inline in the tool card. The video
is also saved to your Nodaro library.
Input: plan (a resolved ShotSequencePlan from resolve_shot_sequence)
Video Director tools
One-shot tools that author + render a narrated motion-graphics video in a single
call (author → speech → alignment → resolve → render). The director writes the
VO script and shot-sequence brief for you. These tools are the motion-graphics
(typography + shapes) path — for a bare “explainer” ask with no stated visual
style, the tool descriptions instruct the LLM to confirm the method with the
user first; illustrated/animated-footage explainers route to get_recipe →
video-explainer instead. See Video Director
for credit costs, honest Phase-1 limits, and the full brief format.
start_video_director
Scope: none — always visible (all editions, free).
Returns the motion-director doctrine: pick a genre and arc, draft the VO as cue
phrases, build a ShotSequenceBrief, then drive the Phase-0 pipeline yourself.
Idempotent, non-destructive, zero credits.
Input: none
create_explainer
Scope: workflows:execute (Cloud only)
Author and render a narrated, time-coded concept-led explainer video in one
call. Priced as the video-director entry in list_models (authoring,
speech, alignment and render stages; credits vary by deployment). Returns a
job_id.
Input: topic (string, 1–8000 chars) — what the explainer should cover.
create_launch_video
Scope: workflows:execute (Cloud only)
Author and render a narrated product-launch video. Pass brief describing the
product. Passing url without brief returns a deferred-capability message
(real-UI capture is not yet supported). Priced as the video-director entry
in list_models. Returns a job_id.
Input: brief (string, 1–8000 chars), url (string, optional — not yet supported)
Utility tools
reduce
Scope: workflows:execute
Fold a list of candidates into one result — the engine behind the
canvas Choose Best node. Six strategies: pick-best-llm (an LLM
judge picks the best candidate against your criteria — works on texts
or images via inputKind: "text" | "image-url", with an optional
llmModel judge override; economy/standard/premium credit tiers apply),
concat, first-non-empty, count, vote, and merge-json. Pass the
candidates as inputs (up to 1000 strings — text fragments or URLs),
the strategy as strategyId, and its config as strategyConfig. The
judged winner comes back with its reasoning.
ping
Scope: none (always visible)
Returns "pong" plus the authenticated Nodaro user id and the calling MCP
client name. Use to verify the connector is wired up correctly.
Input: none
start_film_director
Scope: none (always visible)
Returns the Film Director skill — a multi-step prompt that instructs the LLM to drive a 10-stage director workflow (script → characters → storyboard → animation → audio → final cut) and assemble an editable Nodaro workflow on your canvas in real-time.
Input: none
start_workflow_editor
Scope: none (always visible)
Returns the Workflow Editor skill — a step-by-step guide instructing the LLM how to create, edit, and run Nodaro workflows via MCP tools.
Input: none
get_node_skill
Scope: none (always visible)
Returns documentation for a specific node type — accepted inputs, outputs, and configuration options — so the LLM can correctly populate that node when building or editing a workflow.
Input: { node_type: string }
get_recipe
Scope: none (always visible)
Discover and load multi-step Nodaro content recipes — curated,
terminal-verb-anchored playbooks (e.g. video-explainer) that walk the LLM
through a full multi-tool flow. Call with no argument to list available
recipes (name, description, trigger phrases); pass recipe to load that
recipe’s full instructions; add file to read a bundled reference file
inside it. Pure content delivery, no side effects — the actions a recipe
instructs the LLM to take are scope-gated by their own tools. The
video-explainer recipe is for explainers told through generated animated
footage; for kinetic-typography/motion-graphics explainers use
start_video_director instead. When the user hasn’t specified a style, the
recipe itself asks (see Content Recipes).
Input:
| Field | Type | Notes |
|---|---|---|
recipe |
string | Recipe name, e.g. "video-explainer". Omit to list all. |
file |
string | Relative path inside the recipe folder, e.g. "references/prompts.md". Requires recipe. |
See Content Recipes for the current catalog and the
RECIPE.md authoring format (frontmatter fields, folder layout, bundled
reference files).
get_picker_catalog
Scope: none (always visible)
Discover the valid values for parameter-picker nodes (setting, mood,
person, action-fx, lens, …) — curated catalogs that contribute a descriptive
clause to a downstream node’s prompt rather than calling the API. Read-only,
idempotent, no side effects. Call it before writing a picker node’s value field
in update_workflow_json so you set a real catalog id instead of guessing.
- No
node_type→ a directory of every picker:nodeType,label,kind(single/multi),valueField(single-dim) orfields(multi-dim), andoptionCount. - With
node_type→ that picker’s catalog of valid ids. An unknown type returns an error listing the valid picker types.
Input:
| Field | Type | Notes |
|---|---|---|
node_type |
string | Picker node type, e.g. "setting" (kebab-case, from start_workflow_editor’s catalog). Omit to list every picker. |
detail |
enum compact / full |
compact (default): id, label, category, term, icon. full: additionally includes each option’s description and promptHint (the prompt fragment it injects). |
category |
string | Single-dim pickers: filter options to one category. |
field |
string | Return only this dimension’s field — multi-dim pickers (person / styling / framing), and the secondary parameters of a single-dim picker (transition / character-fx: position / duration / intensity; character-motion: position / pace). |
Every option carries a term at both detail levels: the short
professional phrase to write into a prompt when you want a compact instruction
("whip pan left"), where label is display-only and promptHint is the full
mechanism sentence. It is "" for a no-op (auto / none) option that injects
nothing — so compact prompt assembly needs no detail: "full" round-trip.
See Parameter Picker Catalogs for the underlying
@nodaro/shared data and the prompt-fragment helpers.
3D scenes
3D scene tools: generate_3d_scene, edit_3d_scene, and render_3d_scene create editable scenes, revise them, and export MP4s.