Use paper as a generic, schema-driven bridge to Paper Desktop's live MCP
server. Paper's live tool catalog and schemas are authoritative; never rely on
a remembered argument shape.
Each paper process is a new MCP session. Remember the file with paper open or paper use, then later commands reopen it in that process. Do not
expect paper open in one invocation to stick for the next unless state was
written.
Preconditions
-
Check whether the CLI is installed:
command -v paper
-
If it is missing, report that clearly. Do not silently install software. Suggested installation from this repository:
cargo install --git https://github.com/lassejlv/paper-cli --locked -
Paper Desktop must be running. A Paper file must be open for design tools.
-
Establish context with one command:
paper inspectPrefer
paper use <id>after a successful open so later processes stick the same file. If inspect reportsfileOpen: false, open a file (paper openor theopenfield) orpaper use <id>, then inspect again. Do not continue with mutations until the reported file, page, and selection match the request.
The default endpoint is http://127.0.0.1:29979/mcp. Use --url or
PAPER_MCP_URL only when the user has configured another endpoint.
Core rule: discover, then call
Lead with convenience commands, then fall back to generic discovery:
paper inspect
paper use <file-id>
paper html hero.html --into "Test — Desktop"
paper tree
paper batch @steps.json
paper tools --schemas
paper schema <tool-name>
paper call <tool-name> '<json-object>'
Do not guess parameter names, accepted values, or response shapes. Re-read a
schema after a Paper update or after a validation error. Use @file JSON only
as a fallback when paper html / batch htmlFile cannot carry the payload.
Use convenience commands first:
paper inspect [--file-id <id>]paper use <id>/paper use --clearpaper html <file|-> --into <name> [--mode insert-children]paper tree [target] [--depth N]paper batch @steps.jsonpaper new <name> --openpaper artboard <name> --size desktop|tablet|mobilepaper doctorpaper status --shortpaper context --short [--file-id <id>]paper files [--limit 50] [--names]paper open <file-id-or-url> [--page-id <id>]paper screenshot <target> --output <path> [--scale 1] [--file-id <id>] [--force]
--file-id is global and wins over PAPER_FILE_ID, which wins over the sticky
state file. The CLI injects it as fileId only when the live tool schema
accepts that argument; otherwise it is skipped silently and the session
open_file from sticky state targets the file. Do not copy node IDs from
inspect into the user-facing reply.
Default stdout unwraps the MCP envelope. --raw keeps it. --compact avoids
PTY line wrapping; write huge payloads to files. --select /pointer and
--print ids (--quiet) trim unwrapped call / html / batch results.
Failures print one JSON object to stderr (code, tool, message, hint)
and exit nonzero.
Standard workflow
1. Establish file context
paper inspect
Prefer inspect over a chain of status, files, context, get_basic_info,
and get_selection. It returns IDs agents need for later tool calls in one
session, plus fileSource and impliedFileId. Use paper context --short
only when a human-facing summary without IDs is required.
If several files are open, target one explicitly:
paper open <file-id-or-url> --page-id <page-id>
paper use <file-id>
paper inspect
Pass --file-id (or fileId in tool arguments) when ambiguity is possible. Do
not assume an unremembered file is the intended one. Do not auto-open a guessed
file.
For several follow-up reads or writes, use paper batch so initialize and the
Paper guide run once. Decode screenshots with a per-step output path instead
of leaving base64 in the JSON.
2. Inspect before mutation
Start with read-only tools. paper tree is the usual hierarchy view. Read
schemas before invoking style, JSX, token, comment, screenshot, or export
tools:
paper tree
paper schema get_node_info
paper schema get_computed_styles
paper schema get_screenshot
Resolve the target from inspect selection, --into / tree exact names, or
an explicit user-provided node. Do not choose a similarly named node when
multiple nodes fit.
3. Choose the output mode
Unwrapped JSON — default
paper call get_selection
paper --compact call get_selection
paper --print ids call get_selection
Raw MCP envelope
paper --raw call get_selection
Text
Use only when the response is text-only:
paper call get_basic_info --text
paper tree
The CLI rejects --text when any non-text content is present. Do not work
around this protection or print base64 into the terminal.
Image file
Use --output when exactly one image is expected:
paper call get_screenshot '{"nodeId":"<node-id>"}' --output captures/screen.jpg
paper screenshot --active-artboard --output captures/artboard.jpg
paper screenshot --selected --output captures/selection.png
paper screenshot --artboard "Dashboard — Desktop" --output captures/dashboard.jpg
paper screenshot <node-id> --output captures/screen.jpg --scale 1
Screenshot convenience targets are mutually exclusive:
--selectedrequires exactly one selected node.--active-artboardprefers the single selected node's artboard and otherwise requires exactly one artboard on the active page.--artboard "<exact-name>"uses the name resolver (exact artboard, unique layer, else raw ID).- Use a positional node ID when a known node that is not naturally selected or named as an artboard is the intended target.
The CLI reports ambiguity with human-readable names and never chooses the first
match. Use --file-id when resolving against a specific open file.
Omit the extension when the CLI should infer it from the returned MIME type.
If a given extension mismatches, the CLI corrects it, notes the final path on
stderr, and reports it in the JSON result — no trial and error needed. Parent
directories are created automatically. Never add --force unless replacing
that exact file is intended.
After writes, the CLI waits 200ms (--settle 0 disables) before returning or
capturing. The first screenshot after a write can still be empty.
4. Supply arguments safely
Prefer paper html so HTML is read as bytes and never JSON-escaped in the
shell:
paper html hero.html --into "Test — Desktop" --mode insert-children
cat hero.html | paper html - --into Activity
Use inline JSON for small generic inputs:
paper call <tool-name> '{"key":"value"}'
Use a file for other complex input, or --dry-run to print the arguments that
would be sent:
paper call <tool-name> @arguments.json
paper --dry-run call <tool-name> '{"key":"value"}'
Arguments for paper call must be a JSON object. Keep stdout available for
machine-readable results; diagnostics and failures are written to stderr.
Before any write_html payload is sent, the CLI runs an HTML preflight and
reports to stderr. Local <img> paths are rewritten to the paper-asset://
absolute URLs Paper requires (resolved against the HTML file's directory, or
the working directory for stdin/inline payloads); base64 data-URI images are
materialized to a temp asset file and rewritten the same way, since Paper
silently renders data-URIs as 0×0 rects. Remote https:// and paper-gen://
URLs pass through. Heed stderr warnings for patterns Paper silently drops or
flattens: empty <span> elements, <span> with display: block (use <div>
instead), display: grid / display: inline, margin, and <table>.
5. Make focused changes
When the user authorizes design changes:
- Read the mutation tool's current schema (
paper tools --schemasfor a compact catalog). - Respect tool annotations such as
readOnlyHintanddestructiveHint. - Google Fonts need no
get_font_family_info;write_htmlalready accepts them. Callget_font_family_infoonly for local families, and only afterinspectshowsfileOpen: true(or afteropen/usehas set state). Never retry it as session init. - Prefer targeted text/style/move/duplicate operations over rewriting a large subtree.
- Keep each
write_html/paper htmlcall to one coherent visual group. - Preserve unrelated nodes and existing design tokens.
- Verify returned node information rather than trusting remembered node IDs.
Before deleting a node because its parent appears wrong, call get_node_info
and verify the relationship.
6. Verify and finish
After meaningful changes:
-
Re-read the changed node or subtree (
paper treeorget_node_info). -
Capture a screenshot at scale 1 for layout review; use scale 2 only for fine typography or small details.
-
Confirm the actual state matches the request.
-
Call
finish_working_on_nodeswhen creation or editing is complete:paper schema finish_working_on_nodes paper call finish_working_on_nodes '{}'
If the live schema requires arguments, follow it instead of the example.
Upgrade the CLI and skill
Only when the user explicitly asks to update Paper CLI, run:
paper upgrade
This updates the globally installed use-paper-cli skill through
npx skills@latest, then runs the repository's checksum-verifying installer in
the directory containing the current paper executable. It does not require
Paper Desktop or Cargo. It requires npx, internet access, an existing global
skill installation, and either a POSIX shell on macOS/Linux or Windows
PowerShell. On Windows, the result reports the CLI update as scheduled because
the installer waits for the running paper.exe to exit before replacing it;
installer progress then appears in the same terminal. Treat a nonzero exit as a
partial or failed upgrade and report the failed component and retry guidance
shown by the CLI.
Safety rules
- Paper tools act on the active file unless a supported
fileIdis supplied. - Read-only inspection does not authorize mutation.
- Ask before destructive or unrelated mutations unless the request already authorizes them.
paper openchanges Paper's active context and writes sticky state; use it deliberately.--forceoverwrites a local output file and must be explicit.- Do not use
paper-gen://unless the user explicitly requested image generation and the relevant Paper guide has been loaded. - Do not expose raw node IDs in the final user-facing response.
- Never report completion from a successful exit code alone; inspect the final Paper state.
Error handling
- Connection failure: confirm Paper Desktop is running and a file is open, then
retry
paper inspect,paper doctor, orpaper status --short. inspectreportsfileOpen: false: run theopencommand from that JSON, orpaper use <id>, then inspect again. Do not call design tools yet.- A tool fails with
NO_FILE_OPEN: runpaper open/paper use/paper inspect, then retry. Do not retry the same tool while no file is open. - Multiple open files: pass
--file-idorpaper use.inspectlists names when Paper marks more than one file as open. - Unknown tool: run
paper tools --names; the catalog may have changed. - Invalid arguments: run
paper schema <tool-name>again, or--dry-run, and rebuild the JSON. - Batch step failure: read
failedStepand the structurederror.codein the JSON, fix that call, and rerun the remaining steps. Do not assume later steps ran. --textrejection: omit--textfor structured JSON or use--outputfor one image.- MIME/extension mismatch: the CLI corrects the extension automatically and notes the final path on stderr; omitting the extension infers it instead.
- Existing output file: choose another path or use
--forceonly after confirming replacement. - Multiple returned images: keep structured JSON and handle each image
deliberately;
--outputwrites exactly one image.
Completion report
State:
- The Paper file and page used, without exposing raw node IDs.
- What was inspected or changed.
- Which Paper tools or convenience commands were used.
- How the final state was verified.
- Any unresolved ambiguity, unsupported output, or pending destructive action.
Detailed examples
Read examples.md for copy-paste workflows covering file selection, design inspection, screenshots, exports, mutations, comments, and failure recovery.