{
	"name": "clueso",
	"version": "1.0.0",
	"kind": "product",
	"description": "Create and edit explainer videos, product demos, motion graphics and step-by-step documentation. Describe what you need and every output stays fully editable afterwards, by you or by an agent.",
	"icon": "https://www.clueso.io/icon.png",
	"url": "https://connect.clueso.io/mcp",
	"transport": "streamable-http",
	"documentationUrl": "https://www.clueso.io/mcp",
	"protocolVersion": "2025-06-18",
	"instructions": "Clueso Connect creates and edits explainer videos and motion graphics. Use these tools when the user wants to produce, update, or manage a video project.\n\nWhen composing a clip's visuals, design for the medium — a video frame isn't a web page or a slide. If you're building from a clueprint, follow its design; otherwise call `get_design_guide` before composing.\n\nBefore creating anything: `find(type='workspaces')` to confirm the active workspace. A workspace is created automatically on first connect, so this won't be empty for a normal account.\n\nWhen the user wants a video, look for a relevant template FIRST: call `find(type='clueprints', query='<what the user wants>')` and, if there are strong matches, show the best 2-3 and ask whether to build from one — before building from scratch. Skip only if the user asked to start blank or already named a clueprint. Details under \"Producing a video from a clueprint\" below.\n\n## Producing a video from a clueprint\nClueprints are reusable templates with pre-designed clip layouts and voiceover patterns.\n0. SUGGEST FIRST (unless the user asked to start blank or described a fully custom design): call `find(type='clueprints', query='<the kind of video the user wants>')`. Results are relevance-ranked across the user's workspace + the community library. If there are strong matches, show the top 2-3 — name, what it's for (search_summary), why it fits (relevance_reason), and whether it's a community template (is_community) — and ask whether to build from one or start blank. If matches are weak/empty, just proceed.\n1. Once a clueprint is chosen: `get_clueprint(include='tree')` for the file layout → `get_clueprint(include='files', file_paths=[...])` for every `data.json` you need. (Or use an ID the user gave you directly.)\n2. `create_project` with a title.\n3. `add_clips(kind='blank', clips=[...])` — one entry per clueprint clip.\n4. For each clip: `add_elements` to place content (clueprint data uses fractional [0..1] coords; multiply by the project's canvas dimensions for pixel positions — 1920×1080 for the default 16:9, but call `get_project` for other aspect ratios such as 9:16 or 1:1 which use smaller canvases), `update_clips` for background, `voiceover_batch` for narration. Call `get_element_schema` first if you don't know the `type_data` shape for a given `element_type`.\n5. For animation clips: `generate_media(kind='animation', prompt=...)` with a SPECIFIC prompt describing the exact UI elements, interaction sequence, timing feel, and visual style. Vague prompts produce bad output. (Full guide: resource `clueso://docs/animation-prompts`.)\n6. For AI images: `generate_media(kind='image', prompt=..., style_id=...)`. Pick a style from `find(type='image_gen_style_packs')` — see resource `clueso://docs/generation-styles`.\n7. For video clips with source recordings: run `auto_sync` BEFORE generating TTS so the voiceover paces against the demo. See resource `clueso://docs/sync-points`.\n8. `get_clip(select=[], render={})` to preview, iterate.\n9. Share the `projectUrl` (returned by `create_project`) when done.\n\n## Authoring a NEW clueprint\nStructure it like a polished design document — never a code dump.\n- Folder layout: `README.md` (overview), `design/` (colors.md, typography.md, backgrounds.md, animation.md), `layouts/` (one .md per distinct clip layout, named by purpose not clip index — e.g. `title-slide.md`, not `clip-0.md`), `rules/` (composition.md, voiceover.md, editing.md), `screenshots/`.\n- Markdown only — no JSON or config files.\n- Every layout file MUST start with the rendered screenshot: `![Title Slide](../screenshots/title-slide.png)`. To capture: call `get_clip(select=[], render={save: true})` per clip, then `update_clueprint(files=[...])` with the returned `presigned_url` as `source_url`.\n- Set the clueprint thumbnail via `update_clueprint(thumbnail_path=...)` after screenshots exist.\n- Full authoring guide (folder details, anti-patterns, color-block syntax): resource `clueso://docs/clueprint-authoring`.",
	"capabilities": {
		"tools": true,
		"resources": true
	},
	"authentication": {
		"required": true,
		"schemes": [
			"oauth2"
		],
		"protectedResourceMetadata": "https://connect.clueso.io/.well-known/oauth-protected-resource",
		"authorizationServers": [
			"https://auth.clueso.io/oauth/2.1"
		],
		"anonymousDiscovery": true
	},
	"tools": [
		{
			"name": "get_design_guide",
			"title": "Get design guide",
			"description": "Clueso's house style for composing video clips — how to think about concept, typography, color, composition, motion, and pacing.",
			"readOnly": true,
			"destructive": false
		},
		{
			"name": "create_project",
			"title": "Create project",
			"description": "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).",
			"readOnly": false,
			"destructive": false
		},
		{
			"name": "update_project",
			"title": "Update project",
			"description": "Update a project's metadata: rename, change description, move to a different folder, or change aspect ratio. Only fields you provide are changed.",
			"readOnly": false,
			"destructive": false
		},
		{
			"name": "duplicate_project",
			"title": "Duplicate project",
			"description": "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.",
			"readOnly": false,
			"destructive": false
		},
		{
			"name": "export_project",
			"title": "Export project",
			"description": "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.",
			"readOnly": false,
			"destructive": false
		},
		{
			"name": "find",
			"title": "Find resources",
			"description": "Find any resource in Clueso by type, optionally filtered by name or exact id. One tool for listing and searching across the workspace.",
			"readOnly": true,
			"destructive": false
		},
		{
			"name": "switch_workspace",
			"title": "Switch active workspace",
			"description": "Switch the active workspace for this session. Use find(type='workspaces') to see available options.",
			"readOnly": false,
			"destructive": false
		},
		{
			"name": "get_project",
			"title": "Get project data",
			"description": "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 pr…",
			"readOnly": true,
			"destructive": false
		},
		{
			"name": "get_clip",
			"title": "Get clip details",
			"description": "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.",
			"readOnly": true,
			"destructive": false
		},
		{
			"name": "update_clips",
			"title": "Update clips (batch)",
			"description": "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.",
			"readOnly": false,
			"destructive": true
		},
		{
			"name": "remove_clip",
			"title": "Remove clip",
			"description": "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.",
			"readOnly": false,
			"destructive": true
		},
		{
			"name": "split_clip",
			"title": "Split clip",
			"description": "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.",
			"readOnly": false,
			"destructive": false
		},
		{
			"name": "duplicate_clip",
			"title": "Duplicate a clip",
			"description": "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`).",
			"readOnly": false,
			"destructive": false
		},
		{
			"name": "add_clips",
			"title": "Add clips to project",
			"description": "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?}, ...]`.",
			"readOnly": false,
			"destructive": false
		},
		{
			"name": "get_element_schema",
			"title": "Get element schema",
			"description": "Return the JSON schema for an element type's type_data. Call this before add_elements / update_elements when you don't already know the field shape for the element_type you're p…",
			"readOnly": true,
			"destructive": false
		},
		{
			"name": "add_elements",
			"title": "Add elements to clips",
			"description": "Add many elements across one or more clips in a single tool call. Replaces the per-element tool — always batch. Use after calling get_element_schema to confirm the type_data shape per element_type.",
			"readOnly": false,
			"destructive": false
		},
		{
			"name": "update_elements",
			"title": "Update elements",
			"description": "Update many elements across one or more clips in a single tool call. Replaces the per-element tool — always batch.",
			"readOnly": false,
			"destructive": true
		},
		{
			"name": "remove_elements",
			"title": "Remove elements from clips",
			"description": "Remove many elements across one or more clips in a single tool call. One entry per element ({clip_index, element_id}).",
			"readOnly": false,
			"destructive": true
		},
		{
			"name": "reorder_elements",
			"title": "Reorder elements within a clip",
			"description": "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.",
			"readOnly": false,
			"destructive": false
		},
		{
			"name": "remove_from_project",
			"title": "Remove element or audio track",
			"description": "Remove an element or audio track from a project. - target=\"element\": removes an element from a clip (requires clip_index + element_id) - target=\"audio\": removes a music/SFX trac…",
			"readOnly": false,
			"destructive": true
		},
		{
			"name": "add_audio",
			"title": "Add audio track",
			"description": "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.",
			"readOnly": false,
			"destructive": false
		},
		{
			"name": "update_audio",
			"title": "Update an existing audio track",
			"description": "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 k…",
			"readOnly": false,
			"destructive": false
		},
		{
			"name": "voiceover_batch",
			"title": "Set voiceover scripts",
			"description": "Set voiceover text and/or trigger speech generation for any number of clips in a single call.",
			"readOnly": false,
			"destructive": true
		},
		{
			"name": "auto_sync",
			"title": "Auto-generate sync points",
			"description": "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.",
			"readOnly": false,
			"destructive": true
		},
		{
			"name": "add_sync_point",
			"title": "Add a sync point at a word + timestamp",
			"description": "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\").",
			"readOnly": false,
			"destructive": false
		},
		{
			"name": "upload_file",
			"title": "Upload file",
			"description": "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).",
			"readOnly": false,
			"destructive": false
		},
		{
			"name": "check_uploads",
			"title": "Check upload status",
			"description": "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.).",
			"readOnly": true,
			"destructive": false
		},
		{
			"name": "generate_media",
			"title": "Generate AI media (image or animation)",
			"description": "Generate an AI image or canvas-code-based animation directly into a clip. - kind=\"image\": text-to-image. Pass `prompt`.",
			"readOnly": false,
			"destructive": false
		},
		{
			"name": "estimate_duration",
			"title": "Estimate clip duration",
			"description": "Estimate voiceover duration for one or many clips at once (~150 words/minute). Pass an array of voiceover texts — one per clip.",
			"readOnly": true,
			"destructive": false
		},
		{
			"name": "analyze_audio",
			"title": "Analyze audio",
			"description": "Analyze an audio file. Modes: - transcript: Speech-to-text with word-level timestamps. Works on BOTH speech and sung lyrics — routes to a music-aware provider when content is detected as music.",
			"readOnly": true,
			"destructive": false
		},
		{
			"name": "get_article",
			"title": "Get article",
			"description": "Get the article content as markdown. Screenshots appear as <SCREENSHOT {id}> placeholders. Returns the markdown text and a list of screenshot IDs.",
			"readOnly": true,
			"destructive": false
		},
		{
			"name": "update_article",
			"title": "Update article",
			"description": "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.",
			"readOnly": false,
			"destructive": false
		},
		{
			"name": "add_article_media",
			"title": "Add article media (image or GIF)",
			"description": "Add a screenshot or GIF to the article. Returns a screenshot_id to place in the article via update_article using `<SCREENSHOT screenshot_id>`.",
			"readOnly": false,
			"destructive": false
		},
		{
			"name": "update_article_media",
			"title": "Update or inspect article media",
			"description": "Update an article image/GIF (screenshot), or inspect its current state. - Provide one or more of `zoom_factor`, `crop`, `shapes` to change metadata.",
			"readOnly": false,
			"destructive": false
		},
		{
			"name": "create_clueprint",
			"title": "Create clueprint",
			"description": "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.",
			"readOnly": false,
			"destructive": false
		},
		{
			"name": "get_clueprint",
			"title": "Get clueprint",
			"description": "Fetch clueprint data. Use `include` to control how much you pull back: - include=\"metadata\": just the clueprint's name/description/tags/visibility/thumbnail.",
			"readOnly": true,
			"destructive": false
		},
		{
			"name": "update_clueprint",
			"title": "Update clueprint",
			"description": "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.",
			"readOnly": false,
			"destructive": true
		},
		{
			"name": "set_voice",
			"title": "Set voice",
			"description": "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 da…",
			"readOnly": false,
			"destructive": false
		},
		{
			"name": "add_comment",
			"title": "Add comment",
			"description": "Post a review comment on a project, attributed to \"Clueso AI\".",
			"readOnly": false,
			"destructive": false
		},
		{
			"name": "record_screen",
			"title": "Record screen",
			"description": "Create a screen-recording clip in a project. Creates blank placeholder clips, registers job entities, and sends the job to AVS.",
			"readOnly": false,
			"destructive": false
		}
	]
}
