* 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> |
||
|---|---|---|
| .. | ||
| assets | ||
| src | ||
| tests | ||
| AGENTS.md | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
| tsconfig.test.json | ||
| tsdown.config.ts | ||
@open-pencil/core
Editor engine for OpenPencil: the CanvasKit (Skia WASM) renderer, Yoga layout, the framework-agnostic editor with undo and selection, the Figma Plugin API compatibility layer, the AI/MCP tool definitions, clipboard and vector conversion, and format-neutral document I/O.
It depends on @open-pencil/scene-graph, @open-pencil/pen, @open-pencil/kiwi, and @open-pencil/fig, and keeps browser DOM out so it runs in the app, the CLI, the MCP server, and headless scripts alike.
Import the root barrel or the targeted subpaths listed in package.json exports, for example @open-pencil/core/io, @open-pencil/core/geometry, and @open-pencil/core/canvaskit.
Scripts get two globals through compileScript from @open-pencil/core/tools: figma, the Figma Plugin API over a document, and openpencil (OpenPencilAPI from @open-pencil/core/openpencil-api), what OpenPencil adds to it in the same style, such as making a component behave as a Reka UI control:
import { FigmaAPI } from '@open-pencil/core/figma-api'
import { compileScript } from '@open-pencil/core/tools'
await compileScript(`
const set = figma.currentPage.findOne((n) => n.name === 'Switch')
openpencil.setBehaviour(set, { kind: 'switch', values: { value: 'State' } })
`)(new FigmaAPI(graph))
- Programmable overview and SDK docs: https://openpencil.dev/programmable/
- Source and issues: https://github.com/open-pencil/open-pencil
MIT License.