Files
photocraft/docs/mcp.md
T
KnottyDyes 2d6ff3f6cc Inspect: report each layer's vector mask (#2980)
`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.
2026-10-11 15:21:03 -04:00

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; accepts filter and enabled_only.
  • command_run: id, optional params and wait. Command parameters remain engine-defined.
  • command_batch: ordered steps, optional stop_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 returns document:null. Every layer (including groups and nested children) reports raster-only hasMask, hasVectorMask for vector mask presence, and vectorMaskEnabled (true/false when present, null when absent). A disabled vector mask still has hasVectorMask:true.
  • render_preview: bounded PNG content; index and max_side (default 1024, maximum 2048).
  • ui_inspect and ui_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.