{"ok":true,"site":{"host":"estro-webmcp.vercel.app","url":"https://estro-webmcp.vercel.app/","type":"live","desc":"A photo editor that does not assume you know what saturation means. Describe what you want and an agent moves the real controls, then tells you which ones and what they do. Everything stays in your…","tools":[{"name":"get_capabilities","kind":"answer","impl":"imperative","description":"Report what Estro can actually do in this browser right now, with import, decode, proxy, preview, video encode, audio encode, mux, worker, durable storage, and fallback support reported separately. Never changes a project.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{},"required":[]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"list_projects","kind":"answer","impl":"imperative","description":"List the Estro projects in this browser, newest first, with the id every other tool needs. Start here: nearly every tool takes a projectId, and there is no other way to discover one. Reports whether each project holds an image document, sequences, or media, and whether it has an unsaved draft to recover, so a caller can pick the right one without opening each in turn. Never changes anything.","annotations":{"readOnlyHint":true,"untrustedContentHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"limit":{"type":"integer","minimum":1,"maximum":50,"default":20,"description":"How many projects to return."},"query":{"type":"string","maxLength":120,"description":"Case-insensitive match against the project name."},"kind":{"enum":["photo","video","unassigned"],"description":"Only projects of this kind."}},"required":[]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"inspect_project","kind":"answer","impl":"imperative","description":"Inspect one local Estro project, its durable revision, recovery state, snapshots, media, sequences, and a bounded transaction history. This never mutates the project.","annotations":{"readOnlyHint":true,"untrustedContentHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1},"historyLimit":{"type":"integer","minimum":1,"maximum":20,"default":8}},"required":["projectId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"manage_project","kind":"act","impl":"imperative","description":"Create, rename, duplicate, save, Save As, snapshot, or request deletion of a local Estro project. Deletion always pauses for visible user confirmation. Use create_sample when the user has no media of their own: a browser cannot open a file without a user gesture, so create_sample builds a photo project from a bundled photograph and returns its ids, giving you something real to edit in one call. Pass `sample` to choose which photograph; omit it for the first. Each was picked for a different problem, so choose the one whose difficulty matches what the user wants to learn to change.","annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":false,"openWorldHint":false,"untrustedContentHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"operation":{"enum":["create","create_sample","rename","duplicate","save","save_as","snapshot","request_delete"]},"sample":{"type":"string","enum":["sindhudurg","city","deer","quarry"],"description":"sindhudurg — Greens and a blue sky. Good for saturation and for seeing what temperature does. city — A blue cast over a busy street. The one to practise white balance on. deer — Mist, low contrast, almost no colour. Good for exposure and for shadows. quarry — Flat grey overcast with fine detail. Good for contrast and for sharpening."},"projectId":{"type":"string"},"name":{"type":"string","minLength":1,"maxLength":120},"expectedRevisionId":{"type":"string","minLength":1,"description":"Refuse the command if the project has moved past this revision. Accepted by every operation except create."}},"required":["operation"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"propose_transaction","kind":"act","impl":"imperative","description":"Validate and normalize an ordered Estro project transaction without mutating the project. The proposal expires and is bound to its source revision.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1},"operations":{"type":"array","minItems":1,"maxItems":10,"items":{"oneOf":[{"type":"object","additionalProperties":false,"properties":{"type":{"const":"rename_project"},"name":{"type":"string","minLength":1,"maxLength":120}},"required":["type","name"]},{"type":"object","additionalProperties":false,"properties":{"type":{"const":"create_snapshot"},"name":{"type":"string","minLength":1,"maxLength":120}},"required":["type","name"]}]}}},"required":["projectId","operations"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"apply_transaction","kind":"act","impl":"imperative","description":"Atomically apply one reviewed Estro proposal if its source revision is still current. A stale or invalid proposal changes nothing.","annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"proposalId":{"type":"string","minLength":1}},"required":["proposalId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"inspect_transaction","kind":"answer","impl":"imperative","description":"Explain one Estro transaction, including actor, intent, operations, warnings, source revision, resulting revision, and Undo identity.","annotations":{"readOnlyHint":true,"untrustedContentHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"transactionId":{"type":"string","minLength":1}},"required":["transactionId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"list_presets","kind":"answer","impl":"imperative","description":"List reusable presets and project templates available here, with the attributes each carries, its version, and whether it ships with Estro. Never changes anything.","annotations":{"readOnlyHint":true,"untrustedContentHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1},"domain":{"enum":["layer","document","project","brush","effect_stack"]}},"required":[]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"save_preset","kind":"act","impl":"imperative","description":"Save a named, reusable bundle of attributes, either from an existing object or from explicit parameters. Re-saving an existing preset raises its version rather than replacing it silently. Presets that ship with Estro cannot be overwritten.","annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false,"untrustedContentHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":80},"domain":{"enum":["layer","document","project","brush","effect_stack"]},"description":{"type":"string","maxLength":240},"projectId":{"type":"string","minLength":1,"description":"Set to keep the preset inside one project; omit to make it available everywhere."},"presetId":{"type":"string","minLength":1,"description":"Update this preset instead of creating a new one."},"fromTargetId":{"type":"string","minLength":1,"description":"Read the attributes from this object."},"attributes":{"type":"array","items":{"type":"string"},"description":"Which attribute names to take from the object."},"parameters":{"type":"object","description":"Explicit attribute values, instead of reading an object."},"expectedRevisionId":{"type":"string","minLength":1,"description":"With fromTargetId: refuse if the project has moved past this revision, so the copied attributes are the ones you inspected."}},"required":["name","domain"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"apply_batch","kind":"act","impl":"imperative","description":"Apply one bundle of attributes to many objects at once, from a preset or from explicit parameters. Plans by default: every target is costed and the result says which would change, which would not, and why. Set apply to true to commit, as a single transaction and a single Undo step. The failure policy decides whether a batch that cannot reach every target proceeds at all.","annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1},"domain":{"enum":["layer","document","project","brush","effect_stack"]},"targetIds":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"maxItems":500},"presetId":{"type":"string","minLength":1},"parameters":{"type":"object","description":"Explicit attribute values, instead of a preset."},"policy":{"enum":["all_or_nothing","best_effort"],"default":"all_or_nothing"},"expectedRevisionId":{"type":"string"},"apply":{"type":"boolean","default":false}},"required":["projectId","domain","targetIds"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"inspect_history","kind":"answer","impl":"imperative","description":"Read a project's history: every transaction with its actor, intent, summary, affected objects, warnings, and revision pair, plus its named snapshots and which entries can be reverted on their own. Never changes anything.","annotations":{"readOnlyHint":true,"untrustedContentHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1},"limit":{"type":"integer","minimum":1,"maximum":200,"default":50}},"required":["projectId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"revert_transaction","kind":"act","impl":"imperative","description":"Revert one past change that need not be the most recent. Plans by default and reports whether the revert is safe, which later changes block it, and over which objects; set apply to true to commit it. The reversal is recorded as a new transaction, so history is never rewritten.","annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1},"transactionId":{"type":"string","minLength":1},"expectedRevisionId":{"type":"string"},"apply":{"type":"boolean","default":false}},"required":["projectId","transactionId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"undo_transaction","kind":"act","impl":"imperative","description":"Undo the latest safe Estro transaction by immutable transaction ID, or return a structured dependency conflict without changing the project.","annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1},"transactionId":{"type":"string","minLength":1},"expectedRevisionId":{"type":"string","minLength":1,"description":"Refuse the undo if the project has moved past this revision."}},"required":["projectId","transactionId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"inspect_document","kind":"answer","impl":"imperative","description":"Inspect the current image document, exact dimensions, resolution, background, stable ID, and project revision without changing project or workspace state.","annotations":{"readOnlyHint":true,"untrustedContentHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1}},"required":["projectId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"apply_document_operation","kind":"act","impl":"imperative","description":"Create one empty non-destructive image document in a photo or unassigned project through Estro's shared revision and Undo engine.","annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1},"expectedRevisionId":{"type":"string","minLength":1,"description":"Optional. Refuse if the project has moved past this revision."},"widthPx":{"type":"integer","minimum":1,"maximum":32768},"heightPx":{"type":"integer","minimum":1,"maximum":32768},"resolutionPpi":{"type":"number","minimum":1,"maximum":2400},"orientation":{"enum":["landscape","portrait","square"]},"background":{"oneOf":[{"type":"object","additionalProperties":false,"properties":{"type":{"const":"transparent"}},"required":["type"]},{"type":"object","additionalProperties":false,"properties":{"type":{"const":"solid"},"color":{"type":"string","pattern":"^#[0-9a-fA-F]{6}$"}},"required":["type","color"]}]}},"required":["projectId","widthPx","heightPx","resolutionPpi","orientation","background"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"resize_document","kind":"act","impl":"imperative","description":"Resize the canvas frame or resample the whole image, with an explicit anchor, resampling algorithm, and aspect lock. Returns the normalized size, the algorithm actually used, the resampling job IDs it started, and any content that now falls outside the frame. A canvas resize reports no algorithm because it resamples nothing.","annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1},"mode":{"enum":["canvas","image"]},"widthPx":{"type":"integer","minimum":1,"maximum":32768},"heightPx":{"type":"integer","minimum":1,"maximum":32768},"anchor":{"enum":["top-left","top-center","top-right","middle-left","center","middle-right","bottom-left","bottom-center","bottom-right"]},"resampleAlgorithm":{"enum":["nearest","bilinear","lanczos3","browser-smooth"]},"lockAspect":{"type":"boolean"},"expectedRevisionId":{"type":"string"}},"required":["projectId","mode","widthPx","heightPx"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"inspect_workspace","kind":"answer","impl":"imperative","description":"Inspect viewport, panels, overlays, tool, selection, preview quality, active sequence, monitor context, media view, comparison, and timeline view state. Never changes the project.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1}},"required":["projectId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"set_workspace","kind":"act","impl":"imperative","description":"Set viewport, panels, dock, tool, overlays, guides, distraction-free mode, solo, isolate, preview quality, active sequence, monitor, source marks, media view, comparison, or timeline view. These are view changes and never create a project revision.","annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1},"change":{"oneOf":[{"type":"object","additionalProperties":false,"properties":{"type":{"const":"viewport"},"viewport":{"type":"object"}},"required":["type","viewport"]},{"type":"object","additionalProperties":false,"properties":{"type":{"const":"panel"},"panel":{"enum":["left","inspector"]},"open":{"type":"boolean"},"widthPx":{"type":"integer"}},"required":["type","panel"]},{"type":"object","additionalProperties":false,"properties":{"type":{"const":"dock"},"leadingPanel":{"enum":["left","inspector"]}},"required":["type","leadingPanel"]},{"type":"object","additionalProperties":false,"properties":{"type":{"const":"tool"},"tool":{"enum":["select","hand","zoom"]}},"required":["type","tool"]},{"type":"object","additionalProperties":false,"properties":{"type":{"const":"overlay"},"overlay":{"enum":["rulers","guides","grid","snapping","safeAreas","pixelGrid"]},"enabled":{"type":"boolean"}},"required":["type","overlay","enabled"]},{"type":"object","additionalProperties":false,"properties":{"type":{"const":"guide"},"action":{"enum":["add","update","remove","clear"]},"guideId":{"type":"string"},"axis":{"enum":["x","y"]},"positionPx":{"type":"number","minimum":-32768,"maximum":65536}},"required":["type","action"]},{"type":"object","additionalProperties":false,"properties":{"type":{"const":"distraction_free"},"enabled":{"type":"boolean"}},"required":["type","enabled"]},{"type":"object","additionalProperties":false,"properties":{"type":{"const":"solo"},"layerIds":{"type":"array","items":{"type":"string"},"maxItems":500}},"required":["type","layerIds"]},{"type":"object","additionalProperties":false,"properties":{"type":{"const":"isolate"},"groupId":{"type":["string","null"]}},"required":["type","groupId"]},{"type":"object","additionalProperties":false,"properties":{"type":{"const":"preview_quality"},"quality":{"enum":["draft","balanced","full"]}},"required":["type","quality"]},{"type":"object","additionalProperties":false,"properties":{"type":{"const":"active_sequence"},"sequenceId":{"type":["string","null"]}},"required":["type","sequenceId"]},{"type":"object","additionalProperties":false,"properties":{"type":{"const":"monitor"},"monitor":{"enum":["program","source"]}},"required":["type","monitor"]},{"type":"object","additionalProperties":false,"properties":{"type":{"const":"source_monitor"},"itemType":{"enum":["asset","subclip",null]},"itemId":{"type":["string","null"]},"inPointSeconds":{"type":["number","null"]},"outPointSeconds":{"type":["number","null"]}},"required":["type","itemType","itemId"]},{"type":"object","additionalProperties":false,"properties":{"type":{"const":"media_view"},"view":{"enum":["grid","list","bins","storyboard"]},"binId":{"type":["string","null"]}},"required":["type","view"]},{"type":"object","additionalProperties":false,"properties":{"type":{"const":"comparison"},"mode":{"enum":["off","hold","toggle","split","side_by_side"]},"baseline":{"enum":["original_import","previous_revision","chosen_revision"]},"revisionId":{"type":["string","null"]},"splitPosition":{"type":"number","minimum":0,"maximum":1}},"required":["type","mode"]},{"type":"object","additionalProperties":false,"properties":{"type":{"const":"timeline_view"},"pixelsPerSecond":{"type":"number"},"scrollSeconds":{"type":"number"},"snapping":{"type":"boolean"},"linkedSelection":{"type":"boolean"},"rippleMode":{"type":"boolean"},"audibleScrub":{"type":"boolean"},"trackHeightPx":{"type":"integer"}},"required":["type"]}]}},"required":["projectId","change"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"inspect_selection","kind":"answer","impl":"imperative","description":"Inspect the current selection, including multiple selected layers or clips, without changing it.","annotations":{"readOnlyHint":true,"untrustedContentHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1}},"required":["projectId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"set_selection","kind":"act","impl":"imperative","description":"Select the canvas, the document, one or more layers, clips, tracks, assets, sequences, or an output. Validated against what actually exists, and never changes project content.","annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1},"selectionType":{"enum":["none","canvas","document","layer","clip","track","asset","sequence","output"]},"targetId":{"type":["string","null"]},"targetIds":{"type":"array","items":{"type":"string"},"maxItems":500}},"required":["projectId","selectionType","targetId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"focus_ui","kind":"act","impl":"imperative","description":"Reveal and focus one stable semantic editor control so the user can see what an operation affected. Navigation only; it never changes project or workspace data.","annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1},"targetId":{"type":"string","enum":["workspace-shell","tool-select","tool-hand","tool-zoom","tool-crop","panel-layers","panel-media","panel-history","history-snapshots","media-import","media-filters","media-search","media-sort","media-view-switch","media-bins","media-storyboard","media-add-to-canvas","media-relink","media-replace","media-proxy","canvas-stage","document-canvas","crop-overlay","view-zoom","toggle-grid","comparison-toggle","preview-quality","inspector","inspector-document-width","inspector-transform","inspector-crop","inspector-align","inspector-adjustments","inspector-masks","inspector-presets","inspector-corrections","inspector-styles","inspector-tools","inspector-profiles","inspector-channels","inspector-swatches","inspector-batch","inspector-sharing","inspector-content","inspector-compositing","inspector-effects","inspector-histogram","inspector-export","export-preset","export-start","output-list","job-center","command-palette-trigger","activity-island"]}},"required":["projectId","targetId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"search_commands","kind":"answer","impl":"imperative","description":"Search every manual editor command by name, category, shortcut, or keyword, with the semantic target each one acts on. Never changes state.","annotations":{"readOnlyHint":true,"untrustedContentHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"query":{"type":"string","maxLength":120,"default":""}},"required":[]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"inspect_assets","kind":"answer","impl":"imperative","description":"Search the project's media with structured filters over kind, format, availability, editability, proxy state, duration, pixels, and bin. Returns stable IDs, technical metadata, and which fields matched. Never decodes media and never changes state.","annotations":{"readOnlyHint":true,"untrustedContentHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1},"query":{"type":"string","maxLength":120},"kinds":{"type":"array","items":{"enum":["image","video","audio"]},"maxItems":3},"mediaTypes":{"type":"array","items":{"type":"string"},"maxItems":16},"availability":{"type":"array","items":{"enum":["available","missing","permission_required","unsupported"]},"maxItems":4},"editability":{"type":"array","items":{"enum":["editable","proxy_required","import_only","unsupported"]},"maxItems":4},"proxyState":{"enum":["any","present","absent"]},"binId":{"type":["string","null"]},"minDurationSeconds":{"type":["number","null"]},"maxDurationSeconds":{"type":["number","null"]},"minPixels":{"type":["integer","null"]},"maxPixels":{"type":["integer","null"]},"sortBy":{"enum":["name","addedAt","byteSize","pixels","duration"]},"direction":{"enum":["asc","desc"]},"limit":{"type":"integer","minimum":1,"maximum":500}},"required":["projectId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"inspect_asset","kind":"act","impl":"imperative","description":"Inspect one asset by stable ID: detected container and streams, dimensions, duration, content hash, source revision, durability, editability, derivatives, and every layer, clip, and subclip that uses it.","annotations":{"readOnlyHint":true,"untrustedContentHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"assetId":{"type":"string","minLength":1}},"required":["assetId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"manage_asset","kind":"act","impl":"imperative","description":"Update tags, remove an asset through the shared Undo engine, re-check availability, or start a thumbnail, proxy, or waveform job. Importing and relinking files need the visible interface, because a browser only grants file access from a user gesture; those operations focus the right control and explain what to do.","annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":false,"openWorldHint":false,"untrustedContentHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"operation":{"enum":["update_tags","remove","refresh_availability","request_import","request_relink","plan_relink","generate_proxy","generate_thumbnail","generate_waveform"]},"candidates":{"type":"array","maxItems":2000,"description":"For plan_relink: the files available to relink from, each {key, name, byteSize, contentHash}. A key is anything that identifies the file to you; Estro only matches on it.","items":{"type":"object"}},"assetId":{"type":"string"},"projectId":{"type":"string"},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":48},"maxItems":32},"quality":{"enum":["draft","balanced"]},"expectedRevisionId":{"type":"string","minLength":1,"description":"For remove: refuse if the project has moved past this revision."}},"required":["operation"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"preview_revision","kind":"answer","impl":"imperative","description":"Render a bounded preview of one asset at a named quality and return it with the exact project revision, source revision, and the derivative's real dimensions. This is a read: it never changes project state.","annotations":{"readOnlyHint":true,"untrustedContentHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"assetId":{"type":"string","minLength":1},"quality":{"enum":["draft","balanced","full"],"default":"draft"},"focus":{"type":"boolean","default":false}},"required":["assetId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"inspect_organization","kind":"answer","impl":"imperative","description":"Inspect bins, bin membership, storyboard positions, subclips, and source markers with stable IDs. Organization is project state, so it is versioned and undoable, but this call never changes it.","annotations":{"readOnlyHint":true,"untrustedContentHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1}},"required":["projectId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"manage_organization","kind":"act","impl":"imperative","description":"Create, rename, move, or delete bins; move items between bins; set storyboard positions; reorder items; create, rename, or delete subclips; and manage source markers. Each is one reversible project mutation that never changes where media lives.","annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":false,"openWorldHint":false,"untrustedContentHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1},"operation":{"enum":["create_bin","rename_bin","move_bin","delete_bin","move_items","set_storyboard_position","reorder_item","create_subclip","rename_subclip","delete_subclip","add_source_marker","remove_source_marker"]},"binId":{"type":"string"},"parentBinId":{"type":["string","null"]},"name":{"type":"string","minLength":1,"maxLength":160},"confirm":{"type":"boolean"},"items":{"type":"array","items":{"type":"object"},"maxItems":500},"itemType":{"enum":["asset","subclip","sequence"]},"itemId":{"type":"string"},"x":{"type":["number","null"]},"y":{"type":["number","null"]},"toIndex":{"type":"integer","minimum":0},"assetId":{"type":"string"},"subclipId":{"type":"string"},"markerId":{"type":"string"},"sourceRange":{"type":"object"},"time":{"type":"object"},"comment":{"type":"string","maxLength":500},"color":{"type":"string"},"duration":{"type":["object","null"]},"expectedRevisionId":{"type":"string"}},"required":["projectId","operation"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"inspect_job","kind":"answer","impl":"imperative","description":"Inspect one job or list a project's recent jobs, with monotonic status, stage, real progress when measurable, priority, warnings, failure codes, retry eligibility, derivative and output IDs, and whether it ran off the interface thread.","annotations":{"readOnlyHint":true,"untrustedContentHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"jobId":{"type":"string","description":"Inspect this one job."},"projectId":{"type":"string","description":"List this project's recent jobs instead."},"limit":{"type":"integer","minimum":1,"maximum":50,"description":"With projectId: how many to list."}},"anyOf":[{"required":["jobId"]},{"required":["projectId"]}]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"manage_job","kind":"act","impl":"imperative","description":"Cancel a running job or retry one that failed, was cancelled, or was interrupted by a reload. Cancellation reaches the worker rather than only updating a record, and is idempotent.","annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"operation":{"enum":["cancel","retry"]},"jobId":{"type":"string","minLength":1}},"required":["operation","jobId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"inspect_layers","kind":"answer","impl":"imperative","description":"Inspect the document's layer stack: stable IDs, kind, nesting, visibility, lock, opacity, transform, crop, and active colour adjustments. Never returns pixels.","annotations":{"readOnlyHint":true,"untrustedContentHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1}},"required":["projectId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"apply_layer_operation","kind":"act","impl":"imperative","description":"Every edit to a photo layer, chosen with the operation field. Structure: add, remove, duplicate, reorder, group, ungroup, move between groups, rename, show, hide, lock. Placement: transform, crop, crop ratio, reset, quarter-turn, fit, fill, straighten, flip, align, distribute, free transform, perspective, warp, lens correction. Appearance: opacity, blend mode, clip to the layer below, masks, and an effect container holding exposure, levels, curves, vibrance, colour balance, selective colour, black and white, gradient map, photo filter, 3D LUT, shadows and highlights, replace colour, posterize, threshold, invert, equalize. Content: text, shapes, fills, adjustment layers, layer styles, brush and retouch strokes, keyframes. Everything is stored as settings and re-run at export size, so any of it can be changed or removed later. Each operation reads only the fields it needs; the rest are ignored. Alignment and grouping act only on the layers named.","annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":false,"openWorldHint":false,"untrustedContentHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1},"expectedRevisionId":{"type":"string"},"operation":{"enum":["add_image","remove","duplicate","reorder","group","ungroup","move_into_group","rename","set_visibility","set_lock","set_opacity","transform","crop","set_crop_ratio","reset_transform","rotate_quarter","fit","straighten","flip","align","distribute","set_blend_mode","set_clipping","add_mask","update_mask","remove_mask","add_effect","update_effect","remove_effect","reorder_effect","set_keyframe","remove_keyframe","set_track_enabled","clear_animation","add_text","edit_text","add_shape","set_paint","add_adjustment_layer","add_fill_layer","add_style","update_style","remove_style","free_transform","set_perspective","warp","correct_lens","apply_profile","paint_stroke","undo_stroke","restyle_stroke","fill_region"]},"content":{"type":"string","maxLength":20000,"description":"Text content for add_text or a whole-block replacement."},"range":{"type":"object","description":"Character range: start and end."},"insert":{"type":"string","maxLength":20000},"font":{"type":"object","description":"Family, weight, italic."},"sizePx":{"type":"number","minimum":1,"maximum":2000},"colour":{"type":"string","pattern":"^#[0-9a-fA-F]{6}$"},"trackingMille":{"type":"number","minimum":-500,"maximum":2000},"paragraph":{"type":"object","description":"Alignment, leading, indents, spacing, list."},"paragraphIndex":{"type":"integer","minimum":0},"layout":{"type":"object","description":"Point text, or a paragraph box with a width and height."},"shape":{"type":"object","description":"Rectangle, ellipse, polygon, or path commands."},"fill":{"type":"object"},"stroke":{"type":["object","null"]},"paint":{"type":"object","description":"Fill paint for a fill layer: solid, gradient, or a swatch."},"style":{"type":"object","description":"A layer style: kind is one of stroke, drop_shadow, inner_shadow, glow, overlay, plus that kind's own settings."},"styleId":{"type":"string"},"corners":{"type":["object","null"],"description":"Four corners in reading order — topLeft, topRight, bottomRight, bottomLeft — each {x,y} in document pixels. Null clears the correction."},"sliders":{"type":"object","description":"Perspective as angles instead of corners: verticalDeg, horizontalDeg, rotationDeg, scale."},"columns":{"type":"integer","minimum":2,"maximum":16,"description":"Warp grid width."},"rows":{"type":"integer","minimum":2,"maximum":16,"description":"Warp grid height."},"point":{"type":"object","description":"Moves one warp control point: column, row, and an offset {x,y} in fractions of the layer's size."},"clear":{"type":"boolean","description":"Removes the warp."},"correction":{"type":"object","description":"Lens correction: distortion, distortionFine, chromaticAberration, vignette, each -1 to 1."},"brush":{"type":"object","description":"Brush settings: kind (brush, pencil, eraser, clone, dodge, burn, sponge, blur, sharpen, smudge, red_eye), sizePx, hardness, flow, opacity, spacing, roundness, angleDeg, scatter. Only what is given changes."},"cloneOffset":{"type":["object","null"],"description":"For a clone stamp: {x,y}, the distance from where it paints to where it reads. Required for clone."},"strength":{"type":"number","minimum":0,"maximum":1,"description":"How strongly a retouching brush works. Not opacity: these change what is already there. Defaults to 0.5."},"dynamics":{"type":"object","description":"What the pen drives: pressureToSize, pressureToOpacity, pressureToFlow, tiltToRoundness, rotationToAngle, velocityToSize, each 0 to 1."},"points":{"type":"array","maxItems":4000,"items":{"type":"object"},"description":"Pointer samples: x, y, and optionally pressure, tiltDeg, rotationDeg, velocity. Pressure defaults to full, so a mouse draws at the brush's stated size."},"strokeId":{"type":"string"},"selectionId":{"type":"string","description":"A saved selection the stroke or fill is confined to."},"simplifyPx":{"type":"number","minimum":0,"maximum":20,"description":"Thins the points to the ones that describe the shape. 0 keeps every sample."},"propertyPath":{"type":"string","description":"An animatable property, such as transform.x or opacity."},"time":{"type":"object","description":"A rational time: numerator and denominator."},"value":{"type":"number"},"interpolation":{"enum":["linear","hold","ease_in","ease_out","ease_in_out","bezier"]},"handles":{"type":"object","description":"Bezier control handles, for custom easing."},"keyframeId":{"type":"string"},"blendMode":{"enum":["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity"]},"clipToBelow":{"type":"boolean"},"mask":{"type":"object","description":"Mask source, feather, density, inverted, and enabled."},"maskId":{"type":"string"},"effectId":{"type":"string"},"enabled":{"type":"boolean"},"parameters":{"type":"object","description":"Adjustment values for an effect or an adjustment layer."},"profile":{"type":"object","description":"A camera profile or a creative look: id, name, kind ('camera' or 'creative'), and an ordered list of colour operations. Applied before everything else, so later edits are edits away from it. Its operations are copied onto the layer, so editing the profile later does not change photographs already developed with it."},"remove":{"enum":["camera","creative"],"description":"For apply_profile: removes the profile of that kind."},"colourOperation":{"type":"object","description":"One tone or colour operator for an effect. `kind` is one of exposure, levels, curves, vibrance, colour_balance, selective_colour, black_and_white, channel_mixer, gradient_map, photo_filter, lut, shadows_highlights, replace_colour, posterize, threshold, invert, equalize, plus that kind's own settings. Replaces the operator whole on an update, because a curve and a lookup table share no fields."},"assetId":{"type":"string"},"layerId":{"type":"string"},"groupId":{"type":["string","null"]},"layerIds":{"type":"array","items":{"type":"string"},"maxItems":500},"name":{"type":"string","minLength":1,"maxLength":120},"fit":{"enum":["fit","fill","actual"]},"mode":{"enum":["fit","fill","actual"]},"toIndex":{"type":"integer","minimum":0},"visible":{"type":"boolean"},"locked":{"type":"boolean"},"opacity":{"type":"number","minimum":0,"maximum":1},"rotationDeg":{"type":"number","minimum":-360,"maximum":360},"turns":{"type":"integer","minimum":-3,"maximum":3},"ratio":{"type":["number","null"]},"axis":{"enum":["horizontal","vertical"]},"edge":{"enum":["left","horizontal-center","right","top","vertical-center","bottom"]},"reference":{"enum":["canvas","selection","key-layer"]},"keyLayerId":{"type":["string","null"]},"transform":{"type":"object"},"crop":{"type":"object"}},"required":["projectId","operation"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"inspect_color_state","kind":"answer","impl":"imperative","description":"Report every colour adjustment on a layer with its current value, documented range, unit, and a plain-language description. This never changes the project.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1},"layerId":{"type":"string","minLength":1}},"required":["projectId","layerId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"apply_color_adjustment","kind":"act","impl":"imperative","description":"Set one colour adjustment on a layer using its documented range. Values outside the range are clamped and the clamp is reported rather than applied silently.","annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1},"layerId":{"type":"string","minLength":1},"adjustment":{"enum":["brightness","contrast","temperature","tint","hue","saturation","lightness"]},"value":{"type":"number"},"expectedRevisionId":{"type":"string"}},"required":["projectId","layerId","adjustment","value"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"inspect_histogram","kind":"answer","impl":"imperative","description":"Measure the current visible composite and return binned tone distribution per channel with clipping diagnostics and a plain-language exposure reading. Returns summaries, never pixels.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1},"scale":{"type":"number","minimum":0.05,"maximum":1,"default":0.25},"revisionId":{"type":["string","null"]}},"required":["projectId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"compare_revisions","kind":"act","impl":"imperative","description":"Resolve a before-and-after comparison to a real revision pair, either from a transaction or from a chosen baseline, and optionally set the interface's comparison mode. Returns identifiers, never pixels.","annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"untrustedContentHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1},"fromTransactionId":{"type":"string"},"baseline":{"enum":["original_import","previous_revision","chosen_revision"]},"revisionId":{"type":["string","null"]},"mode":{"enum":["off","hold","toggle","split","side_by_side"]},"apply":{"type":"boolean","default":false}},"required":["projectId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"explain_edit","kind":"answer","impl":"imperative","description":"Explain a transaction, layer, clip, sequence, or colour parameter: what it does, its current value, the visible consequence, whether it can be undone, and where its control lives. This is a read and never changes the project.","annotations":{"readOnlyHint":true,"untrustedContentHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1},"transactionId":{"type":"string"},"layerId":{"type":"string"},"clipId":{"type":"string"},"sequenceId":{"type":"string"},"adjustment":{"type":"string"}},"required":["projectId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"guided_step","kind":"act","impl":"imperative","description":"Return one step of a guided walkthrough with the real control to reveal and how to verify it. Teaching never performs the edit; the person stays in control, and every step points at a control the interface actually has.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1},"goal":{"enum":["add_image","adjust_brightness","crop","export_image"]},"step":{"type":"integer","minimum":1,"maximum":8,"default":1}},"required":["projectId","goal"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"export_image","kind":"act","impl":"imperative","description":"Encode the current photo composite at a chosen format, quality, size, and resampling algorithm, and store it as a durable output. The reported size is measured by encoding, never estimated, and a substituted format is stated.","annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1},"mediaType":{"enum":["image/png","image/jpeg","image/webp","image/avif"]},"quality":{"type":"number","minimum":0.1,"maximum":1,"default":0.85},"maxEdgePx":{"type":["integer","null"],"minimum":16,"maximum":32768,"description":"Longest edge in pixels, or null for full size."},"resampleAlgorithm":{"enum":["nearest","bilinear","lanczos3","browser-smooth"]},"name":{"type":"string","minLength":1,"maxLength":160},"measureOnly":{"type":"boolean","default":false},"expectedRevisionId":{"type":"string","minLength":1,"description":"Refuse the export if the project has moved past this revision, so the file is of the picture you inspected."}},"required":["projectId","mediaType"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"inspect_outputs","kind":"answer","impl":"imperative","description":"List the project's finished deliveries with their kind, scope, source revision, preset, real format and settings, size, warnings, substitutions, job linkage, and whether their bytes are still stored.","annotations":{"readOnlyHint":true,"untrustedContentHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1},"outputId":{"type":"string"},"limit":{"type":"integer","minimum":1,"maximum":50,"default":25}},"required":["projectId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"manage_output","kind":"act","impl":"imperative","description":"Reveal a finished output in the interface so the user can download it, or delete one permanently. Deleting an output removes its stored file and cannot be undone through project history, because outputs are deliveries rather than project state.","annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":false,"openWorldHint":false,"untrustedContentHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"operation":{"enum":["reveal","delete"]},"outputId":{"type":"string","minLength":1},"confirm":{"type":"boolean","default":false}},"required":["operation","outputId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"select_region","kind":"act","impl":"imperative","description":"Choose the part of the image the next edit applies to. Tools: a rectangular or elliptical marquee, a freehand or polygonal lasso, a magic wand that spreads from one point by colour, a colour range or brightness range across the whole image, a layer's own transparency, or everything. Every tool supports replace, add, subtract, and intersect, so selections are built up rather than restarted. A selection is where the next edit lands, not an edit itself, so it does not appear in Undo; save it by name to keep it.","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1},"mode":{"enum":["replace","add","subtract","intersect"],"description":"How this combines with what is already selected. Defaults to replace."},"source":{"type":"object","description":"Which tool, and its parameters. One of: {kind:'marquee',shape:'rectangle'|'ellipse',x,y,width,height,featherPx}, {kind:'lasso',points:[{x,y},…]}, {kind:'wand',x,y,tolerance,contiguous}, {kind:'colour_range',colour:'#rrggbb',tolerance}, {kind:'luminance_range',low,high,softness}, {kind:'layer_alpha',layerId}, {kind:'all'}."}},"required":["projectId","source"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"refine_selection","kind":"act","impl":"imperative","description":"Adjust the current selection: grow it, shrink it, soften its edge, smooth a ragged boundary, keep only a band along the edge, move it, or invert it. Also runs the whole refinement workspace in one pass when given smoothPx, featherPx, contrast, and shiftEdge together, which is how a difficult edge is cut without degrading the selection through repeated rounding.","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1},"operation":{"type":"object","description":"One of: {kind:'feather',radiusPx}, {kind:'expand',amountPx}, {kind:'contract',amountPx}, {kind:'smooth',radiusPx}, {kind:'border',widthPx}, {kind:'move',dx,dy}, {kind:'invert'}. Leave out to use the workspace sliders instead."},"smoothPx":{"type":"number","minimum":0,"maximum":100},"featherPx":{"type":"number","minimum":0,"maximum":250},"contrast":{"type":"number","minimum":-1,"maximum":1,"description":"Positive hardens the edge, negative softens it, without moving it."},"shiftEdge":{"type":"number","minimum":-1,"maximum":1,"description":"Slides a soft boundary in or out without changing how soft it is. A hard edge has no band to slide; use expand for that."}},"required":["projectId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"manage_selections","kind":"act","impl":"imperative","description":"Keep, reload, list, or discard named selections. A saved selection survives a reload and can be brought back on its own or combined with whatever is selected now; loading one into a differently sized image is refused rather than silently misplaced. Use inspect to see what is selected right now without changing it.","annotations":{"readOnlyHint":false,"untrustedContentHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1},"action":{"enum":["inspect","save","load","list","delete","clear","select_all"]},"name":{"type":"string","description":"For save. Saving over an existing name replaces it."},"selectionId":{"type":"string","description":"For load and delete."},"mode":{"enum":["replace","add","subtract","intersect"],"description":"For load. Defaults to replace."}},"required":["projectId","action"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"manage_channels","kind":"act","impl":"imperative","description":"Look at the document one colour channel at a time, hide channels, or list the stored greyscale ones. An alpha channel here is the same thing as a saved selection, so anything kept in one panel appears in the other and can be loaded from either. Which channels are shown is a way of looking at the document, not an edit, so it never appears in Undo.","annotations":{"readOnlyHint":false,"untrustedContentHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1},"action":{"enum":["inspect","isolate","set_visible","reset"]},"channel":{"enum":["red","green","blue","alpha"],"description":"For isolate. Pass null to stop isolating."},"visible":{"type":"array","items":{"enum":["red","green","blue","alpha"]},"description":"For set_visible. At least one."}},"required":["projectId","action"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"exchange_svg","kind":"act","impl":"imperative","description":"Reads an SVG into editable shape layers, or writes the document's shapes back out as SVG. Importing keeps each object as its own layer rather than flattening the file into a picture of itself, and anything Estro cannot draw is named in the warnings rather than dropped in silence. Exporting resolves swatch fills to the colours they currently hold, because an SVG has nowhere to keep a reference.","annotations":{"readOnlyHint":false,"untrustedContentHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1},"action":{"enum":["import","export"]},"svg":{"type":"string","description":"The SVG source, when importing."},"expectedRevisionId":{"type":"string"}},"required":["projectId","action"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"manage_swatches","kind":"act","impl":"imperative","description":"Add, rename, recolour, remove, and list the document's named colours and gradients. A swatch is shared: changing it changes every shape, stroke, and fill pointing at it in one edit rather than in forty. Removing one leaves anything using it unpainted and says so, rather than quietly baking in the colour it had.","annotations":{"readOnlyHint":false,"untrustedContentHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1},"action":{"enum":["list","add","update","remove"]},"swatchId":{"type":"string"},"name":{"type":"string","minLength":1,"maxLength":80},"paint":{"type":"object","description":"Solid: {kind:'solid',colour:'#rrggbb',opacity}. Gradient: {kind:'linear'|'radial',stops:[{offset,colour,opacity}],…}."},"expectedRevisionId":{"type":"string"}},"required":["projectId","action"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"match_photos","kind":"act","impl":"imperative","description":"Copy one photograph's settings onto photographs in other projects. Plans by default: every target is checked before anything is written, so a strict batch can refuse rather than leave half a set synchronised. Each project gets its own Undo step, because each project keeps its own history and there is nowhere a single one could live.","annotations":{"readOnlyHint":false,"untrustedContentHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"sourceProjectId":{"type":"string","minLength":1},"sourceLayerId":{"type":"string","minLength":1},"targets":{"type":"array","maxItems":200,"items":{"type":"object"},"description":"Each {projectId, layerId}: the photograph in each project to bring into line."},"attributes":{"type":"array","items":{"type":"string"},"description":"Which attributes to copy. All of the source layer's if left out."},"policy":{"enum":["all_or_nothing","best_effort"]},"apply":{"type":"boolean","description":"False (the default) plans without writing anything."}},"required":["sourceProjectId","sourceLayerId","targets"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"batch_export","kind":"act","impl":"imperative","description":"Export many photographs at once, in one or more sizes and formats. Plans by default and says how many files that is, which projects cannot take part, and why — three sizes of a hundred photographs is three hundred encodes, so it runs as a job with progress and a cancel rather than blocking. Set apply to true to queue it; poll inspect_job for progress.","annotations":{"readOnlyHint":false,"untrustedContentHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1,"description":"The project the job belongs to, for progress and cancellation."},"projectIds":{"type":"array","items":{"type":"string"},"maxItems":200},"variants":{"type":"array","maxItems":6,"items":{"type":"object"},"description":"Each {name, mediaType, quality, maxEdgePx, resampleAlgorithm}. The name goes into the file name, so a set of three sizes stays tellable apart."},"namePattern":{"type":"string","maxLength":160,"description":"{project} and {variant} are replaced. Defaults to “{project} — {variant}”."},"onFailure":{"enum":["continue","stop"],"description":"continue (the default) keeps going past a photograph that fails; stop refuses to begin unless every one can take part."},"apply":{"type":"boolean"}},"required":["projectId","projectIds","variants"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"resolve_phrase","kind":"answer","impl":"imperative","description":"Read a phrase like “make it a bit warmer” or “black and white” into the exact command Estro would run, without running it. Says what it understood, what it did not, and which words meant nothing here. This is a lookup rather than a language model: a phrase it does not know is refused by name instead of being approximated, and the command it returns is an ordinary one that goes through the same history as any other edit. Call list_phrases to see everything it knows.","annotations":{"readOnlyHint":true,"untrustedContentHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"phrase":{"type":"string","minLength":1,"maxLength":500},"projectId":{"type":"string","minLength":1},"layerId":{"type":"string"},"clipId":{"type":"string"},"sequenceId":{"type":"string"}},"required":["phrase","projectId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"list_phrases","kind":"answer","impl":"imperative","description":"Every phrase resolve_phrase understands, with what each one means. Making people guess at a vocabulary is worse than showing them. Never changes anything.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{},"required":[]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"mark_media","kind":"act","impl":"imperative","description":"Rate, label, favourite, tag, or note media. Many items at once, as one transaction and one press of Undo, because that is how selects are actually made. A rating of zero means unrated rather than bad, so “show me everything nobody has looked at” stays answerable. Tags are added and removed rather than replaced, so marking fifteen shots “wide” does not strip whatever else each was tagged.","annotations":{"readOnlyHint":false,"untrustedContentHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1},"itemIds":{"type":"array","items":{"type":"string"},"maxItems":500},"itemType":{"enum":["asset","subclip","sequence"],"description":"Defaults to asset."},"rating":{"type":"integer","minimum":0,"maximum":5,"description":"0 clears it; 0 means unrated, not bad."},"label":{"type":["string","null"],"enum":["red","orange","yellow","green","blue","purple","grey",null]},"favourite":{"type":"boolean"},"addTags":{"type":"array","items":{"type":"string"},"maxItems":32},"removeTags":{"type":"array","items":{"type":"string"},"maxItems":32},"note":{"type":"string","maxLength":2000},"expectedRevisionId":{"type":"string"}},"required":["projectId","itemIds"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"manage_collections","kind":"act","impl":"imperative","description":"Saved questions about the media, as against places to file it. A collection is not a bin: nothing is moved into it, and an item that stops matching leaves on its own — so a collection is always current and never has to be maintained. List, run, add, change, or remove one; browse with the same rules without saving them.","annotations":{"readOnlyHint":false,"untrustedContentHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1},"action":{"enum":["list","run","add","update","remove","browse"]},"collectionId":{"type":"string"},"name":{"type":"string","minLength":1,"maxLength":80},"match":{"enum":["all","any"]},"rules":{"type":"array","maxItems":16,"items":{"type":"object"},"description":"Each {field, comparison, value}. Fields: rating, label, favourite, tag, name, kind, duration, used."},"sortField":{"enum":["name","rating","duration","kind","label"]},"sortDirection":{"enum":["ascending","descending"]},"minimumRating":{"type":"integer","minimum":0,"maximum":5,"description":"For browse."},"favouritesOnly":{"type":"boolean","description":"For browse."},"tag":{"type":"string","description":"For browse."},"expectedRevisionId":{"type":"string"}},"required":["projectId","action"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"manage_package","kind":"act","impl":"imperative","description":"Plan moving a project between machines. This tool reads and reasons; it does not write or open a package, because a browser cannot hand a file to another machine without a user gesture. estimate says how large a package would be under each media policy — “everything” on a long project is very large. offline_state says what this copy would be missing if it were opened elsewhere. inspect and plan_open take the contents of a package you already have and say whether this copy is behind, ahead, diverged, or unrelated, because those four need different things done. Writing the file itself is a user action through the interface.","annotations":{"readOnlyHint":true,"untrustedContentHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1,"description":"For estimate and offline_state."},"action":{"enum":["estimate","offline_state","inspect","plan_open"]},"mediaPolicy":{"enum":["none","used_only","everything"],"description":"used_only by default. none needs the media to already be on the machine that opens it."},"writtenBy":{"type":"string","maxLength":120,"description":"Names the machine, so two packages can be told apart."},"packageJson":{"type":"string","description":"For inspect and plan_open: the package's contents."},"resolution":{"enum":["take_incoming","keep_local","keep_both"],"description":"For plan_open."}},"required":["action"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"manage_review","kind":"act","impl":"imperative","description":"People on a project, comments anchored to an object, a timecode, or a region of the frame, version stacks, claims, and shares. None of it is enforcement and every answer says so: a role decides what Estro offers rather than what it prevents, and a claim is a note to whoever else opens the project. Comments are resolved rather than deleted, so the thread that explains a decision survives, and each records which version it was written against.","annotations":{"readOnlyHint":false,"untrustedContentHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","minLength":1},"action":{"enum":["list_comments","comment","reply","resolve","reopen","list_people","set_person","remove_person","permissions","list_stacks","set_stack","remove_stack","list_claims","claim","release","list_shares","share"]},"body":{"type":"string","maxLength":4000,"description":"For comment and reply."},"anchor":{"type":"object","description":"Where a comment points: {kind:'project'} | {kind:'object',objectType,objectId} | {kind:'time',sequenceId,time,duration} | {kind:'region',sequenceId,time,x,y,width,height}."},"authorName":{"type":"string","maxLength":120},"commentId":{"type":"string"},"sequenceId":{"type":"string","description":"For list_comments: only this sequence's."},"includeResolved":{"type":"boolean"},"personId":{"type":"string"},"name":{"type":"string","maxLength":120},"role":{"enum":["owner","editor","reviewer","viewer"]},"email":{"type":["string","null"]},"stackId":{"type":"string"},"versionIds":{"type":"array","items":{"type":"string"},"maxItems":50},"currentId":{"type":"string"},"approvedId":{"type":["string","null"]},"objectType":{"enum":["project","sequence","layer","clip"]},"objectId":{"type":"string"},"heldBy":{"type":"string","maxLength":120},"note":{"type":"string","maxLength":500},"expiresInMinutes":{"type":"number","minimum":1,"maximum":10080},"outputId":{"type":["string","null"]},"watermarked":{"type":"boolean"},"expectedRevisionId":{"type":"string"}},"required":["projectId","action"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]},{"name":"inspect_accessibility","kind":"answer","impl":"imperative","description":"How the interface presents itself, and how to operate it without a mouse. Reports the resolved motion and contrast modes, every status indicator with the shape and word that carry its meaning without colour, and the keyboard route to each action. Colour is never the only signal here, and no status is described by naming its colour — “red” tells nobody anything they can act on.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","additionalProperties":false,"properties":{"projectId":{"type":"string","description":"For the preferences saved against a project's workspace."}},"required":[]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/","pages":["/","/projects"]}],"category":"AI & Agents","favicon":"/favicons/estro-webmcp.vercel.app.svg","apiSurface":"spec","toolCount":56}}