Opura / MCP
AI assistants (MCP)
Opura Select, Photo and Video each include an MCP server. Through it your AI assistant reads from the app and — if you allow it — works in it. This page shows what each app offers, the permission every tool needs and how to set up the connection.
Supported AI clients
Claude Code, Claude Desktop and Cursor: for these three clients each app shows the setup itself. This page makes no promise for other clients.
Set up
- Open the app’s MCP settings and switch MCP on with the switch listed below for each app. Until then MCP is off.
- The app then shows the exact setup for this Mac, each with a copy button: a command for Claude Code (“Claude Code — run once:”) and a JSON block for Claude Desktop and Cursor (“Claude Desktop / Cursor — MCP config:”). Copy them from the app. They contain paths that differ from Mac to Mac, which is why this page deliberately shows no ready-made snippet.
- If the assistant should change things, switch on the permission for changes, and in Opura Video, if needed, the one for big actions. Both apply to the current connection and switch off as soon as the assistant disconnects.
- Keep the app open while the assistant works. If it is closed or MCP is off, the helper reports that it cannot connect.
Opura Select
- Server name
selra- MCP settings
- Open a folder, then Settings (gear in the toolbar or the , key), section “AI agent (MCP)”
- Switch MCP on
- “Allow an AI agent to control Opura Select”
- Changes (write)
- “Let it change ratings, picks and labels”
- Big actions (destructive)
- No switch: Opura Select refuses every call of this tier. A confirmation mentioned in a tool description does not come into play here.
Opura Photo
- Server name
luce- MCP settings
- Opura Photo ▸ Settings… (⌘,), tab “AI agent (MCP)”
- Switch MCP on
- “Allow an AI agent to control Opura Photo”
- Changes (write)
- “Let it change adjustments and presets”; for masks also “Let it change masks”
- Big actions (destructive)
- No switch: Opura Photo refuses every call of this tier.
Opura Video
- Server name
incisa- MCP settings
- Opura Video ▸ Settings… (⌘,)
- Switch MCP on
- “Allow an AI agent to control Opura Video”
- Changes (write)
- “Let it edit the timeline (…)”
- Big actions (destructive)
- “Let it run big actions (…)”; the app asks before every call
Permission tiers
Every tool has one of three tiers. The app enforces them itself, whichever assistant is connected.
read- Only reads and changes nothing. Available as soon as MCP is on and an assistant is connected.
write- Changes something in the app, such as ratings, adjustments or the timeline. Refused until you allow changes; the permission applies to the current connection only.
destructive- Big actions, such as replacing the whole timeline, writing files or starting an export. Only in an app with its own switch for them, and only while it is on; the app then asks you before every single call (Allow / Deny), with no “don’t ask again”. If the app has no such switch, it refuses every call of this tier.
Security
- MCP is off by default and after every app launch; you switch it on per app.
- Every call to one of the app’s tools, refused ones included, is recorded in the app’s log. The MCP settings show the recent agent activity and export it as a JSON file.
- MCP only works while the app’s licence allows editing.
- Only your own user account on this Mac can reach the connection: the app’s socket is accessible to you alone (0600), and the helper must present a token that the app writes to a file only you can read.
How the connection works
Each app contains a signed helper program, opura-mcp-bridge. Your AI client starts it on your Mac as a local MCP server (stdio); the helper passes the messages over a private Unix socket to the running app.
Opura runs no MCP server on the internet; there is no URL and no port. The connection between helper and app stays on your Mac. Whether your AI client itself uses a model in the cloud depends on that client.
For Macs with Apple Silicon · macOS 26 or later
Tools per app
Names, tiers and descriptions come unchanged from each app’s own tool catalog; the descriptions are the apps’ English texts. The same catalogs are available as JSON files.
Opura Select
| Tool | Tier | Description (app text, English) |
|---|---|---|
list_shoot | read | List photos in the open shoot with their culling state. Paged. The list is the displayed catalog: `total` is the whole shoot, `catalog` is what the app's filter, keepers-only and search leave, and `applied` is the input set that produced it — the app's own filter and sort values, plus the search with its filename needle redacted. `total` minus `catalog` is what the inputs hide. Use the returned ids with rate/set_pick/set_label. |
get_selection | read | Get the app's current selection: the cursor photo with its culling state, plus `selectedIds` — every tile in the multi-selection, in display order. |
rate | write | Set the star rating on one or more photos. -1 = reject, 0 = unrated, 1…5 = stars. |
set_pick | write | Set the pick flag on one or more photos: pick, none, or reject. |
set_label | write | Set or clear the colour label on one or more photos (Red/Yellow/Green/Blue/Purple, or null to clear). |
undo | write | Undo the most recent culling edit (rating/label/pick). |
redo | write | Re-apply the most recently undone culling edit (rating/label/pick). |
open_folder | write | Open a shoot folder. Starts the scan, background index, and folder watcher, and replaces the current session. Not undoable — there is no undo for opening a folder. |
get_cull_stats | read | Counts for the open shoot from the same progress the toolbar uses: decided/undecided, selects, rejects, colour labels, and whether a scan is still running. A missing folder is an error; an empty open folder is all zeros. |
export_xmp | destructive | Write XMP sidecars next to the original photos for every decided frame. Undecided frames get no sidecar. Originals are never rewritten. Repeating the export is idempotent. Not undoable — sidecars stay on disk — and every call needs confirmation. |
Opura Photo
| Tool | Tier | Description (app text, English) |
|---|---|---|
get_recipe | read | Get the current develop recipe (global tone/color, crop, LUT, local masks) for the selected image, as JSON. |
get_selection | read | Get the image currently selected in the editor (its file path) plus a summary of its lens info (model + whether built-in lens correction is supported). Path and lens are one atomic snapshot: lens is null while no image is selected or while the selected image's lens info is still being read — never a previously selected image's lens. |
list_presets | read | List the available develop presets (built-in looks + the user's saved presets) with their id and name. Use an id or name with apply_preset. |
apply_preset | write | Apply a develop preset's look to the selected image (its own crop is preserved). Identify the preset by id OR by name. The persistence receipt is returned only after the sidecar's atomic disk write has completed. |
set_adjustment | write | Set one tone/color adjustment on the selected image's global recipe — the whole photo, never a local mask, whatever the editor happens to show as selected. To write a local mask, address it by its list_masks index with set_mask_adjustment. Names: blacks, clarity, contrast, dehaze, denoiseColor, denoiseDetail, denoiseLuminance, exposureEV, highlights, monochrome, saturation, shadows, sharpenRadius, sharpness, temperature, texture, tint, vibrance, vignette, whites. The persistence receipt reports only an awaited atomic sidecar commit. |
list_masks | read | List the selected image's mask terms (the runtime sequence, not only the primary spec). Empty when the image has none. `index` is the local write address for remove_mask / set_mask_adjustment / combine_masks; `term` is the position in that local's sequence. |
add_mask | write | Add a local mask of one stored kind to the selected image. Kinds: radial, brush, linear, subject, luminance, color, person, face. Uses the same add-mask path as the UI. |
remove_mask | write | Remove one local mask on the selected image by the 0-based index from list_masks. Uses the same remove-mask path as the UI. |
set_mask_adjustment | write | Set one tone/color adjustment on a local mask identified by list_masks index. Names: blacks, clarity, contrast, dehaze, denoiseColor, denoiseDetail, denoiseLuminance, exposureEV, highlights, monochrome, saturation, shadows, sharpenRadius, sharpness, temperature, texture, tint, vibrance, vignette, whites. Writes that local through setAdjustmentValue. |
combine_masks | write | Add a mask-algebra operand to the mask at list_masks index. Operation is union, intersect, or subtract. Operand kinds: radial, brush, linear, subject, luminance, color, person, face. Uses the same addMaskOperand path as the UI COMBINE row. |
undo | write | Undo the last develop change on the selected image — the same per-photo stack the UI uses. |
redo | write | Redo the last undone develop change on the selected image — the same per-photo stack the UI uses. |
Opura Video
| Tool | Tier | Description (app text, English) |
|---|---|---|
list_timeline | read | List the timeline: video/audio tracks in order, each with its clips (id, source path, in/out, timeline position, aggregate speed, optional authored speed-ramp shape, and outgoing transition when present). Use the clip ids with select_clip/replace_clip_source. |
get_selection | read | Get the timeline selection: every selected clip id in timeline order (selectedClipIDs), the anchor clip id (selectedClipID) and its full summary (including aggregate speed, optional authored ramp shape, and outgoing transition when present), and the playhead in seconds. |
get_project | read | Get the project header: name, render size, frame rate (ntsc-aware), delivery target, total duration in seconds, and whether it is empty / has renderable content. |
export_status | read | Poll the export job: whether one is running, what kind (movie/frame), its progress (0…1), ETA, last output path, and the last failure reason. |
caption_status | read | Poll auto-caption generation: whether one is running, whether captions exist, segment count, and the last rejection or terminal reason (e.g. an unavailable source or speech failure). |
list_styles | read | List the built-in auto-reel styles (names) you can pass to generate_reel. |
list_templates | read | List the built-in reel templates (names) you can pass to apply_template. |
list_looks | read | List built-in creative looks (catalog filename and English name) you can pass to apply_look. |
select_clip | write | Replace the timeline selection with the given clips (ids from list_timeline). Pass one id to select one clip, several to select several; the last id named becomes the anchor. The clip-scoped tools act on this selection. Undoable only through the edits it enables. |
seek | write | Move the playhead to a position in seconds (clamped to the timeline). |
split_at_playhead | write | Split the clip under the playhead into two at the playhead, on every lane that holds a selected clip — or on every lane when nothing is selected. Lanes where the playhead sits on a boundary or in a gap are skipped; if no lane can be split it returns skipped without changing project or selection. However many lanes are cut, it is one undo step. |
delete_selected | write | Delete the given clip, or every clip in the current selection when clipID is omitted. Ripple by default. Reports how many clips it deleted, and which. Undoable. |
set_bpm | write | Set the project tempo (beat grid) in BPM, for beat-snapped editing. Undoable. |
clear_beat_grid | write | Remove the project's beat grid. Undoable. |
clear_captions | write | Remove all auto-captions from the project. Undoable. |
generate_captions | write | Start on-device speech-to-text auto-captioning of the timeline (async). Returns started only after reserving a live job; an unavailable source or existing job returns skipped. poll caption_status for running/lastError (privacy refusals and recognition failures). Needs a clip with speech. |
add_marker | write | Add a timeline marker at the playhead (or at a given time). Undoable. |
remove_marker | write | Remove the marker at the playhead (or at a given time). Returns skipped without moving the playhead when no marker is within one frame. Undoable. |
clear_markers | write | Remove all timeline markers. Undoable. |
undo | write | Undo the most recent editing change. |
redo | write | Redo the last undone change. |
export_cancel | write | Cancel the in-flight export, if any (deletes the partial file). Safe no-op otherwise. |
apply_look | write | Apply a built-in creative look to every selected video clip (or to clipID alone). Address the look by catalog filename or English name (see list_looks). Identity is the filename, never a bundle path. Undoable. Skipped on HDR projects. |
set_transition | write | Set the outgoing transition on the selected video cuts (kind and optional duration in seconds). Omit seconds to keep each cut's current duration, or use the kind's default on a hard cut. Reports which cuts now carry the kind. Does not author the punch pivot or motion-match alignment — those stay on their existing surfaces. Undoable. Kinds: dissolve, dipToBlack, dipToWhite, flash, pushLeft, pushRight, pushUp, pushDown, wipeLeft, wipeRight, wipeUp, wipeDown, zoomIn, zoomOut, spin, whipPanLeft, whipPanRight, zoomPunch, lumaCut, irisPunch, shapeWipe. |
apply_transition_to_all_cuts | write | Apply one transition kind to every butted cut on the first video lane (the Inspector ‘Apply to all’ action). Uses that kind's default duration. Undoable. Kinds: dissolve, dipToBlack, dipToWhite, flash, pushLeft, pushRight, pushUp, pushDown, wipeLeft, wipeRight, wipeUp, wipeDown, zoomIn, zoomOut, spin, whipPanLeft, whipPanRight, zoomPunch, lumaCut, irisPunch, shapeWipe. |
clear_transition | write | Clear the outgoing transition on the selected video cuts, back to a hard cut. Reports which cuts it cleared. Undoable. |
set_clip_crop | write | Crop the selected video clips (or clipID alone): cut away part of each SOURCE frame before the clip's fit places what is left. The four edges are fractions of the source width (left/right) or height (top/bottom), 0 = nothing cut, and they are ABSOLUTE — pass only the edges you want to change. Opposite edges must leave at least 2% of the axis standing. crop_aspect snaps the crop to the largest centred rectangle of that shape and keeps the ratio locked for later edits; pass free to release the lock and keep the rectangle. Cropping needs the clip's source size, which is measured on first use — a shape asked for before that measurement lands returns skipped, and the same call then works. A call that names no edge and no shape changes nothing and returns skipped. Undoable. Shapes: free, portrait9x16, square1x1, portrait4x5, landscape16x9. |
new_project | destructive | Start a new, empty project. DISCARDS the current timeline AND its undo history — this cannot be undone. Source files are untouched. |
open_project | destructive | Open a saved project document (.incisa, or the legacy .incisa.json). REPLACES the current timeline and clears the undo history — this cannot be undone. Source files are untouched. |
generate_reel | destructive | Auto-generate a reel from the current clips using a built-in style (see list_styles). REBUILDS the whole base video lane. Runs asynchronously; returns immediately. One undo step. Source files untouched. |
apply_template | destructive | Apply a built-in reel template (see list_templates), REBUILDING the first video track from the template's slots. One undo step. Source files untouched. |
replace_clip_source | destructive | Re-point a video clip at a different source file (keeps its timeline edits). Async; returns immediately. The old media is untouched; only a regenerable preview cache is dropped. Video clips only. |
export | destructive | Render the timeline to a NEW movie file (async hardware encode; returns immediately — poll export_status). Pick a preset OR a codec. For SDR, standard/reels/youtube/square write MP4; ProRes Master and Custom write MOV. HDR always uses HEVC Main10/MOV. Existing files require overwrite=true; sources stay untouched. |
export_frame | destructive | Export the composited frame at the playhead (or a given time) as a PNG (a cover still). Async. |
import_media | destructive | Import media files onto the base video lane (async probe; returns immediately). Paths must stay inside the open project folder. One undo step after the clips land. Source files are read, never modified. |
save_project | destructive | Write the open project document to a path inside the project folder (.incisa preferred). Never overwrites an existing file unless overwrite=true, except the currently open document which is an ordinary save. Refuses source clips, music, and stickers. The file write is not an undo step. |