`hasMask` in document inspection covers only raster masks, so a layer with a vector mask looked unmasked to an agent. Layers, groups included, now also report `hasVectorMask` and `vectorMaskEnabled` (null when there is no vector mask). `hasMask` keeps its meaning.
4.8 KiB
MCP conventions
PhotoCraft follows the same conventions as FilmCraft #28. Start a headless session:
photocraft-cli mcp --automation-read-root /work/project --automation-write-root /work/project
Paths are relative to the corresponding root, or absolute paths beneath it; without a root that
filesystem authority is absent. Bridge mode uses --bridge and --control-token-file as
described in development.md. UI tools require a running desktop app.
Tools and resources
command_list: discover engine ids, parameter docs and current enabled state; acceptsfilterandenabled_only.command_run:id, optionalparamsandwait. Command parameters remain engine-defined.command_batch: orderedsteps, optionalstop_on_error; one history step per command, not an atomic transaction. Existing per-step results and reply budgets are preserved.doc_inspect: layer tree, history and selection; an empty session returnsdocument:null. Every layer (including groups and nested children) reports raster-onlyhasMask,hasVectorMaskfor vector mask presence, andvectorMaskEnabled(true/falsewhen present,nullwhen absent). A disabled vector mask still hashasVectorMask:true.render_preview: bounded PNG content;indexandmax_side(default 1024, maximum 2048).ui_inspectandui_screenshot: live app state/window in bridge mode.
Existing document/session/job/UI tools remain listed, including the documented
doc_render_preview spelling. There are no hidden legacy aliases. Every tool has a title
and all four annotation hints. Generic command/control tools conservatively advertise writes;
file saves may replace existing targets. Hints do not grant permission.
Unknown tool arguments return JSON-RPC -32602, naming the key, before execution. Batch
step envelopes are strict too. Nested engine params retain their command-specific handling.
Tool execution failures return isError:true. A worker panic becomes a tool error and the
existing poisoned-session recovery keeps serving. Invalid JSON lines receive -32700 with
id:null; the next line is still processed.
Embedded Smart Objects support command_run with layer.smartObjects.editContents and
layer.smartObjects.convertToLayers, optionally targeting params.layer. Use
layer.smartObjects.saveContents in an opened contents document to update its parent in memory;
save nested contents from the inside outward, then doc_save the parent to a scoped path.
doc_save on a contents document exports that document rather than updating its parent.
No filesystem root is needed for the in-memory commands. External linked sources that require
a file read remain refused. See the control policy
for the shared restrictions.
photocraft://document and photocraft://commands return live JSON matching doc_inspect
and command_list. Resource reads are uncached; tool/resource catalogs are private and cached
for ten minutes. List/read responses include the MCP 2026-07-28 result/cache fields.
Progress and cancellation
A direct headless command_run of file.export.renderVideo reports frame counts when
_meta.progressToken is present (a string or number). Notifications increase strictly,
are throttled to at most ten per second except completion, and include total. No token
means no progress notifications. Ping remains responsive while rendering.
{"jsonrpc":"2.0","id":20,"method":"tools/call","params":{"name":"command_run","arguments":{"id":"file.export.renderVideo","params":{"dir":"frames","format":"png"}},"_meta":{"progressToken":"export-20"}}}
{"jsonrpc":"2.0","method":"notifications/cancelled","params":{"requestId":20}}
Create a document and timeline first (doc_new, then timeline.create). Export uses the
configured write root and creates dir beneath it. Filenames must be single components;
absolute paths, traversal and escaping symlinks are rejected. Existing target filenames
are refused, including symlinks, so a cancelled or failed job cannot replace an earlier export.
Only files actually created by this job are removed on cancellation, error or an escaped panic;
unrelated files and the destination directory remain. PNG sequences and animated GIF share
the engine renderer. The document and playhead are unchanged.
Cancellation suppresses the request response and stops at a frame boundary (the current
frame/encoding may finish first). Unknown request ids are ignored. Render Video stays a
synchronous command even with wait:false; other job-capable commands keep their existing
jobs_list/jobs_cancel behavior. Batch exports do not emit MCP progress or support per-step
MCP cancellation. Nested engine actions and bridge Render Video remain denied by the existing
ambient-filesystem policy; the new scoped writer is available for direct headless commands.