openpencil/packages/mcp
Victor Wads 68ffd72839
feat(mcp): let MCP clients read only the selection, with a compact get_selection (#732)
* feat(MCP): follow agent activity in canvas

* fix(fig): preserve imported design fidelity

Keep component overrides, variable-backed icon colors, page backgrounds, and fixed text sizing intact across lazy FIG materialization.

* feat: add selection-context MCP tools and mode

* chore: scope work branch to MCP selection and canvas follow

* fix: honor MCP-only tool contracts in CI

* refactor(mcp): drop the follow and selection-context tools this branch carried

Following agents landed in #725, through the agents registry and the
chat's follow toggle, so this branch's MCP follow setting and its
follow-agent module are superseded. The see_user_selection and
get_user_selection_details tools duplicated get_selection, get_node,
describe, get_page_tree, and export_image; the selection-only workflow
they served is rebuilt on those tools in the following commits.

Co-authored-by: Victor Wads <victor@wads.dev>

* feat(mcp): make get_selection the compact entry point with a depth

get_selection returned every selected layer's whole subtree, which is
too much as the first call when the user points at a large frame. It now
returns the selection with direct children by default, counts deeper
children as childCount, and takes a depth.

Co-authored-by: Victor Wads <victor@wads.dev>

* feat(mcp): share only the selection with MCP clients

A selection scope, set with Share only the selection in the local
server settings or OPENPENCIL_MCP_SCOPE=selection, limits MCP clients
to get_selection, get_node, get_page_tree, describe, and export_image
on the selected layers and what they hold.

The server enforces the scope on everything it sends to the app: MCP
sessions and /rpc, which stdio clients also go through, carry only
those tool calls and the session-closed notice, each stamped with the
scope, so a client cannot reach other tools or the settings that would
widen it. The app's bridge rejects node IDs outside the selection,
points describe and export_image at the selection when they name no
nodes, and asks get_page_tree for a root inside it. A stdio client can
ask for the scope itself while the server shares the whole document.

Co-authored-by: Victor Wads <victor@wads.dev>

* fix(mcp): keep selection-scoped clients from writing files or listing wider tools

export_image writes its result to a file when given a path and an MCP
root is set, which reaches past reading the selection. A path is now
refused in selection scope, by the tool registration before the call
and by the app's bridge, so a client with a stale scope cannot write
either; the image itself is still returned.

A stdio client follows the narrower of its own scope and the scope the
server records, instead of letting OPENPENCIL_MCP_SCOPE=document list
tools a selection-scoped server rejects.

Co-authored-by: Victor Wads <victor@wads.dev>

* test(mcp): name the selection scope's tools instead of reading the allowlist

The server test compared the listed tools with SELECTION_SCOPE_TOOLS,
the same list that decides registration, so a tool added to it by
mistake would still pass. It now names the five tools the scope offers.

Co-authored-by: Victor Wads <victor@wads.dev>

---------

Co-authored-by: Danila Poyarkov <dev@dannote.net>
2026-10-07 13:01:28 +00:00
..
bin build: publish node-compatible packages 2026-05-21 17:03:19 +03:00
src feat(mcp): let MCP clients read only the selection, with a compact get_selection (#732) 2026-10-07 13:01:28 +00:00
tests feat(mcp): let MCP clients read only the selection, with a compact get_selection (#732) 2026-10-07 13:01:28 +00:00
AGENTS.md docs: route contributors through per-domain guides and ship npm license text (#785) 2026-09-29 01:02:06 +04:00
package.json feat(mcp): let MCP clients read only the selection, with a compact get_selection (#732) 2026-10-07 13:01:28 +00:00
README.md docs: route contributors through per-domain guides and ship npm license text (#785) 2026-09-29 01:02:06 +04:00
tsconfig.json feat(mcp): add local transport discovery 2026-07-25 21:29:03 +03:00
tsdown.config.ts feat(mcp)!: migrate to SDK v2 and Valibot 2026-09-14 00:54:13 +03:00

@open-pencil/mcp

Model Context Protocol server for OpenPencil. It lets MCP clients such as Claude Code, Cursor, and Windsurf inspect and edit designs through the running app, reusing the same tool definitions as the built-in AI chat.

npm install -g @open-pencil/mcp
openpencil-mcp        # stdio transport for MCP clients
openpencil-mcp-http   # Streamable HTTP transport for browser extensions and scripts

On macOS and Linux, local clients prefer a private Unix domain socket; Windows and unavailable sockets fall back to localhost TCP. File access is limited to the effective MCP root.

MIT License.