Clueso
REMOTE · CONNECT.CLUESO.IO · SCANNED SEP 20
Make videos and docs with your AI agent — describe what you need, every output stays editable.
Available components
How this component scores in each security and reliability category. Every signal is checked automatically against the live server, and we only credit what we can confirm. How we score → Why this is hard to score →
Endpoint Security89
- The endpoint's TLS certificate is valid, in date, and uses a strong key. View diagnostics → Pass
- Authorisation is enforced on tool calls, advertised via RFC 9728 protected-resource metadata. Discovery is public, which costs nothing: no tool can be invoked without a token. View diagnostics → Pass
- HTTPS is enforced; there's no plaintext access path. View diagnostics → Pass
- HSTS check failed: the Strict-Transport-Security header is absent. See how to fix → View diagnostics → Fail
- DNSSEC check failed: this domain isn't protected by DNSSEC. See how to fix → View diagnostics → Fail
- The authorisation server offers only Dynamic Client Registration (RFC 7591), which MCP 2026-07-28 deprecated in favour of Client ID Metadata Documents. View diagnostics → Partial
Transport & Reachability100
- Verified streamable-http transport via a live MCP handshake. View diagnostics → Pass
Schema Quality & AI Usability76
- 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).Pass
- AI-judged instruction clarity (excellent).Pass
- Context-footprint check failed: tool/resource definitions use about 23346 tokens (~402/item across 58 items; 44 tools + 14 resources), over budget; trim descriptions and params. See how to fix → Fail
- Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management100
- No destabilizing schema changes in the last 30 days.Pass
Tool Coverage100
- 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
- 100% of tool parameters carry a description.Pass
Tool Safety100
- No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
- All 3 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation.Pass
- An AI judge read all 46 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
- Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.Pass
How do I install the Clueso MCP server?
Clueso is a hosted endpoint at https://connect.clueso.io/mcp, so there is nothing to install locally. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.
remote · connect.clueso.io
claude mcp add --transport http io-clueso-video 'https://connect.clueso.io/mcp'
{
"mcpServers": {
"io-clueso-video": {
"url": "https://connect.clueso.io/mcp"
}
}
} {
"servers": {
"io-clueso-video": {
"type": "http",
"url": "https://connect.clueso.io/mcp"
}
}
} [mcp_servers.io-clueso-video] url = "https://connect.clueso.io/mcp"
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"io-clueso-video": {
"type": "remote",
"url": "https://connect.clueso.io/mcp",
"enabled": true
}
}
} openclaw mcp add io-clueso-video --url 'https://connect.clueso.io/mcp' --transport streamable-http
mcp_servers:
io-clueso-video:
url: "https://connect.clueso.io/mcp" {
"McpServers": {
"io-clueso-video": {
"Transport": "http",
"Url": "https://connect.clueso.io/mcp"
}
}
} assistant mcp add io-clueso-video -t streamable-http -u 'https://connect.clueso.io/mcp'
{
"mcpServers": {
"io-clueso-video": {
"type": "http",
"url": "https://connect.clueso.io/mcp"
}
}
} The mcpServers block is a cross-client convention. Remote transports vary, so check your client's docs.
Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.
- 18 Sept 26 0
- Tool “add_comment” rewrote its description, which is the text the model reads security
- Tool “add_elements” rewrote its description, which is the text the model reads security
- Tool “find” rewrote its description, which is the text the model reads security
- Tool “generate_media” rewrote its description, which is the text the model reads security
- Tool “run_script” rewrote its description, which is the text the model reads security
- Tool “switch_workspace” rewrote its description, which is the text the model reads security
- New tool “get_comments” functional
- “add_comment” added an optional parameter “parent_comment_id” cosmetic
- “generate_media” added an optional parameter “animation_setting” cosmetic
- “generate_media” added an optional parameter “background” cosmetic
- “generate_media” added an optional parameter “model” cosmetic
- “add_elements” reworded the description of “returning” cosmetic
- “get_clip” reworded the description of “select” cosmetic
- “update_elements” reworded the description of “returning” cosmetic
- “update_groups” reworded the description of “returning” cosmetic
- 16 Sept 26 −1
- The server rewrote its instructions, which are the text every model session reads security
- New tool “run_script”, which the server declares destructive security
- Tool “add_elements” rewrote its description, which is the text the model reads security
- Tool “analyze_audio” rewrote its description, which is the text the model reads security
- Tool “get_clip” rewrote its description, which is the text the model reads security
- Tool “get_element_schema” rewrote its description, which is the text the model reads security
- Tool “remove_elements” rewrote its description, which is the text the model reads security
- Tool “remove_from_project” rewrote its description, which is the text the model reads security
- Tool “reorder_elements” rewrote its description, which is the text the model reads security
- Tool “update_elements” rewrote its description, which is the text the model reads security
- Tool “voiceover_batch” rewrote its description, which is the text the model reads security
- Schema quality: 295 → 378 ▼ functional
- New tool “get_script_job” functional
- New tool “update_groups” functional
- “add_elements” added an optional parameter “defaults” cosmetic
- “add_elements” added an optional parameter “returning” cosmetic
- “get_element_schema” added an optional parameter “fields” cosmetic
- “get_element_schema” added an optional parameter “format” cosmetic
- “remove_from_project” added an optional parameter “group_id” cosmetic
- “remove_from_project” added an optional parameter “keep_children” cosmetic
- “update_elements” added an optional parameter “defaults” cosmetic
- “update_elements” added an optional parameter “returning” cosmetic
- “get_clip” reworded the description of “render” cosmetic
- “get_clip” reworded the description of “select” cosmetic
- “get_element_schema” reworded the description of “element_type” cosmetic
- “remove_from_project” reworded the description of “target” cosmetic
- Tool “remove_from_project” changed its title: Remove element or audio track → Remove element, group or audio track cosmetic
- 11 Sept 26 +1
- Stability: 0.97 → pass security
- 9 Sept 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 90 to 93. That category is still filling its 30-day observation window: 27 days of observed history at the previous scan, 28 at this one. The score rises as the window fills, whether or not the server changes.
- 7 Sept 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 83 to 87. That category is still filling its 30-day observation window: 25 days of observed history at the previous scan, 26 at this one. The score rises as the window fills, whether or not the server changes.
- 5 Sept 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 77 to 80. That category is still filling its 30-day observation window: 23 days of observed history at the previous scan, 24 at this one. The score rises as the window fills, whether or not the server changes.
- 3 Sept 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 70 to 73. That category is still filling its 30-day observation window: 21 days of observed history at the previous scan, 22 at this one. The score rises as the window fills, whether or not the server changes.
- 1 Sept 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 63 to 67. That category is still filling its 30-day observation window: 19 days of observed history at the previous scan, 20 at this one. The score rises as the window fills, whether or not the server changes.
Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.
Captured 20 Sept 2026 · Probed https://connect.clueso.io/mcp
TLS valid
Negotiated TLS 1.3 with TLS_AES_128_GCM_SHA256 .
| Subject | Issuer | Valid from | Valid until | Key | Signature | Serial |
|---|---|---|---|---|---|---|
| CN=connect.clueso.io | CN=Amazon RSA 2048 M01,O=Amazon,C=US | 23 Aug 2026 | 8 Mar 2027 | RSA 2048 | SHA256-RSA | 8126b0c9b5da36c1c2f94995f2d3c35 |
| SANs: connect.clueso.io | ||||||
| CN=Amazon RSA 2048 M01,O=Amazon,C=US (CA) | CN=Amazon Root CA 1,O=Amazon,C=US | 23 Aug 2022 | 23 Aug 2030 | RSA 2048 | SHA256-RSA | 77312380b9d6688a33b1ed9bf9ccda68e0e0f |
| CN=Amazon Root CA 1,O=Amazon,C=US (CA) | CN=Starfield Services Root Certificate Authority - G2,O=Starfield Technologies\, Inc.,L=Scottsdale,ST=Arizona,C=US | 25 May 2015 | 31 Dec 2037 | RSA 2048 | SHA256-RSA | 67f944a2a27cdf3fac2ae2b01f908eeb9c4c6 |
Background: What to check on a remote MCP endpoint →
DNSSEC insecure
Validation of connect.clueso.io. — Not signed
| Zone | DS | Keys | Algorithms | Outcome |
|---|---|---|---|---|
| . | trust_anchor | 20326, 38696 | 8, 8 | Verified |
| io. | present | 57355 | 8 | Verified |
| clueso.io. | absent | Unsigned (proven) parent-signed NSEC/NSEC3 proves an unsigned delegation |
Authentication Enforced and verified
The endpoint asked for a token and published valid RFC 9728 metadata describing how to get one.
| Result | Enforced and verified |
|---|---|
| Enforced | On tool calls |
| HTTP status | 200 |
WWW-Authenticate challenge Bearer resource_metadata="https://connect.clueso.io/.well-known/oauth-protected-resource/mcp"
Bearer resource_metadata="https://connect.clueso.io/.well-known/oauth-protected-resource/mcp" Protected resource metadata
| Document | https://connect.clueso.io/.well-known/oauth-protected-resource/mcp |
|---|---|
| Retrieved | Yes |
| Resource | https://connect.clueso.io/mcp |
| Authorisation server | https://auth.clueso.io/oauth/2.1 |
Background: How OAuth 2.1 works in the 2026 MCP spec →
Transports 2 probes
| Transport | URL | Outcome | Status | Location |
|---|---|---|---|---|
| streamable-http | https://connect.clueso.io/mcp | Verified | 200 | |
| http (plaintext) | http://connect.clueso.io/mcp | HTTPS enforced |
The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →
add_article_media Add article media (image or GIF) ~224
Add a screenshot or GIF to the article. Returns a screenshot_id to place in the article via update_article using `<SCREENSHOT screenshot_id>`. - kind="image": pass `timestamp` to capture a frame from the project's base video, OR pass `mcp_upload_id` (from the upload tool) to attach an uploaded image. One of the two is required. - kind="gif": pass `timestamp` (start) and `duration` (seconds). Captures a short GIF clip from the base video. Requires the project to have a video clip.
| Name | Type | Req | Description |
|---|---|---|---|
| duration | number | – | kind='gif' only: GIF duration in seconds. |
| kind | string | yes | 'image' or 'gif'. |
| mcp_upload_id | string | – | kind='image' only: attach an uploaded image (mcp_upload_id from the upload tool) instead of capturing from video. |
| project_id | string | yes | Project ID. |
| timestamp | number | – | kind='image': capture frame at this timestamp (seconds). kind='gif': GIF start time. |
No output schema declared.
No examples provided.
add_audio Add audio track ~938
Add a music track or sound effect that plays as a project-level audio layer over all clips. Does NOT consume a clip slot. Use this for background music or a soundtrack that should play under the existing timeline. (For inserting an audio file as its own sequential clip with auto-transcription, use add_clips(kind='video') with an audio mime_type instead.) - type="music": requires src, name, source_duration. `src` is either the `src` from a find(type='music') result, or an mcp_upload_id (prefixed `mup_`) from upload_file — upload ids resolve to a presigned URL server-side. For a Freesound result the `src` is an opaque handle; pass it through unchanged and Clueso downloads + hosts the original server-side (do not try to fetch it yourself). Get `source_duration` from the find result, or from analyze_audio mode='features' (data.duration_ms / 1000). Optional: guide_start_time, guide_end_time, music_start_time, music_end_time (trim the source track), volume, loop, fade_in, fade_out. - type="sfx": pass the `src`, `name`, and `source_duration` from a find(type='sfx') result, plus guide_start_time (Freesound `src` is an opaque handle, resolved server-side just like music). Optional: volume. (Legacy: a fixed-library `sfx_key` like 'whoosh' still works instead of src.) Concurrency: whole-project mutation (conflict domain: the entire project) — serialize; do not run in parallel with ANY other mutation on the same project_id (including element/voiceover edits). Size your clips BEFORE calling add_audio, or pass guide_end_time explicitly — the default ('end of project') is captured at call time and will NOT auto-extend if clips are added or resized afterwards.
| Name | Type | Req | Description |
|---|---|---|---|
| fade_in | number | – | Fade-in duration in seconds. Music only. (default: 0.5) |
| fade_out | number | – | Fade-out duration in seconds. Music only. (default: 0.5) |
| guide_end_time | number | – | When to stop playing (seconds). Music only. Default = end of project AT CALL TIME — captured once at insert and NOT recomputed when clips are later added or resized. Pass an explicit value (e.g. the… |
| guide_start_time | number | – | When to start playing in the guide timeline (seconds). Required for type='sfx', optional for music (default 0). |
| loop | boolean | – | Loop the track if project is longer than the source. Music only. (default: false) |
| music_end_time | number | – | Out-point within the SOURCE track (seconds) — trims where playback ends in the music file. Music only. Default = source_duration. |
| music_start_time | number | – | In-point within the SOURCE track (seconds) — trims where playback begins in the music file. Music only. Default 0 (start of source). |
| name | string | – | Track/effect name. From the find result, or any descriptive label when using mcp_upload_id. Required for type='music' and for stock type='sfx' (passed via src). |
| project_id | string | yes | The project ID |
| sfx_key | string | – | LEGACY fixed-library SFX key (e.g. 'whoosh', 'pop', 'click'). Optional alternative to src for type='sfx'. Prefer the src/name/source_duration from a find(type='sfx') result. |
| source_duration | number | – | Source duration in seconds. From the find result, or analyze_audio mode='features' (data.duration_ms / 1000). Required for type='music' and for stock type='sfx' (passed via src). |
| src | string | – | Audio source. For type='music' (required) or a stock type='sfx': the `src` from a find(type='music'|'sfx') result (may be an opaque Freesound handle — pass as-is), or an mcp_upload_id (prefixed 'mup_… |
| type | string | yes | Audio type: 'music' or 'sfx' |
| volume | number | – | Volume as percent (0–100). Default: 50 for music, 80 for sfx. |
No output schema declared.
No examples provided.
add_clips Add clips to project ~683
Create new clips on a project. One tool, three sources: - kind="blank": empty slide clips you'll populate with add_elements / generate_media. Pass `clips: [{title?, duration?}, ...]`. Note: create_project already creates clip 0; calling with N blank entries gives N+1 clips total. - kind="pptx": extract slides from an uploaded .ppt/.pptx. Pass `mcp_upload_id` (from upload_file), optional `slide_indices`. Each slide becomes a slide_clip with native text/image/shape elements pre-populated. - kind="video": cut clips from an uploaded video/audio. Pass `mcp_upload_id` and optionally `mime_type` (default video/mp4), `title`, `voiceover_text`, `cuts: [{start_seconds, end_seconds, heading?}]`, `auto_elements`. Without `cuts` the whole upload becomes one clip. Pipeline (download → transcribe → insert) runs in the background; subsequent calls on the same upload hit a 24h cache and return synchronously. (To overlay a video ONTO an existing clip — picture-in-picture, b-roll, background loop — rather than insert it as its own clip, use add_elements(element_type='video') instead.) All variants accept `after_clip_id` to control insertion position; appends at end if omitted. Concurrency: whole-project mutation (conflict domain: the entire project) — serialize. Do not run it in parallel with ANY other mutation on the same project_id, including element/voiceover edits; run them one at a time. (Mutations to different projects run in parallel freely.)
| Name | Type | Req | Description |
|---|---|---|---|
| after_clip_id | string | – | Insert after this clip ID; appends at end if omitted. |
| auto_elements | boolean | – | kind='video' only: when true, run auto-element detection (zooms, spotlights, blurs). Default false. Only meaningful on cache miss; cache hits clone the originating run's auto-elements. |
| clips | array | – | kind='blank' only: one entry per blank clip. Optionally set background_color/background + transition per clip at creation — no follow-up update_clips needed. |
| cuts | array | – | kind='video' only: per-clip cuts. Each entry becomes one inserted clip. Omit to insert the full upload as a single clip. |
| kind | string | yes | Source for the new clips: 'blank' | 'pptx' | 'video'. |
| mcp_upload_id | string | – | kind='pptx' or 'video': mcp_upload_id from the upload_file tool. |
| mime_type | string | – | kind='video' only: MIME type (default 'video/mp4'). Audio MIME types insert the file as a sequential clip with auto-TTS; for background music, use add_audio instead. |
| project_id | string | yes | Project (guide) ID. |
| slide_indices | array | – | kind='pptx' only: 0-based slide indices to insert. Omit to insert all slides. |
| title | string | – | kind='video' only: clip title (default 'Video'). |
| voiceover_text | string | – | kind='video' only: post-AI voiceover script (saved as v2). Original audio is always retained as the base transcript. |
No output schema declared.
No examples provided.
add_comment Add comment ~247
Post a review comment on a project, attributed to "Clueso AI". Use this to leave feedback, suggestions, or notes — either at the project level (no clip_id) or pinned to a specific clip with an optional timestamp inside that clip. Pass `parent_comment_id` to REPLY to an existing comment rather than open a new thread. Read what is already there with `get_comments` first: answering a reviewer in their own thread is what makes the note resolvable, where a fresh top-level comment just adds noise.
| Name | Type | Req | Description |
|---|---|---|---|
| clip_id | string | – | Optional clip ID to pin the comment to. Omit for a project-level comment. |
| clip_timestamp | number | – | Optional timestamp within the clip (seconds). Only used when clip_id is provided. |
| comment_text | string | yes | Comment text to post |
| parent_comment_id | string | – | Reply to this comment instead of starting a new thread. Take the id from get_comments. Replying is how you answer feedback you have acted on — the clip pin and timestamp come from the parent, so leav… |
| project_id | string | yes | The project (guide) ID |
No output schema declared.
No examples provided.
add_elements Add elements to clips ~1,788
Add many elements across one or more clips in a single tool call. Replaces the per-element tool — always batch. SEND LESS. Most batches repeat themselves — the same clip_index, element_type, font_setting, alignment or gradientSetting on every item. Hoist those into `defaults` and send them once; each item then carries only what differs, and overrides any key it sets (type_data merges one level). On a 20-30 element batch this typically cuts the call by a quarter to a half. `returning` shapes the response the way `select` shapes a get_clip read. defaults: { clip_index: 2, element_type: 'text', type_data: { font_setting: { font: 'Inter', weight: '600' }, alignment: 'center' } } elements: [ { name: 'headline', x: 960, y: 400, type_data: { text: 'Hello', fontSize: 120 } }, ... ] Use after calling get_element_schema to confirm the type_data shape per element_type. Items within one call are applied in order; returns one result entry per input item so partial success is fine. Reuse instead of rebuilding: an item may pass `component_id` INSTEAD of element_type/type_data to insert a saved component from this workspace exactly as stored — no generation, instant — returning every new element_id plus its parameter_schema; set its content afterwards with update_elements(type_data.parameter_values). Find them with find(type='element_components'). Use `base_component_id` (with element_type='animation' and a prompt) only when you want a NEW variant rather than that component. Z-order: list position IS z-index — later renders on top — and a new element goes on top by default. Pass `insert_at: 'back'` to put it behind what's already there, or `insert_at: {before: id}` / `{after: id}` to land next to a specific element — that also puts the new element in THAT node's group, which is the only way to place inside one. `reorder_elements` rewrites the whole order in one call, grouped clips included. `group` + `insert_at: {before|after}` together: what the reference is relative to…
| Name | Type | Req | Description |
|---|---|---|---|
| defaults | object | – | Values shared by every item, sent once rather than repeated. Items win per key; type_data merges one level. E.g. defaults:{clip_index:1, element_type:'text', type_data:{font_setting:{font:'Inter',wei… |
| elements | array | yes | Elements to add — at least one entry. |
| project_id | string | yes | Project ID |
| returning | array | – | Declare what comes back, the way get_clip's `select` shapes a read. Omit it and you get ids, the measured layout, and the clip audit in compact form — which names every problem but drops the explanat… |
No output schema declared.
No examples provided.
add_sync_point Add a sync point at a word + timestamp ~383
Insert one sync marker on a clip's transcript. Use this when: - The user is explicit about WHERE the camera should pause / cut (e.g. "sync the word 'submit' to 4.2s of the demo"). - `auto_sync` ran but missed a step you care about. How matching works: - `word`: case-insensitive, punctuation-stripped. The first match in the transcript is used unless `occurrence > 1`. - `occurrence`: 1-indexed — pass 2 to target the SECOND time that word appears, 3 for the third, etc. Required when the word repeats. - `timestamp_seconds`: clip-relative seconds. When the clip has run TTS already (`generated_timestamps` present), the server inverse-maps this to original-recording seconds automatically. Constraints: the clip MUST be a video clip with a source recording (otherwise the frame thumbnail can't be extracted). The transcript must already contain the word — if not, you'll get `word_not_found` with a 200-char excerpt of the transcript to help you retry.
| Name | Type | Req | Description |
|---|---|---|---|
| clip_id | string | – | Clip ID (preferred). If omitted, clip_index is used. |
| clip_index | integer | – | Zero-based clip index. Ignored if clip_id is provided. |
| occurrence | integer | – | 1-indexed match number when the word repeats. Defaults to 1 (first occurrence). |
| project_id | string | yes | Project ID. |
| sync_point_name | string | – | Optional label (e.g. 'Click submit'). Defaults to 'Sync point N' using the next order number. |
| timestamp_seconds | number | yes | Clip-relative timestamp in seconds. Auto-mapped to original-recording seconds when the clip has generated_timestamps. |
| word | string | yes | Target word (case-insensitive; trailing punctuation is stripped). |
No output schema declared.
No examples provided.
analyze_audio Analyze audio ~566
Analyze an audio file. Modes: - transcript: Speech-to-text with word-level timestamps — returns `{language, full_text, words}` where each word is `{word, start_ms, end_ms, punctuated_word}`. ⚠ MILLISECONDS here; get_clip's `voiceover_words` gives the same words in SECONDS as `{word, start, end}`. Use for caption timing, script editing, or word-level visual sync. Works on narration and on sung lyrics: the provider is picked from the content, and if it returns nothing the other one is tried automatically. So an empty `words` means the audio genuinely has no intelligible speech, not that the wrong engine ran. - silences: returns `{silences, total_silence_ms}`, each span `{start_ms, end_ms, peak_db}`. Use for auto-trim, smart-split, or pause-aware editing. - beats: returns `{tempo_bpm, beats_ms}` — beats_ms is an array of MILLISECOND positions. Empty for non-music. Use to align animations/zooms to a beat. - features: returns `{duration_ms, peak_db, rms_db, lufs, has_music, has_speech}` — loudness plus two INDEPENDENT hints — `has_music` (beats hold a steady period) and `has_speech` (there is audible content above a loudness floor; it is not a speech detector). Both can be true at once, e.g. narration over a music bed. Cheap dispatcher — call once to pick a mode, or for duration_ms to pass as add_audio's source_duration. When the words matter, trust transcript rather than these flags. Source: provide exactly one of mcp_upload_id (from upload tool) or file_url (already-public URL, e.g. a find(type='music') result or Clueso CDN file). Optional time range: range_start_ms / range_end_ms crops the analysis window.
| Name | Type | Req | Description |
|---|---|---|---|
| file_url | string | – | Public http(s) URL to the audio. Use when the file is already accessible (e.g. find(type='music') result, Clueso CDN). Validated against private/loopback ranges. |
| mcp_upload_id | string | – | MCP upload ID from the upload_file tool. Use this OR file_url, not both. |
| mode | string | yes | Which analysis to run. |
| range_end_ms | integer | – | End of analysis window in milliseconds. Default: whole file. |
| range_start_ms | integer | – | Start of analysis window in milliseconds. Default 0 (beginning). |
| silences_options | object | – | Options for mode='silences'. |
| transcript_options | object | – | Options for mode='transcript'. |
No output schema declared.
No examples provided.
auto_sync Auto-generate sync points ~174
Run the agentic auto-sync pipeline against a clip with a source recording. Detects natural sync points (UI state changes, narrated steps) and inserts sync-marker nodes into the clip's transcript. Async: returns immediately with a status enum from the pre-flight; sync-marker nodes appear in the transcript a few seconds later. Poll get_clip if you need to verify. Capacity: capped at 3 concurrent runs platform-wide. Returning status='success' means the job was accepted, not that it finished. Sync points are required input for voiceover TTS on video clips — without them, the TTS has no per-step pacing reference. (See resource clueso://docs/sync-points for the full model.)
| Name | Type | Req | Description |
|---|---|---|---|
| clip_id | string | yes | Clip ID to auto-sync. |
| project_id | string | yes | Project ID. |
No output schema declared.
No examples provided.
check_uploads Check upload status ~91
Fetch all files the user uploaded via the hosted upload page. Returns one mcp_upload_id per file — pass each to the appropriate tool (add_clips, add_article_media, etc.). Call this once after the user confirms they are done uploading; the token covers all files they dropped on the page.
| Name | Type | Req | Description |
|---|---|---|---|
| upload_token | string | yes | The upload_token returned by upload_file(request_hosted_upload: true) |
No output schema declared.
No examples provided.
create_clueprint Create clueprint ~191
Create a new clueprint (reusable video template). A clueprint is a structured file directory with design notes, composition rules, and screenshots that can be used to generate videos. Use human-readable folder categories: design/ (colors, typography, backgrounds, animation), rules/ (composition, voiceover, editing), screenshots/ (rendered clip previews). See the "Creating Clueprints" section in the system instructions for the full structure. If source_guide_ids are provided, guide data is automatically extracted clip-by-clip into the clueprint as reference material.
| Name | Type | Req | Description |
|---|---|---|---|
| description | string | – | Description of what this clueprint does |
| name | string | yes | Name of the clueprint |
| source_guide_ids | array | – | IDs of existing projects to extract template data from |
| visibility | string | yes | 'private' = only you, 'workspace' = everyone in your workspace |
No output schema declared.
No examples provided.
create_project Create project ~171
Create a new blank Clueso project. Returns the projectId and initialClipId — the project starts with one blank clip already at index 0 (default short duration). Use update_clips to resize/retitle clip 0, add_clips(kind='blank') to append more clips, add_elements to place content, and add_audio to attach a project-level music track. Optionally place the project inside a folder (use find(type='folders') to find folder IDs) and set a description at creation time.
| Name | Type | Req | Description |
|---|---|---|---|
| description | string | – | Optional project description (max ~500 chars) |
| folder_id | string | – | Optional folder ID to nest the project under. Use find(type='folders') to discover IDs. Omit to create at workspace root. |
| title | string | – | Project title |
No output schema declared.
No examples provided.
duplicate_clip Duplicate a clip ~284
Clone one clip — within the same project, or **from another project** — into a target project. - Same project: pass `target_project_id` and `source_clip_id` (omit `source_project_id`). - Cross-project: pass `target_project_id`, `source_project_id`, `source_clip_id`. The source clip's S3 assets (voiceover audio, original video footage, generated video, etc.) are re-hosted into the target guide's S3 namespace, so the new clip is independent of the source — deleting the source project later won't break it. Insertion: pass `after_clip_id` to place immediately after a specific clip in the target. Omit to append at end. Returns the new clip_id and its final index. Concurrency: whole-project mutation (conflict domain: the entire target project) — serialize; do not run in parallel with any other mutation on the same target_project_id.
| Name | Type | Req | Description |
|---|---|---|---|
| after_clip_id | string | – | Insert after this clip ID in the target. Appends at end if omitted. |
| source_clip_id | string | yes | ID of the clip to duplicate. |
| source_project_id | string | – | Cross-project mode: ID of the project the source clip lives in. Omit for same-project duplication. |
| target_project_id | string | yes | Project (guide) ID to insert the duplicate into. |
No output schema declared.
No examples provided.
duplicate_project Duplicate project ~216
Clone an entire project — every clip, voiceover, asset, and metadata field — into a fresh project. The copy has its own S3 namespace, so changes or deletions to the source never affect the duplicate. Defaults: - new_title omitted → "{source title} (copy)" when no folder_id is given (or it's empty) and the source stays in the same org; pass an explicit non-empty folder_id and the title is preserved. - folder_id omitted → copy lives in the same folder as the source. Returns the new project's id and title. Concurrency: whole-project read+create — serialize against other mutations on the same source_project_id; do not run them in parallel.
| Name | Type | Req | Description |
|---|---|---|---|
| folder_id | string | – | Place the duplicate in this folder. Omit to keep the same folder as the source. Pass '' (empty string) to move to workspace root. |
| new_title | string | – | Override the title of the duplicate. |
| source_project_id | string | yes | Project (guide) ID to duplicate. |
No output schema declared.
No examples provided.
estimate_duration Estimate clip duration ~69
Estimate voiceover duration for one or many clips at once (~150 words/minute). Pass an array of voiceover texts — one per clip. Returns durations in the same order, ready for add_clips.
| Name | Type | Req | Description |
|---|---|---|---|
| texts | array | yes | Array of voiceover texts to estimate — one string per clip. |
No output schema declared.
No examples provided.
export_project Export project ~126
Kick off a video export of the project. Returns immediately with an export_id; the export pipeline runs in the background. The user can find the rendered video in the Exports tab in the editor. Defaults: 1080p / 30fps / no captions / English. Pass overrides only when needed.
| Name | Type | Req | Description |
|---|---|---|---|
| captions | boolean | – | Burn subtitles into the video (default false) |
| fps | – | – | Frames per second (default 30) |
| project_id | string | yes | The project ID to export |
| resolution | string | – | Output resolution (default 1080p) |
No output schema declared.
No examples provided.
find Find resources ~1,548
Find any resource in Clueso by type, optionally filtered by name or exact id. One tool for listing and searching across the workspace. type: • projects | folders | clueprints | workspaces • backgrounds | voices | image_gen_style_packs | element_components (voices carry `gender`, `tags`, `accent`, `preview_url` and — where one has been written — a free-text `description` of tone and pace, which is the field actually worth choosing on. `tags` is a small closed vocabulary, so it groups voices rather than telling them apart. Choose deliberately: voiceover is the film's clock, and regenerating speech later rescales the clip and every element time and keyframe with it.) • images | videos | music | sfx — media; each result carries a `source` ('org' = your saved-media library, 'stock' = a stock/curated provider). Scope with `source`, pick the library with `provider` (see below). Stock results are a short described shortlist — pick the best fit and use its `src`. Stock video results also carry `safe_src` and a `video_files` tier list with one entry marked `recommended` — use `safe_src` (or the recommended tier) in add_elements; tiers above 1080p can exceed its ~200MB source cap and fail. For a Freesound music/sfx result, `src` is an OPAQUE handle (not a playable URL) — pass it straight to add_audio and the original is fetched + hosted by Clueso server-side; a `preview_url` is included only so you can tell what it sounds like. (image_gen_style_packs = generation style presets for generate_media kind='image' style_id; element_components = saved components (e.g. animations) from THIS WORKSPACE only — there is no community library for components (unlike clueprints); each reports param_keys. Insert one AS-IS with add_elements(component_id=...), or generate a variant from it with base_component_id.) Filters (all optional): • query — for stock media it's the search phrase (real semantic search for provider='clueso'; provider keyword search otherwise). For clueprint…
| Name | Type | Req | Description |
|---|---|---|---|
| color | string | – | stock images only: color name or hex, e.g. 'blue'. |
| creator_id | string | – | clueprints only: filter by creator id. |
| engine | string | – | voices only: 'eleven' | 'cartesia' | 'google'. |
| folder_id | string | – | projects/images/videos/music only: restrict to a folder. |
| id | string | – | Exact id — returns just that record. |
| image_type | string | – | stock images + provider='pixabay' only: 'photo' | 'illustration' | 'vector' (flat/drawn graphics, icons, clip-art). Use illustration/vector for graphic looks; photo (or Pexels) for realism. |
| language | string | – | voices only: e.g. 'en'. |
| limit | integer | – | Page size (default 50; voices default 5 — a '_more' item flags further pages). |
| max_duration | integer | – | stock videos + freesound audio: maximum clip length in seconds. |
| min_duration | integer | – | stock videos only: minimum clip length in seconds. |
| mine_only | boolean | – | clueprints only: only ones I created. |
| orientation | string | – | stock images/videos only: result orientation. |
| page | integer | – | Page (default 1) — projects/element_components/clueprints. |
| provider | string | – | stock media: which library to search (exactly one). images/videos: 'pexels' (default — polished real-world photos & footage) | 'pixabay' (illustrations, vectors, clip-art, icons + more variety; pair… |
| query | string | – | Case-insensitive substring match on name. |
| size | string | – | stock videos only: minimum resolution bucket. |
| source | string | – | media types (images/videos/music/sfx) only: where to search — 'org' (your saved workspace media), 'stock' (stock library — images/videos via Pexels, music from Clueso's catalog), 'all' (both; default… |
| type | string | yes | Resource type to find. |
| video_type | string | – | stock videos + provider='pixabay' only: 'film' (live footage) | 'animation' (motion graphics). |
No output schema declared.
No examples provided.
generate_media Generate AI media (image or animation) ~1,176
Generate an AI image or canvas-code-based animation directly into a clip. - kind="image": text-to-image. Pass `prompt`. Optional: `animation_setting` (entry/exit — set it HERE, see below), `style_id` (from find type='image_gen_style_packs'), `reference_image_url` or `mcp_upload_id` for image-to-image grounding. - kind="animation": canvas-code animation rendered from a prompt. Pass `prompt`. Optional: `voiceover_text` (drives timing), `base_component_id` (reuse a saved animation as the starting point), `reference_image_url` or `mcp_upload_id` for visual grounding. Generation is asynchronous: the element is created immediately with a stable `element_id` and rendered in the background. Poll `get_clip(select:['busy'])` — an EMPTY `busy` means the render has landed. (This previously said to watch the `phantom` flag; `phantom` has never been a key get_clip returns, so there was nothing to poll.) Set presentation up front. `animation_setting` is applied to the element as it is created, so the image enters correctly the first time it renders. Doing it afterwards with `update_elements` means writing to the element that is still generating, which is the write most likely to be refused while the generation holds it. `group` is NOT accepted here, unlike `add_elements`: a generated element is built in the background, and the grouping would be overwritten when the render lands. Add it ungrouped, then call `update_elements` with `group` once it appears. Tip: use this tool whenever the user asks for a "generated", "AI", or "create me a" visual. For uploaded photos / logos / icons / GIFs, use `add_elements` with `element_type='image'` and a `src` or `mcp_upload_id` instead.
| Name | Type | Req | Description |
|---|---|---|---|
| animation_setting | object | – | Image only. Entry/exit animation, same shape as add_elements' type_data.animation_setting. The design guide asks AI images to enter with `masked_reveal` or a slow fade, so set it here rather than fol… |
| background | – | – | Image only, and only honoured by `gpt-image-2.5-flare`, `gpt-image-2.5-sunburst`, `gpt-image-1` and `gpt-image-1.5` — every other model is always opaque and ignores this. Pass `false` for a cut-out w… |
| base_component_id | string | – | Animation only. Reuse a saved animation component as the starting point (from find(type='element_components')). To re-skin its tunable parameters, set parameter_values via update_elements after it re… |
| clip_id | string | yes | Clip ID to place the generated element into. |
| end_time | number | – | Disappear at (seconds). |
| height | number | yes | Height in pixels. |
| kind | string | yes | 'image' = AI text-to-image; 'animation' = canvas-code-based motion graphic. |
| mcp_upload_id | string | – | mcp_upload_id from the upload flow. Resolved server-side to a presigned URL before generation. |
| model | string | – | Image only. Which image model renders it. Default `gemini-3-pro-image-preview` (Nano Banana Pro), a strong general choice — leave it off unless you want one of the specifics below. `gemini-3.1-flash-… |
| project_id | string | yes | Project ID. |
| prompt | string | yes | Generation prompt. For animations, be SPECIFIC: name the UI elements, interaction sequence, timing feel, and visual style. Vague prompts produce bad output. |
| reference_image_url | string | – | Public URL of a reference image. Mutually exclusive with mcp_upload_id. |
| start_time | number | – | Appear at (seconds). |
| style_id | string | – | Image only. Style preset ID from find(type='image_gen_style_packs'). See resource clueso://docs/generation-styles. |
| voiceover_text | string | – | Animation only. Paces the motion to the spoken script — and as a side effect sets this clip's voiceover text and triggers speech generation for the clip. |
| width | number | yes | Width in pixels. |
| x | number | yes | Top-left X in canvas pixels. |
| y | number | yes | Top-left Y in canvas pixels. |
No output schema declared.
No examples provided.
get_article Get article ~48
Get the article content as markdown. Screenshots appear as <SCREENSHOT {id}> placeholders. Returns the markdown text and a list of screenshot IDs.
| Name | Type | Req | Description |
|---|---|---|---|
| project_id | string | yes | Project ID |
No output schema declared.
No examples provided.
get_clip Get clip details ~1,576
Read one clip: its elements (positions/sizes in canvas pixels), voiceover (text, voice, duration, voiceover_volume), background and transition. Pass `render` to also get a PNG of the frame. ASK FOR WHAT YOU NEED. A full read is large — on a dense clip the per-word voiceover array and the element type_data blobs dominate it, and repeated full reads are the main way a long session runs out of context. `select` returns exactly the parts you name: select: ['elements.x','elements.y','elements.width','elements.height'] → geometry only, to fix a layout select: ['elements.name','elements.start_time','elements.end_time'] → a timing pass select: ['voiceover_words'] → word timings only, to sync visuals to narration select: ['elements.textdata','voiceover_words'] → rewrite copy against the VO select: ['elements'] → whole element rows, no words select: ['groups'] → group rows only, to get a group_id for update_groups select: [] → no JSON at all (pair with render for the PNG alone — smallest read) (omit select) → everything; fine for a first look, expensive to repeat `render` is the other output, and it is separate from `select`: `select` shapes the JSON, `render` produces a PNG. render: {} → the frame at t=0 render: { timestamps: 2.5 } → the frame 2.5s into the clip render: { timestamps: [0.5, 2, 4] } → those three moments as ONE labelled grid render: { timestamps: [...], layout:'separate'} → the same moments as full-size images (~4x the tokens) render: { save: true } → also uploads the frame and returns presigned_url render: { max_width: 1280 }…
| Name | Type | Req | Description |
|---|---|---|---|
| clip_index | integer | yes | Zero-based clip index |
| element_ids | array | – | WHICH element rows to return — all others are dropped. Independent of `select`, which chooses the sections/keys. Use it to re-inspect just what you added or updated; most add_elements/update_elements… |
| project_id | string | yes | The project ID |
| render | object | – | Render the clip as an image. Presence of this object IS the request to render — omit it and nothing is rendered. `{}` renders at t=0. Independent of `select`, which only shapes the JSON: pair `select… |
| select | array | – | Ask for exactly the JSON you want, GraphQL-style. Omit for everything; pass [] for none. Sections: 'elements' (whole element rows), 'voiceover_words' (per-word VO timings; returns the key of the sa… |
No output schema declared.
No examples provided.
get_clueprint Get clueprint ~269
Fetch clueprint data. Use `include` to control how much you pull back: - include="metadata": just the clueprint's name/description/tags/visibility/thumbnail. - include="tree": metadata + the full file tree (path, mime_type, and size per entry). Call this first when exploring an unfamiliar clueprint. - include="files": the contents of the files listed in `file_paths` (no metadata — call include='tree' first if you also need metadata). Text inline, binary as presigned GET URLs. - include="all": metadata + the file tree + the contents of every file in the clueprint (use sparingly on large clueprints). Calling this also logs the clueprint as "used" (fire-and-forget) so the workspace's recents list stays accurate — no follow-up use_clueprint call needed.
| Name | Type | Req | Description |
|---|---|---|---|
| clueprint_id | string | yes | ID of the clueprint. |
| file_paths | array | – | include='files' only: relative paths to read (e.g. ['design/colors.md', 'rules/voice.md']). Ignored for other modes. |
| include | string | – | What to return: 'metadata' | 'tree' | 'files' | 'all'. Defaults to 'tree'. |
No output schema declared.
No examples provided.
get_comments Get comments ~233
Read the review comments on a project — the other half of `add_comment`, which could post but never read. Comments are how a human reviewer tells you what is wrong with a video: a note pinned to a clip and a moment inside it. Read them before an editing pass so you act on what was actually asked for, and read them again after a build if a reviewer has seen it. Threads come back nested: each top-level comment carries its `replies`. Reply into a thread with add_comment(parent_comment_id=...) rather than posting a new top-level note — a reviewer reading their own thread is how they see that their point was handled. Resolved threads are hidden by default, so a plain read is "what still needs attention".
| Name | Type | Req | Description |
|---|---|---|---|
| clip_id | string | – | Only comments pinned to this clip. Omit for every comment on the project, project-level ones included. |
| include_resolved | boolean | – | Include threads already marked resolved (default false). Turn it on to see history; leave it off to see the work outstanding. |
| project_id | string | yes | The project (guide) ID |
No output schema declared.
No examples provided.
get_design_guide Get design guide ~74
Clueso's house style for composing video clips — how to think about concept, typography, color, composition, motion, and pacing. Read it before composing or editing a clip's visuals when you're NOT following a clueprint, or to fill gaps a clueprint leaves silent. General craft, not clueprint-specific.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
get_element_schema Get element schema ~244
Return the schema for an element type's type_data, as TypeScript declarations. Call this before add_elements / update_elements when you don't already know the field shape for the element_type you're placing. Pass element_type='group' for the GROUP surface instead — what a group is, how its pivot works, and the nine properties it can animate.
| Name | Type | Req | Description |
|---|---|---|---|
| element_type | string | yes | One of: text, callout, rectangle, arrow, blur, spotlight, zoom, image, video, animation, group |
| fields | array | – | Return only these fields, with their prose — text is 15KB whole, ~300 bytes for two. Omit while learning the type: only the full schema carries the keyframable list and the keyframe rules. |
| format | string | – | Defaults to 'declarations' — TypeScript-style, which is the better READ. Inside run_script it defaults to 'json' instead, because a script indexes into the structure and the declaration text would ar… |
| mode | string | – | 'add' returns required + optional fields; 'update' returns all-optional. |
No output schema declared.
No examples provided.
get_project Get project data ~148
Get a summary of a project: canvas dimensions, per-clip summary (ids, indices, durations, element counts, voiceover_volume), and `audio_tracks` — every music/SFX entry on the project flattened to the same wire shape `add_audio` accepts (id, src, name, source_duration, guide_start_time/end_time, music_start_time/end_time, volume, loop, fade_in, fade_out). To copy an audio track to another project: read it from `audio_tracks` here and feed the same fields to `add_audio` on the target project. Call this to understand what's in the project before making changes.
| Name | Type | Req | Description |
|---|---|---|---|
| project_id | string | yes | The project ID |
No output schema declared.
No examples provided.
get_script_job Get a script job's result ~149
Fetch the outcome of a run_script that did not finish inline. Waits for it rather than returning immediately, so one call is usually enough — set `wait_seconds` to how long you are willing to hold. Returns { job_id, status, result?, error? }. `status` is processing, completed or failed; `result` carries the same { ok, result, stdout, ops } the inline reply would have. The script runs to completion whether or not you poll.
| Name | Type | Req | Description |
|---|---|---|---|
| job_id | string | yes | From the run_script reply. |
| wait_seconds | integer | – | How long to wait for completion before answering, default 45s. Pass 0 for an immediate status check. |
No output schema declared.
No examples provided.
record_screen Record screen ~650
Create a screen-recording clip in a project. Creates blank placeholder clips, registers job entities, and sends the job to AVS. The blank clips this tool creates are placeholders; they become video clips when processing completes, so removing one loses that scene. Article placeholders are also inserted automatically into plainDoc. Requires the Auto-Recording add-on and per-workspace sign-in credentials for the product being recorded. Workspaces without it get back the manual path instead (upload_file, then add_clips(kind='video')) rather than a failure.
| Name | Type | Req | Description |
|---|---|---|---|
| chat_id | string | yes | Conversation context ID |
| custom_instructions | string | – | Optional per-recording instructions (e.g. "select project X", "add rectangle 200x100"). Not related to mocking. |
| edit_scene_ids | array | – | The clip id(s) this edit replaces. Only used when recording_session_id is set; scenes you do not name are not re-filmed. Set preceding_clip_id to the clip you are replacing — an edit naming a clip th… |
| exact_article_script | boolean | – | Set to true when the article must be used exactly as written — the agent that does the recording will not reword, rephrase, or rewrite article_script at all. Default false. |
| exact_video_script | boolean | – | Set to true when the video narration must be used exactly as written — the agent that does the recording will not reword, rephrase, or rewrite video_script at all. Default false. |
| guide_id | string | yes | Target guide ID |
| language | string | – | Language code for the recording (default: en) |
| preceding_clip_id | string | yes | Clip ID after which to insert the new clip |
| recording_session_id | string | – | EDIT an existing recording instead of shooting a new one. Pass the recording_session_id from the record_screen that made it, or read it off get_clip. The recorder restores that take's code, notes and… |
| scenes | array | yes | REQUIRED — the recording to make, as a list of scenes. This is the ONLY way to specify what to record. A normal single recording is exactly ONE scene; a code-wizard multi-scene / marketing video is N… |
| video_intention | string | – | One-line intent shared across all scenes of a multi-scene recording (e.g. "punchy 30s launch teaser for feature X"). Ignored for single-scene recordings. |
No output schema declared.
No examples provided.
remove_clip Remove clip ~151
Remove a clip from the project by index. Cannot remove the last remaining clip. After removal, all clips with index > clip_index shift down by 1. When removing multiple clips by index, remove from highest index to lowest (or capture clip_ids first and re-derive indices between calls). Concurrency: whole-project mutation (conflict domain: the entire project) — serialize. Do not run it in parallel with ANY other mutation on the same project_id, including element/voiceover edits; run them one at a time. (Mutations to different projects run in parallel freely.)
| Name | Type | Req | Description |
|---|---|---|---|
| clip_index | integer | yes | Zero-based clip index to remove |
| project_id | string | yes | The project ID |
No output schema declared.
No examples provided.
remove_elements Remove elements from clips ~202
Remove many elements across one or more clips in a single tool call. One entry per element ({clip_index, element_id}). Concurrency: parallel-safe (conflict domain: the individual element) — same as update_elements. Each removal is a granular element_remove patch scoped to that element id, and the whole batch lands in ONE save. Fan out across subagents as long as they touch DIFFERENT element ids. Two concurrent edits to the SAME element id do not last-write-win — the later one is REJECTED and nothing is written; re-read and re-apply. Do NOT run concurrently with whole-clip/whole-project mutations on the same guide (update_clips on that clip, structural clip ops, add_audio, update_project). To remove an audio track (not an element), use remove_from_project(target='audio').
| Name | Type | Req | Description |
|---|---|---|---|
| project_id | string | yes | Project ID |
| removals | array | yes | Elements to remove — at least one entry. |
No output schema declared.
No examples provided.
remove_from_project Remove element, group or audio track ~335
Remove an element, a group or an audio track from a project. - target="element": removes an element from a clip (requires clip_index + element_id) - target="group": removes a GROUP node (requires clip_index + group_id). By default its children survive — they rise to the removed group's own parent, which for a top-level group is the clip root. Pass keep_children=false to delete the whole subtree instead, every nested group and every element inside it. - target="audio": removes a music/SFX track (requires music_id — returned by add_audio) Concurrency: target='element' is element-scoped (conflict domain: the individual element) — parallel-safe with other element edits on different elements, same as remove_elements. target='audio' is a whole-project mutation — serialize it against any other mutation on the same project_id. (Mutations to different projects run in parallel freely.)
| Name | Type | Req | Description |
|---|---|---|---|
| clip_index | integer | – | Zero-based clip index (required for target='element') |
| element_id | string | – | Element ID to remove (required for target='element') |
| group_id | string | – | Group ID to remove (required for target='group') |
| keep_children | boolean | – | target='group' only. Omit/true ungroups: children rise to the removed group's own parent. false deletes the whole subtree. |
| music_id | string | – | Music/SFX track ID to remove (required for target='audio') |
| project_id | string | yes | The project ID |
| target | string | yes | What to remove: 'element', 'group' or 'audio' |
No output schema declared.
No examples provided.
reorder_elements Reorder elements within a clip ~223
Reorder the elements inside a clip. List position IS the z-index — later entries in `ordered_element_ids` render on top of earlier ones. You MUST pass the full set of element IDs currently in the clip. The handler rejects partial lists so a reorder can never silently drop an element. Get the current list via get_clip — the order it returns is exactly the order this takes. Works on grouped clips. Elements keep their group; moving a group's members together moves the whole group relative to everything else. The one thing a group cannot do is render in two pieces, so an order that puts a non-member BETWEEN two members of the same group is rejected and names the group — put the group's elements next to each other, or take the element out of the group first with update_elements(group).
| Name | Type | Req | Description |
|---|---|---|---|
| clip_index | integer | yes | Zero-based clip index. |
| ordered_element_ids | array | yes | All element IDs currently in the clip, in the new order. Position N = z-index N (later = on top). |
| project_id | string | yes | Project ID. |
No output schema declared.
No examples provided.
run_script Run a script that calls these tools ~1,731
Write a JavaScript program that calls this server's other tools. You have the whole language: loops, arithmetic, functions, conditionals, and values carried from one call into the next — all running next to the tools instead of across the conversation. Use it whenever code says the thing more directly than a sequence of separate calls would, which is often. COMPUTE, don't hand-write. Anything you would otherwise work out in your head and type as literals is better computed here — eased keyframe tracks, staggered start times, grid coordinates, derived palettes, positions from measured text widths. This is usually what makes motion look right: sample a curve at ten points and emit the values, rather than guessing four. DON'T COMMENT THE SCRIPT. Nobody reads it — it runs once and is gone. Comments, blank lines and explanatory names are pure cost here. Write it dense. The one thing to remember: inside a script you see only what you `return` or log, so a tool's own rich output (layout measurements, layout_qa, new ids) has to be surfaced deliberately. That also makes a single-call script worthwhile when a read is fat — `find` takes no projection argument, so logging the 200 characters you need is a real saving. A fat read is usually better narrowed at the source than filtered here: get_clip takes `select`, and get_element_schema takes `fields` (name what you're setting and a 15KB schema becomes ~200 bytes). get_element_schema returns TEXT by default, which you cannot index into — pass `format: 'json'` when you want to compute over the schema rather than log it. CALLING TOOLS Every tool except run_script and get_script_job is a global function taking exactly the arguments it takes normally, and returning its parsed result (those two are excluded so a script cannot recurse into itself or poll its own job). Calls are synchronous — do NOT use async/await, and there are no imports. `sleep(ms)` waits, synchronously like everything else here. Use it to poll a generation:…
| Name | Type | Req | Description |
|---|---|---|---|
| code | string | yes | JavaScript. Tools are globals called synchronously — no async/await, no imports, no network or filesystem. `return` a value to hand it back. |
| dry_run | boolean | – | Read-only tools still run; anything that writes is recorded and skipped. Use it to check what a script would do before it does it. |
| idempotency_key | string | – | Pass a unique string so a retry cannot run the same build twice. If a script with this key already ran in this workspace, its job is returned and nothing executes again — including when that run FAIL… |
| timeout_seconds | integer | – | Wall-clock budget, default 45s. Raise it only if your client's own request timeout is longer — many cut off at 60s, and a script killed by the client reports nothing at all. Watch the slow tools: ana… |
| wait_seconds | integer | – | How long to hold this call open waiting for the script, default 45s. If it finishes in time you get the result here; if not you get a job_id to poll with get_script_job, and the script keeps running… |
No output schema declared.
No examples provided.
set_voice Set voice ~165
Set the voiceover voice for every clip in a project. Use this to apply a clueprint's voice (read `voiceover.voice.name` and `voiceover.voice.engine` from the clueprint source data), or to switch all clips to a specific voice in one call. The voice is looked up by name + engine; lookup is case-insensitive on the name. Common engines: 'eleven' (ElevenLabs), 'cartesia', 'google'.
| Name | Type | Req | Description |
|---|---|---|---|
| project_id | string | yes | The project (guide) ID |
| voice_engine | string | yes | Voice engine — 'eleven', 'cartesia', 'google', etc. |
| voice_name | string | yes | Voice name as stored in the voices table (e.g. 'Alex', 'Sofia') |
No output schema declared.
No examples provided.
split_clip Split clip ~201
Split a video clip into two clips at the given timestamp. The left clip keeps the original clip ID; the right clip gets a new ID and is inserted immediately after. Elements spanning the split point are duplicated into both clips with adjusted timing. Voiceover transcript and transcribed words are split proportionally. Concurrency: whole-project mutation (conflict domain: the entire project) — serialize. Do not run it in parallel with ANY other mutation on the same project_id, including element/voiceover edits; run them one at a time. (Mutations to different projects run in parallel freely.)
| Name | Type | Req | Description |
|---|---|---|---|
| clip_index | integer | yes | Index of the clip to split |
| project_id | string | yes | The project ID |
| split_time | number | yes | Time in seconds within the clip where to split (clip-relative, not timeline-relative). Must be > 0.1s and < clip_duration − 0.1s; values outside this range are rejected. |
No output schema declared.
No examples provided.
switch_workspace Switch active workspace ~65
Switch the active workspace. The choice sticks for this client until you change it again — including across reconnects — so every later call operates in the new workspace. Use find(type='workspaces') to see available options.
| Name | Type | Req | Description |
|---|---|---|---|
| workspaceId | string | yes | Workspace ID to switch to |
No output schema declared.
No examples provided.
update_article Update article ~97
Update article text content from markdown. Use <SCREENSHOT {id}> placeholders to position screenshots. Screenshots in the markdown are kept. Screenshots removed from markdown are deleted. Order in markdown defines final order. Get the current article first with get_article, modify the markdown, then call this.
| Name | Type | Req | Description |
|---|---|---|---|
| markdown | string | yes | Updated article content as markdown with <SCREENSHOT {id}> placeholders |
| project_id | string | yes | Project ID |
No output schema declared.
No examples provided.
update_article_media Update or inspect article media ~231
Update an article image/GIF (screenshot), or inspect its current state. - Provide one or more of `zoom_factor`, `crop`, `shapes` to change metadata. - Pass `render=true` (with no other updates) to fetch the current details without mutating. To DELETE an article image/GIF: call `update_article` with markdown that omits the `<SCREENSHOT id>` reference. Unreferenced media is pruned server-side on save. There is no separate delete tool — the markdown IS the source of truth for what's present.
| Name | Type | Req | Description |
|---|---|---|---|
| crop | object | – | Crop data: { position: [x,y], size: [w,h] } in fractional coords. |
| project_id | string | yes | Project ID. |
| render | boolean | – | If true (and no other updates supplied), returns current details and a PNG preview without mutating. |
| screenshot_id | string | yes | Screenshot ID (from get_article). |
| shapes | array | – | Array of shape objects for annotations. |
| zoom_factor | number | – | Zoom magnification (1.0 = no zoom). |
No output schema declared.
No examples provided.
update_audio Update an existing audio track ~252
Mutate fields on an existing music/SFX track by id. Read existing tracks via `get_project.audio_tracks` — the per-entry shape there matches this tool's args, so you can flip a knob (volume, fades, timing, loop) and write it back without losing the track's id. Only fields you pass are changed; omitted fields are preserved. To delete a track entirely, use `remove_from_project(target='audio')` instead.
| Name | Type | Req | Description |
|---|---|---|---|
| fade_in | number | – | Fade-in duration (seconds) |
| fade_out | number | – | Fade-out duration (seconds) |
| guide_end_time | number | – | New end time on the project timeline (seconds) |
| guide_start_time | number | – | New start time on the project timeline (seconds) |
| loop | – | – | Whether the track loops |
| music_end_time | number | – | New end offset within the source file (seconds) |
| music_id | string | yes | ID of the audio track (from get_project.audio_tracks[].id) |
| music_start_time | number | – | New start offset within the source file (seconds) |
| project_id | string | yes | The project ID |
| volume | number | – | New playback volume 0-100 |
No output schema declared.
No examples provided.
update_clips Update clips (batch) ~525
Update one or more clips in a single call — background, transition, duration, title, visibility, position, and (video clips) the footage transform via video_styling. Always batch. Each entry: { clip_index, duration?, title?, background_color? | background?, transition?, hidden?, position?, voiceover_volume?, video_styling? } - voiceover_volume: 0-100. This is how you make a clip SILENT — set 0 to mute the narration while keeping the text and its word timings. get_clip and get_project report the current value, so read it before muting to restore it later. There is no "delete voiceover" tool; muting is the supported way. - background_color: hex (keeps the existing pattern/image, changes color). background: full object from find(type='backgrounds') — replaces the whole background. - transition: { type, duration, direction?, color? }, or null to remove. Set on the OUTGOING clip — the transition plays at the END of clip_index, into the next clip. Types: circleWipe, rainbowWipe, cornerWipe, stack, colorWipe, dissolve, pushPull, fadeToColor. Directions: rainbowWipe/cornerWipe take topLeft|topRight|bottomLeft|bottomRight; colorWipe left|right; stack/pushPull left|right|top|bottom. - position: move the clip to a new zero-based index. Moves apply FIRST (in array order), then property patches — keep reorders in a separate call from property edits so indices stay predictable. - video_styling (VIDEO CLIPS ONLY — ignored on slide clips): reposition/resize the clip's recording on the canvas, e.g. into a designed window slot. { position?: [cx, cy], size?: [w, h] } as canvas fractions 0–1 ([1,1] = full-bleed, position is the footage CENTER), plus crop? and border?. Fields merge onto the clip's existing video_styling. Concurrency: parallel-safe per clip — all property updates land in ONE save. Safe to fan out across DIFFERENT clips. Do NOT run concurrently with element/voiceover edits on the SAME clip, or whole-project mutations (add_clips, add_audio, update_project). When adding…
| Name | Type | Req | Description |
|---|---|---|---|
| project_id | string | yes | Project ID |
| updates | array | yes | One entry per clip to update. |
No output schema declared.
No examples provided.
update_clueprint Update clueprint ~267
Update a clueprint's metadata and/or file contents in one call. Metadata fields (`name`, `description`, `tags`, `visibility`, `thumbnail_path`) are applied as a patch — only the fields you pass change. Pass at least one to update metadata. `files` is a list of file mutations: - Write text: `{ path, content }` - Write binary: `{ path, content, encoding: "base64" }` - Write from URL: `{ path, source_url }` (presigned URL, e.g. from get_clip with save=true) - Delete: `{ path, content: null }` You can mix writes and deletes in a single call. Existing files at the same path are overwritten.
| Name | Type | Req | Description |
|---|---|---|---|
| clueprint_id | string | yes | ID of the clueprint to update. |
| description | string | – | New description. |
| files | array | – | File mutations — writes and deletes. Empty/omitted for metadata-only updates. |
| name | string | – | New name. |
| tags | array | – | New tags (replaces existing). |
| thumbnail_path | string | – | Relative path of a screenshot in the clueprint to use as thumbnail (e.g. 'screenshots/title-slide.png'). |
| visibility | string | – | New visibility. |
No output schema declared.
No examples provided.
update_elements Update elements ~1,146
Update many elements across one or more clips in a single tool call. Replaces the per-element tool — always batch. SEND LESS, GET BACK LESS. `defaults` carries what every item shares (clip_index, element_type, and type_data entries like font_setting or alignment) so you send it once instead of per item; each item overrides any key it sets. `returning` declares what comes back, the way `select` shapes a get_clip read — omit it for a sensible default, or pass [] for just the counts. defaults: { clip_index: 1, element_type: 'text', type_data: { font_setting: {...} } } returning: [] → { total, succeeded, failed } only returning: ['layout'] → + the measured text fit per element returning: ['qa.codes'] → + the clip audit with prose stripped from non-errors (any returning value → error findings regardless; only warnings are opt-in) Each item can update position/timing fields alone, or type-specific fields via type_data (use get_element_schema in 'update' mode to see what's settable for an element_type). Items within one call are applied in order; partial success is fine. You do NOT need clip_index here — an element_id is unique within the project, so the server locates the clip itself. Pass it only as a hint; a wrong one is corrected rather than rejected. Grouping: pass `group: "<name>"` to move an element into a named group (created on demand), or `group: ""` to pull it back out to the clip root. Several items sharing a name collect into one group — the way to tidy loose elements into units the user can move or hide together. Grouping never changes coordinates. It does affect z-order: a group's members render contiguously at the group's slot, and a NEW group takes the slot of its first member, so grouping already-adjacent elements keeps their z-position while grouping scattered ones pulls them together at the lowest member's slot. Customising a component: after add_elements(component_id=...), set its content here with type_data.parameter_va…
| Name | Type | Req | Description |
|---|---|---|---|
| defaults | object | – | Values shared by every item, sent once rather than repeated. Items win per key; type_data merges one level. E.g. defaults:{clip_index:1, element_type:'text', type_data:{font_setting:{font:'Inter',wei… |
| project_id | string | yes | Project ID |
| returning | array | – | Declare what comes back, the way get_clip's `select` shapes a read. Omit it and you get ids, the measured layout, and the clip audit in compact form — which names every problem but drops the explanat… |
| updates | array | yes | Element updates — at least one entry. |
No output schema declared.
No examples provided.
update_groups Update groups ~971
Transform, keyframe, rename, nest or lock GROUPS. A group moves, scales, rotates and fades as ONE unit, without touching any child's stored position — which is how you get a camera push instead of building the target layout twice and crossfading it. Address by `group_id`, never by name. Ids come from get_clip, or from the `group_id` that add_elements/update_elements hands back when you pass `group`. An unknown id is an error, never a silent create. There is no add_groups: a group is CREATED by putting elements in one — `add_elements(group: "hero-card")` — which also returns its id. That is not a shortcut; a group's pivot comes from its children's bounding box, so an empty group has no geometry to transform. The shortest path, in one script: const clip = get_clip({ project_id, clip_index: 2, select: ["groups"] }); const byName = new Map(clip.groups.map(g => [g.name, g.id])); update_groups({ project_id, items: [{ clip_index: 2, group_id: byName.get("hero-card"), anchor_px: [960, 540], keyframes: [ { timestamp: 0, scaleX: 1, scaleY: 1 }, { timestamp: 1.2, scaleX: 2.4, scaleY: 2.4, offsetX: -400, offsetY: -120, interpolation: "easeOut" }, ], }]}); Units are canvas pixels, as everywhere else: `offset_px`, `blur_px` and `anchor_px` are pixels; `scale` is a multiplier; `rotation`/`rotate` are degrees; `opacity` is 0-100. `anchor_px` is the pivot everything rotates and scales about. Give it as a point on the canvas — the server converts it to a fraction of the group's child bounding box and reports back both that fraction and the box, so you can check it. Default is the box's centre. Set it when you want a push that favours one corner. Only fields you pass are changed. `keyframes: []` CLEARS every track; omitting `keyframes` leaves them alone; a non-empty list replaces only the properties it names. `parent_group_id: ""` moves a group to the clip root; omitting it leaves the parent alone. Keyframable: offsetX, offsetY,…
| Name | Type | Req | Description |
|---|---|---|---|
| items | array | yes | One entry per group to update |
| project_id | string | yes | The project ID |
| returning | array | – | Declare what comes back, the way get_clip's `select` shapes a read. Omit it and you get ids, the measured layout, and the clip audit in compact form — which names every problem but drops the explanat… |
No output schema declared.
No examples provided.
update_project Update project ~391
Update a project's metadata: rename, change description, move to a different folder, or change aspect ratio. Only fields you provide are changed. To move a project to the workspace root, pass folder_id="" (empty string). Aspect ratio: pass any "W:H" (positive integers). The canvas is fit inside 1920×1080 keeping the ratio, so element pixel coordinates use the resulting canvas. Common values: - "16:9" → 1920×1080 (landscape, YouTube/web — default) - "9:16" → 608×1080 (portrait — TikTok/Reels/Shorts) - "1:1" → 1080×1080 (square — Instagram feed) - "3:4" → 810×1080 (portrait card) - "4:5" → 864×1080 (portrait — Instagram feed) Element coordinates are stored as fractions of the canvas, so existing elements reflow to the new canvas automatically — no element coordinates are rewritten. Concurrency: whole-project mutation (conflict domain: the entire project) — serialize. Do not run it in parallel with ANY other mutation on the same project_id, including element/voiceover edits; run them one at a time. (Mutations to different projects run in parallel freely.)
| Name | Type | Req | Description |
|---|---|---|---|
| aspect_ratio | string | – | New aspect ratio as 'W:H' (positive integers). Common: '16:9' landscape, '9:16'/'4:5'/'3:4' portrait, '1:1' square. |
| description | string | – | New description |
| folder_id | string | – | New folder ID. Pass '' (empty string) to move to workspace root. |
| project_id | string | yes | The project ID to update |
| title | string | – | New project title |
No output schema declared.
No examples provided.
upload_file Upload file ~666
Upload one or more files to Clueso. Three modes — pick by client + where the file lives: 1. **file_name** — HOSTED upload, the default for any non-UI / programmatic upload (Claude Code, Cursor, Claude Desktop, scripts). Returns an upload URL on Clueso's OWN base domain + a ready-to-run curl that streams a single local file to it; Clueso relays the bytes to storage server-side. The PUT targets the base domain — NOT cloud storage directly — so it works on desktop/agent clients that can't reach or are blocked from S3. Requirement: the client must be able to PUT bytes to the Clueso base domain (run the returned curl, or any HTTP PUT). The agent (or the user at a shell prompt) runs the curl. Prefer this whenever there's no human at a browser. 2. **file_url**: Pass a public https URL. Server fetches and stages the file. Returns mcp_upload_id immediately. Use when the file is already on the open web — no user interaction needed. 3. **request_hosted_upload** (UI mode — use ONLY when a human should pick files in a browser: many files at once, or a host with no shell / no PUT capability): Returns a single upload_token + upload_page URL. Share the link with the user; they open it in a new browser tab, drop their files, click Done. Then call check_uploads(upload_token) to retrieve all mcp_upload_ids. Call once for all files. Hosted uploads cover any number of files per call: one call issues one upload_token, and that token covers every file the user drops on the page. Repeat calls issue additional tokens, each tracking only its own files. The returned mcp_upload_id (prefixed `mup_`) can be passed to: - add_elements / update_elements (image or video → an element ON a clip: pass it as `type_data.mcp_upload_id`, on either tool — this is how a local image becomes on-canvas content, and how an existing element's source is swapped). To fill an animation's image slot, pass it inside `type_data.parameter_values` on update_elements only — parameter_values is an update-path field and…
| Name | Type | Req | Description |
|---|---|---|---|
| file_name | string | – | File name with extension. Returns a Clueso upload URL + curl command that streams this single local file to us (single file). |
| file_names | array | – | List of file names the user will upload (for hosted mode). Shown on the upload page as guidance. |
| file_url | string | – | Public URL to fetch the file from |
| request_hosted_upload | boolean | – | If true, returns a hosted upload page. Call once for all files — the page accepts multiple uploads under one token. |
No output schema declared.
No examples provided.
voiceover_batch Set voiceover scripts ~537
Set voiceover text and/or trigger speech generation for any number of clips in a single call. Each entry chooses its own action: - "set_text" — set transcript for a clip (clip_index + text) - "generate_speech" — async TTS for a clip (returns immediately) - "set_and_generate" — set text and kick off TTS in one entry (+ text) Address a clip the same way as everywhere else: `clip_index`. Pass `clip_id` instead if you already have it — it survives clips being inserted or reordered mid-build — but you never need both; whichever you omit is looked up once for the whole call. Entries within one call are applied in order. Returns one result object per input entry. All text-set actions land in ONE save; the TTS for generate/set_and_generate runs async per clip after. IMPORTANT — generating speech RESCALES the whole clip, it does not clamp it: when audio is generated (generate_speech / set_and_generate), the clip's duration is reset to the spoken audio length, and then EVERY element on that clip is retimed proportionally by (new duration ÷ old duration). start_time, end_time and every keyframe timestamp are multiplied by that factor. Nothing is merely truncated — on a 6s clip that becomes 1.02s, an animation you placed at [0, 1.6] ends up at [0, 0.27]. Zoom elements whose window falls under the minimum after scaling are DROPPED entirely. Generation is async, so this lands AFTER this call has already returned success. So: generate speech BEFORE placing time-sensitive elements, or size them against estimate_duration first — then re-read the clip and check what your elements actually became, not just the clip duration. Concurrency: parallel-safe (conflict domain: a clip's voiceover). The server merges each clip's voiceover under a per-guide lock and preserves that clip's elements, so you can fan voiceover work out across subagents by clip — and it's safe to run alongside element edits. Two concurrent edits to the SAME clip's voiceover do not last-write-win — bo…
| Name | Type | Req | Description |
|---|---|---|---|
| entries | array | yes | Voiceover entries — at least one. |
| project_id | string | yes | Project ID |
No output schema declared.
No examples provided.
What is the Clueso MCP server?
Clueso is an MCP server listed in the public MCP registry as io.clueso/video. Make videos and docs with your AI agent, describe what you need, every output stays editable. This page covers its hosted endpoint (https://connect.clueso.io/mcp).
Is the Clueso MCP server safe to use?
Clueso scores 91 out of 100 on VerifyMCP. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.
What tools does the Clueso MCP server expose?
Clueso exposes 44 tools: get_design_guide, create_project, update_project, duplicate_project, export_project, and 39 more. Their descriptions and schemas cost roughly 20,422 tokens of context every time the server is loaded.
Does the Clueso MCP server require authentication?
Yes. Clueso asked us for credentials when we connected, so you will need to authorise it in your MCP client before it can do anything.
Is the Clueso MCP server still maintained?
Clueso is still listed as active in the MCP registry. We last reached this channel on 20 September 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.