MCP conventions
Install and register
From the repository root, with the source-build prerequisites installed, install the CLI independently of the build directory:
cargo install --path apps/picto-cli --locked
# POSIX shells, for Cargo's default install location:
export PATH="${CARGO_HOME:-$HOME/.cargo}/bin:$PATH"
picto-cli --help
picto-cli mcp --help
Cargo installs a binary, not a symlink into target/, so
it survives cargo clean. Re-run the install command after
updating the checkout. By default the executable goes in
$CARGO_HOME/bin (~/.cargo/bin when unset), or
%USERPROFILE%\.cargo\bin on Windows. If you set
--root, CARGO_INSTALL_ROOT, or Cargo's
install.root, use that installation root's bin
directory instead. Add it to the PATH inherited by the MCP
client, not just an interactive shell, and restart the client after
changing its environment.
Register the installed command explicitly (replace
/work/project with an existing folder):
claude mcp add picto -- picto-cli mcp --automation-read-root /work/project --automation-write-root /work/project
Other MCP clients can use this bare-name configuration:
{"mcpServers":{"picto":{"command":"picto-cli","args":["mcp","--automation-read-root","/work/project","--automation-write-root","/work/project"]}}}
Linux .deb and .rpm packages already
install /usr/bin/picto-cli; those users can skip the source
install. Other release locations are listed in the installed-release
guide. Installing the CLI does not start or register an MCP server
automatically.
If a client reports ENOENT or "Executable not found in
$PATH", verify the install with
`command -v picto-cli` (PowerShell: `Get-Command picto-cli`) in the
client's
environment. If that environment cannot be changed, set JSON `command`
to the absolute
installed binary path, not a literal `~` or
`$HOMEexpression. Avoid symlinks intotarget/release: cleaning the build directory breaks them. A source build alone does not put the CLI on PATH`.
Start a session
Picto follows the same conventions as Kinema #28. Start a headless session:
picto-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.
Use absolute root paths in MCP client configurations, since a
relative root is resolved from the client's launch directory. In bridge
mode, configure roots on the desktop app; root flags on
picto-cli mcp --bridge are rejected. Explicit
--control-token and --control-token-file flags
require --bridge and are mutually exclusive. Bridge
credentials can also come from PICTO_CONTROL_TOKEN or
PICTO_CONTROL_TOKEN_FILE.
MCP and serve launch options (all but
--help/-h) take one non-empty value each and
cannot be repeated. Missing values, stray positional arguments and
options for the wrong mode are usage errors (exit 2), reported on stderr
before the server starts; stdout stays available for protocol messages.
For serve, explicit credential flags require
--port; stdio needs no control token.
Tools and resources
command_list: discover engine ids, parameter docs and current enabled state; acceptsfilterandenabled_only. Returns a bare JSON array of{id, label, menu, shortcut, params, enabled, disabledReason, needsDocument}objects (see Command list replies).command_run:id, optionalparamsandwait. Command parameters remain engine-defined.command_batch: orderedsteps, optionalstop_on_error(default true); stops at the first error unless false. Not an atomic transaction: earlier successful steps stay applied, with no rollback. 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.
After a failed batch, completed and per-step
results report successful steps, not a rolled-back
transaction. Inspect the document and its history with
doc_inspect; commands do not necessarily add one history
entry each. For undoable edits, use command_run with
{"id":"edit.undo","params":{}} once per undoable history
entry added, inspecting history as you recover. Undo does not roll back
files written to disk. If a reply-budget error says the current step may
have completed, inspect its effects before retrying or undoing it.
Before experiments, use command_run with
image.duplicate and {} params, or
history.newDocument and {} params (copies the
current state by default). Both create a new active document, leaving
the source unchanged; run experimental edits on that copy. The optional
state parameter of history.newDocument selects
a retained historical state.
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.
picto://document and picto://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.