Files
designcraft/docs/mcp.md
T
Brandon ThomasandClaude Opus 5.5 927191d25f About: contributor and model credits compiled in (grab bag + table, self-submitted names) (#108)
* About: contributors compiled in from contributors.json (grab bag + table, sortable, name toggle)

Adds the craftrules standard (standards/contributors.md) to Help > About DesignCraft, which now
has tabs About · Contributors · Models (`help.about {tab}` selects one).
contributors/contributors.json is generated by craftrules/scripts/contributors.py and baked
into the binary by crates/ui-egui/build.rs as static tables (crates/ui-egui/src/credits.rs).
Each contributor line: @username, opt-in display/real name, PRs, commits, lines +/−/Δ,
binary assets +/−, first/last commit. Sortable by every column; alphabetical ignores
case and the leading @.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Contributors docs: craftrules is two levels up (../../craftrules)

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Contributors: self-submitted names in contributors/people.toml; AGENTS.md credit-yourself section

build.rs reads contributors/people.toml next to the generated contributors.json and shows a name only
for entries the generator verified as written by that person (craftrules standards/contributors.md).

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Contributors: regenerate (verified people.toml entries)

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-07 21:16:42 -04:00

5.8 KiB

MCP server

designcraft-cli mcp is a Model Context Protocol server that lets Claude and other agents drive DesignCraft: create documents, lay out frames and text, apply styles, place images, and look at the result as PNG images. It speaks newline-delimited JSON-RPC 2.0 on stdin/stdout (protocol 2025-06-18, also 2025-03-26 and 2024-11-05); logs go to stderr. The implementation is the designcraft-mcp crate.

Register it

Build the CLI (cargo build --release -p designcraft-cli), then:

# Headless: an in-process engine, no window
claude mcp add designcraft -- /path/to/target/release/designcraft-cli mcp

# Drive the running desktop app (start it first with a control port)
designcraft --control 7979
claude mcp add designcraft-app -- /path/to/target/release/designcraft-cli mcp --connect 7979

Other MCP clients use the same command line, e.g. in a JSON config:

{"mcpServers": {"designcraft": {"command": "/path/to/designcraft-cli", "args": ["mcp"]}}}

Modes

Headless (mcp) Connected (mcp --connect PORT or HOST:PORT)
Engine In-process designcraft_engine::Session, starts with an empty Letter document (--sample opens the sample magazine) The app's session, through its loopback control channel (control-protocol.md)
Rendering designcraft-render (CPU) The app's renderer
Window tools (screenshot, click, drag, menu_list, ui_inspect, ui_set, dialog_*) Return an error explaining how to connect Work
UI-only commands (view.*, window.*, app.*) via execute Error Work

In connected mode every tool maps to a control-channel method (engine.execute, ui.render, ui.pointer, …), so what the agent does shows up live in the window. The connection is re-established once if the app restarts.

Coordinates

Points (1/72 in), y down, in spread space: on a single-page spread the page's top-left is (0, 0); on a facing spread the right page starts at x = page width. inspect_document lists page bounds per spread. Page indices in render_page / export_png are 0-based. pointer events in connected mode may use "space": "screen" (egui points, see ui_inspect → canvasRect).

Tools

Tool What it does
list_commands Every command (id, label, menu path, shortcut, params, enabled), with filter / enabledOnly
execute Run any command: {command, params}
batch Run commands: [{command, params}] (or script text, one command.id {json} per line) in order, stopping at the first error (reports failedIndex); "$N.path" parameters use earlier results (agents.md)
inspect_document Pages, spreads, items (ids, bounds, fill, story), stories (overset), layers, styles, swatches, selection
get_story Text, frames, paragraphs, lines, overset of a story (story or text frame)
set_story_text Replace a story's text (\n = new paragraph)
new_document file.new (preset, width, height, pages, facingPages, columns, gutter, margins, bleed, title) or sample: true
open_document / save_document Native .designcraft files
place_image Image from path or base64 into frame, the selected frame, or a new frame at x, y, width
render_page Render a page → MCP image content (PNG, base64); optional path to also save it
export_png Write a page as PNG (or JPEG by extension)
screenshot Whole app window → image content (connected only; captured to a temp file and read back)
select_tool Activate a tool (selection, type, rectangleFrame, line, …)
pointer Mouse gesture events (down/drag/up/move/doubleclick) for the active tool, optional tool
key Key press with modifiers (headless: active tool → command shortcuts → tool shortcuts)
type_text Type at the text insertion point (or into the focused dialog field in the app)
click / drag Real pointer input at screen points (connected only)
menu_list, ui_inspect, ui_set Menu tree, UI state, change UI state (connected only)
dialog_set / dialog_confirm / dialog_cancel Fill in and close the open dialog (connected only)

Tool failures come back as results with isError: true and a message the model can act on; protocol errors use JSON-RPC error codes. Resources: designcraft://document (document.inspect) and designcraft://commands.

Example

new_document     {"preset": "A4", "margins": 36}
execute          {"command": "frame.create", "params": {"rect": [36, 36, 559, 200], "content": "text", "text": "Hello"}}
                 → {"id": 8, "story": 9}
set_story_text   {"story": 9, "text": "Summer Fair\nSaturday in the park"}
execute          {"command": "type.char", "params": {"size": 28}}
place_image      {"path": "/tmp/photo.jpg", "x": 36, "y": 220, "width": 523}
render_page      {"page": 0}       → PNG image

Or with the Type tool, the way a user would:

pointer    {"tool": "type", "events": [{"kind": "down", "x": 72, "y": 72}, {"kind": "drag", "x": 300, "y": 200}, {"kind": "up", "x": 300, "y": 200}]}
type_text  {"text": "Hello"}
key        {"key": "Enter"}
key        {"key": "Escape"}

app.links returns the ArtCraft Discord (https://discord.gg/artcraft), the website (https://getartcraft.com), DesignCraft's app page (https://getartcraft.com/apps/designcraft), its GitHub repository (https://github.com/storytold/designcraft) and the issue tracker. In the running app, the UI commands help.discord, help.appPage, help.github, help.issues, help.website, help.app {app} open them in the browser and help.about {tab?} shows the About window (tabs about, contributors, models). The server's serverInfo.websiteUrl is the app page.