{"ok":true,"site":{"host":"duet-canvas.vercel.app","url":"https://duet-canvas.vercel.app/","type":"live","desc":"A collaborative canvas to create with AI, not around it, through WebMCP.","tools":[{"name":"get_document_state","kind":"answer","impl":"imperative","description":"Returns the active illustration surface, current selection, editable layers, and sent Agent edit bundle. This includes temporary cel layers while Illustrate cel is active in Animate. When agentEdit.ready is true, call prepare_ai_edit. Never use browser controls, clicks, drags, or local canvas drawing as a fallback.","title":"Inspect DUET document — WebMCP-only editing policy","hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"get_animation_state","kind":"answer","impl":"imperative","description":"Returns the animation canvas, tracks, selected cel-clip target range, adaptive sample manifest, supported coloured vector shapes, and whether the user pressed Send sampled frames. This call returns metadata only. If aiClipRequest.ready is false, ask the user to choose the Agent target arrow, select a cel range, and send it; do not insert anything.","title":"Inspect DUET animation and Agent target request","hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"create_layer","kind":"act","impl":"imperative","description":"Creates a transparent paint layer and makes it active on the current illustration surface, including Illustrate cel. This is not a fallback for a blocked AI edit.","title":"Create an editable layer","inputSchema":{"type":"object","properties":{"name":{"type":"string","description":"Short layer name"}}},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_active_tool","kind":"act","impl":"imperative","description":"Selects the transform, layer lasso, brush, eraser, smudge, blur, text, eyedropper, region selection, or pan tool on the active illustration surface. Do not use it or the browser UI to make a substitute manual edit when the requested AI edit is blocked.","title":"Choose an editing tool","inputSchema":{"type":"object","properties":{"tool":{"type":"string","enum":["select","layer-lasso","transform","brush","eraser","smudge","blur","text","eyedropper","pan"]}},"required":["tool"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"select_region","kind":"act","impl":"imperative","description":"Creates the region that the next AI edit should modify on the active illustration surface. It does not authorize a browser-control or manual-canvas fallback.","title":"Select a canvas region","inputSchema":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"},"width":{"type":"number"},"height":{"type":"number"}},"required":["x","y","width","height"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"prepare_ai_edit","kind":"act","impl":"imperative","description":"Returns the frozen edit target crop, active-layer crop, mask, placement, and every ordered context reference from the active illustration surface, including temporary cel layers. Context images are reference-only. If the user has not sent a bundle, ask them to add selections and press Send to agent.","title":"Prepare the sent Agent edit bundle","inputSchema":{"type":"object","properties":{"prompt":{"type":"string","description":"Optional visual edit instruction. Omit to let the agent decide."}}},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"insert_ai_result","kind":"act","impl":"imperative","description":"Accepts a generated PNG, JPEG, or WebP data URL for a prepared bundle edit and creates a new editable layer on the originating illustration surface. In Illustrate cel it remains temporary until Flatten and return. Context references are never modified.","title":"Insert an agent-generated image layer","inputSchema":{"type":"object","properties":{"editId":{"type":"string","description":"Temporary ID returned by prepare_ai_edit"},"imageDataUrl":{"type":"string","description":"Base64 image data URL for the complete prepared target crop"},"name":{"type":"string","description":"Optional new layer name"}},"required":["editId","imageDataUrl"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"prepare_animation_edit","kind":"act","impl":"imperative","description":"Returns the frozen adaptively sampled target-cel images, a few composite scene context frames, complete cel timing, source agent recipe when available, and exact output placement. Requires the requestId from get_animation_state. Call before insert_ai_cel_clip.","title":"Prepare the sent Agent animation target frames","inputSchema":{"type":"object","properties":{"requestId":{"type":"string","description":"Exact ready request ID from get_animation_state."}},"required":["requestId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"insert_ai_cel_clip","kind":"act","impl":"imperative","description":"Validates a constrained coloured-shape and keyframe recipe, renders it into ordinary editable canvas cels for exactly the selected target duration, and inserts it nondestructively on a new visual track directly above the target. Requires prepare_animation_edit with the exact requestId first. Never submit scripts, SVG markup, URLs, or raster images.","title":"Insert an Agent vector animation as editable cels","inputSchema":{"type":"object","properties":{"requestId":{"type":"string","description":"Exact ready request ID from get_animation_state."},"name":{"type":"string","description":"Short clip name."},"durationSeconds":{"type":"number","minimum":0.01,"maximum":12,"description":"Optional compatibility hint. The selected target range always determines the exact output duration."},"celFps":{"type":"number","minimum":1,"maximum":24,"description":"Desired cel rate. DUET may lower it for longer targets so the result stays at or below 48 generated cels, while preserving the exact target duration with holds."},"objects":{"type":"array","minItems":1,"maxItems":48,"items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["line","path","rectangle","circle","polygon"]},"x":{"type":"number","description":"Rectangle or circle centre x."},"y":{"type":"number","description":"Rectangle or circle centre y."},"width":{"type":"number"},"height":{"type":"number"},"radius":{"type":"number"},"points":{"type":"array","maxItems":160,"description":"Canvas-coordinate points for a line, path, or polygon.","items":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"]}},"closed":{"type":"boolean","description":"Close a path so it may be filled."},"fillColor":{"type":"string","description":"Hex colour such as #FF6B5F, or none."},"strokeColor":{"type":"string","description":"Hex colour such as #2D1638, or none."},"strokeWidth":{"type":"number","minimum":0,"maximum":96},"opacity":{"type":"number","minimum":0,"maximum":1},"keyframes":{"type":"array","maxItems":32,"items":{"type":"object","properties":{"frame":{"type":"number","minimum":0,"description":"Zero-based cel frame."},"translateX":{"type":"number"},"translateY":{"type":"number"},"scale":{"type":"number","minimum":0.01,"maximum":20},"rotation":{"type":"number","description":"Rotation in degrees."},"opacity":{"type":"number","minimum":0,"maximum":1},"easing":{"type":"string","enum":["linear","ease-in","ease-out","ease-in-out"]}},"required":["frame"]}}},"required":["type"]}}},"required":["requestId","celFps","objects"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"merge_layer_down","kind":"act","impl":"imperative","description":"Flattens the selected layer into the layer directly beneath it on the active illustration surface.","title":"Merge the selected layer down","hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_layer_visibility","kind":"act","impl":"imperative","description":"Changes layer visibility without destroying its pixels on the active illustration surface.","title":"Show or hide a layer","inputSchema":{"type":"object","properties":{"layerId":{"type":"string"},"visible":{"type":"boolean"}},"required":["layerId","visible"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"}],"category":"Media & Personal","apiSurface":"spec","toolCount":11}}