* 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]>
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"}
Community links
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.