open-pencil-headless-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@open-pencil-headless-mcpextract layer tree from design project/landing.fig"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
OpenPencil headless MCP
Inspect and export OpenPencil .fig and .pen files from any MCP client
without opening OpenPencil Desktop and without installing the openpencil CLI.
The server embeds the engine from
salvadorsru/open-pencil in
dist/engine.mjs. npx only installs Node dependencies from the public npm
registry (@modelcontextprotocol/server, zod, canvaskit-wasm, css-tree).
No npm login. No GitHub Packages.
This is not @open-pencil/mcp.
That package is a bridge to a running desktop app. This one reads files on disk.
Requirements
Node.js 20+ (
npxcomes with npm)
Raster export (png, jpg, webp, pdf) downloads canvaskit-wasm the first
time npx runs. Nothing else is required on PATH.
Related MCP server: penpot-headless
Install
From the project root:
npx -y --prefer-online github:salvadorsru/open-pencil-headless-mcp#main -- install-- keeps install as an argument to this package, not to npm. The command
detects the MCP client and writes the right file in that client's JSON shape:
Detects | Writes | Shape |
Cursor (env or |
|
|
VS Code (env or |
|
|
Claude Code (env or |
|
|
Claude Desktop | OS user config |
|
Windsurf |
|
|
If nothing matches, it prints the snippet and does not write. If several
project clients are present and the host is unclear, it also prints instead of
guessing. Override with --client cursor|vscode|claude|claude-code|windsurf
or --out FILE.
Point the sandbox at another folder with --root:
npx -y --prefer-online github:salvadorsru/open-pencil-headless-mcp#main -- install --root /absolute/path/to/your/designsGive each project its own root. A single user-level config can only see one designs folder. Restart the MCP server in your client afterwards.
The server key is pencil. MCP instructions tell the client to use these
tools when the user asks to consult Figma or a .fig, before a Figma
cloud/API/desktop MCP, unless they paste a figma.com URL.
The client starts the server with npx. -y skips the npm prompt.
--prefer-online refreshes main without deleting the npx cache. Progress
goes to stderr (starting, engine loaded, ready, plus the package
version).
Local clone
Skip npx and run the repo you already have:
{
"mcpServers": {
"pencil": {
"command": "node",
"args": ["/absolute/path/to/open-pencil-headless-mcp/server.mjs"],
"env": {
"OPENPENCIL_MCP_ROOT": "/absolute/path/to/your/designs"
}
}
}
}Paths
OPENPENCIL_MCP_ROOT is the only directory the tools can read or write. Point it
at the folder that contains your documents. Tool arguments are relative to
that root:
Root |
|
|
|
|
|
Absolute paths or ../ that escape the root are rejected.
Inspect cache
The first inspect of a .fig still parses the file (~2 s for a large document).
After that, the server writes an index under the designs root:
your-designs/.cache/pencil/project/file.fig.jsonThat folder is your designs root (OPENPENCIL_MCP_ROOT), not the npx cache.
Anyone using npx with the same root reuses it.
The index (v3) is for navigation: TEXT plus named frames, components, instances, groups, and sections. Generic Frame 2147… / Container / vectors are omitted from find/tree.
pencil_find,pencil_tree,pencil_pages,pencil_inforead the index.pencil_nodeandpencil_sectionuse the live graph for style. Afterready, the server warms the graph in the background so the first style query is usually already in memory. If you query before that finishes, only the requested page is populated.Changing the
.fig(new mtime) or an older index version rebuilds the cache.Export, lint, convert, XPath, and analyze always parse the
.fig.
Delete .cache/pencil to force a rebuild.
Tools
Responses are JSON text. File-scoped tools take file relative to the root.
These match the headless CLI. App-only commands (documents, selection,
eval) are omitted: they need OpenPencil Desktop.
pencil_info
Document metadata: page count, node counts by type, fonts.
file: project/file.figpencil_pages
Page list with node counts.
file: project/file.figpencil_tree
Node tree. Optional page (name) and depth.
file: project/file.fig
page: Home
depth: 2Omitting page uses the first page. Large .fig files can be heavy without
depth.
pencil_query
XPath over the document. Optional page and limit (max 10000). Returns id,
name, type, and box. Use pencil_node for text and styles.
file: project/file.fig
selector: //SECTION[@name='Hero']
page: HomeUseful selectors:
//FRAME[@name='Header']
//COMPONENT[contains(@name,'Button')]
//TEXT[contains(@name,'Title')]
//*[@name='Hero']Layer names must match the document exactly.
pencil_find
Find nodes by partial name and/or type (FRAME, TEXT, COMPONENT, …).
Optional page and limit.
file: project/file.fig
name: Hero
type: FRAMEpencil_section
One-shot inspect. Resolves a named block and returns path, descendant copy,
child names, and style (fills, padding, gap, layout) from the live graph.
Prefer this over find + node + tree.
file: project/file.fig
name: Hero
page: Mobile
within: Homepagepage and within are substrings. If several layers share the name, frames and
components win over text.
pencil_node
Full properties for one node from the live graph: fills, strokes, padding,
gap (itemSpacing), layout, type, parent. Works for any id in the document,
including layers omitted from the content index.
file: project/file.fig
id: 12:34pencil_variables
Design variables and collections. Optional collection and type
(COLOR, FLOAT, STRING, BOOLEAN).
pencil_fonts
Fonts used in the document and whether they resolve.
pencil_analyze
kind: colors, typography, spacing, clusters, overlaps.
file: project/file.fig
kind: colors
similar: truepencil_formats
Supported read / write / export formats. No file.
pencil_lint
Quality and accessibility rules. Optional preset: recommended (default),
strict, accessibility.
file: project/file.fig
preset: recommendedpencil_export
Write a derived file inside the root.
Argument | Notes |
| Source |
|
|
| Relative destination, e.g. |
| Optional page name |
| Optional, raster only |
file: project/file.fig
format: png
output: project/exports/hero.png
page: Home
scale: 2Missing fonts on raster/PDF are reported as a warning in the JSON (warn
policy). HTML writes a fragment plus any sidecar assets next to output.
pencil_convert
Write a .fig copy.
file: project/file.fig
output: project/exports/file.figEnvironment
Variable | Default | When it applies |
| process working directory | Runtime. Sandbox for every tool. |
|
|
|
| first existing candidate |
|
There is no OPENPENCIL_CLI.
Develop
The published npx payload is server.mjs + dist/engine.mjs. The source of
the engine is engine.mjs; it is bundled from a sibling clone of the fork.
git clone https://github.com/salvadorsru/open-pencil-headless-mcp.git
git clone https://github.com/salvadorsru/open-pencil.git # sibling directory
cd open-pencil && bun install
cd ../open-pencil-headless-mcp && bun install
bun run bundle
bun run testbun run test runs info on OPENPENCIL_SMOKE_FILE if set, otherwise the
first existing local .fig or .pen fixture it finds.
After changing the fork, regenerate and commit dist/engine.mjs so GitHub npx
picks it up:
bun run bundle
bun run testThis server cannot be deployed
Maintenance
Related MCP Connectors
Render, verify, describe, and safely edit Mermaid diagrams through MCP.
Document-to-Markdown MCP server — convert PDF, Office and HTML into LLM-ready Markdown.
Read, analyze, and safely edit Microsoft Project MPP files.
Document processing over MCP: merge, split and compress PDFs, run OCR, extract document text.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceA hybrid MCP server that proxies Pencil's native design tools and adds utilities for .pen file management, enabling design token extraction, layer trees, diffs, and batch export.MIT
- AlicenseAqualityAmaintenanceA portable MCP server for headless Penpot project/file/content management, using Penpot's RPC API directly. No browser, no Penpot plugin session.5412 npm1MIT
- AlicenseNot gradedqualityBmaintenanceEnables agents to extract, inspect, search, and bundle design context from local Figma .fig files entirely offline, exposing frame summaries, node context, style tokens, assets, vector SVGs, and visual-match review via MCP.MIT
- AlicenseNot gradedqualityBmaintenanceEnables MCP clients to read and modify the currently open Figma design file through a paired local Figma plugin, supporting operations like creating nodes, editing properties, and exporting PNG/SVG.1MIT