Pencil MCP for Claude Code Setup 2026

GuidesAugust 24, 20268 min readBy PinVari
Pencil MCP for Claude Code Setup 2026

Pencil MCP for Claude Code is the local Model Context Protocol server that pen.dev starts when the app is running, so Claude Code can read and edit .pen files instead of guessing from a PNG of the canvas. It is the right plug for "what should this screen look like in the file."

It is the wrong plug for "what is broken in the running app on this Mac right now." Those are two contexts. Most write-ups mash them together.

I run both. Pencil for the file. A local screen MCP for the live window. Claude Code stays the client.

If MCP is still abstract, start with what an MCP server is and the Claude Code MCP primer, then come back.

What does Pencil MCP for Claude Code actually expose?

pen.dev documents a small, honest tool set. The agent does not get a secret second model. It gets tools.

execute is the workhorse. Insert, copy, update, replace, move, delete. Read nodes with a Get visitor. Filter with plain JavaScript. Inspect ctx.bounds and ctx.problems when something is clipped.

TakeScreenshot renders a preview of the design, not a live OS window. GetVariables and SetVariables sit inside execute. get_app_state returns selection, active file, and editor context.

The server is not the model. It answers structured reads and writes against the .pen file that is open.

Exact names can shift. Treat pen.dev's AI integration page as the source. Do not invent a longer tool list.

The mental model matches other MCP tools: advertise, call, return. The agent decides when to call.

Key

Pencil MCP for Claude Code answers "what is in the .pen file." It cannot tell the agent which control you just clicked in the Electron preview on your second display.

The MCP server is local. Design operations stay on the Mac. That is a privacy win. It is not a substitute for a named Accessibility hit on the running UI.

How do I set up Pencil MCP for Claude Code start to finish?

This is the path I use on a Mac when I need a real landing-page loop, not a demo gif.

Install Claude Code and run claude once so auth is done. Install pen.dev (desktop or IDE extension) and finish activation. Open the project that holds design.pen.

Start pen.dev first. Wait until the canvas is actually up. Then open the .pen file. Then start Claude Code in that project directory.

claude

Inside the session, run /mcp. You want a pencil server listed and connected. If it is missing, pen.dev was not running, or you started Claude Code first.

pen.dev's own docs keep the order strict: app running, file open, then the agent. I have wasted an hour reversing that.

If you need an explicit allow list, Claude Code settings can include:

{
  "permissions": {
    "allow": ["mcp__pencil__*"]
  }
}

Some third-party posts show a handmade mcpServers.pencil block with command: pencil and args: ["mcp-server"]. Treat that as a fallback. The current product starts the server when pen.dev is running. Confirm with /mcp before you fight JSON.

Tip

Name the servers by job in your head: pencil for intent on the canvas, pinvari for the live element. When the agent edits the wrong button, you needed the second one.

A first prompt that actually works: "In the open .pen file, add a hero with heading, subheading, and one primary CTA. Use existing color variables. Do not invent a new palette."

Watch the canvas. If execute ran, the nodes change immediately. If nothing moved, the server never connected.

Then generate code only after you accept the frame. "Generate React for the selected hero. Match the variables. Do not restyle."

Commit both sides when they agree:

git add design.pen src/pages/landing.tsx
git commit -m "Add landing hero from pencil frame"

That is the whole happy path. File, then code, then git. No screenshot soup.

Why does design-to-code still fail with a perfect Pencil MCP?

The file is clean. The running UI drifted. Padding changed in code and nobody updated the .pen.

The agent implements the file and "fixes" a deliberate live experiment. Or it implements a frame you were not looking at.

Two buttons share a component. The file says Primary. The live window has two Primaries in two groups. Pencil MCP cannot see the one you hovered.

Live UI needs Accessibility. AXUIElementCopyElementAtPosition returns role, label, frame, parent chain. Confidence and circled-vs-dwelled provenance tell the agent how the hit happened.

When the overlay would hit-test itself, chainExcludingSelf walks real windows. Electron needs AXManualAccessibility and a short retry. Bare AXGroup should descend to a labeled child. Chromium ids (AXDOMIdentifier, AXDOMClassList) name title-less nodes.

OCR is the fallback on canvas. Ask below 0.8 confidence. Never silently guess.

That bundle is what pinvari_next_instruction returns, plus spoken words and a crop. pinvari_request_capture lets Claude Code ask you to point mid-task.

Pencil MCP

Type: local server started by pen.dev while a .pen file is open.

Capture: nodes, variables, selection, design screenshots via TakeScreenshot.

Resolution: file structure. No live AX role or confidence.

Live screen MCP (PinVari)

Type: local stdio connector at ~/.pinvari/mcp/pinvari-mcp, talking to the app on 127.0.0.1:3402.

Capture: cropped screenshot, spoken instruction, pointer trail, window text up to 40,000 characters.

Resolution: named AX element, confidence, circled-vs-dwelled provenance.

Screenshot-only prompt

Type: you paste a PNG into Claude Code.

Capture: pixels. Tokens burn on the image.

Resolution: a guess. Two identical buttons stay identical.

How do I wire PinVari next to Pencil MCP for Claude Code?

Install PinVari from the pricing page. The app must be running. The connector talks to it on 127.0.0.1:3402.

One-click: PinVari → Connect → Claude Code.

CLI, never the bare claude mcp add pinvari (that errors):

claude mcp add --scope user pinvari -- "$HOME/.pinvari/mcp/pinvari-mcp"

--scope user writes to ~/.claude.json so every repo sees it. You do not want to re-add this in every project.

Hotkey is ⌥⌘A, press-to-toggle. Press again or ⏎ to finish. ⌥⌘V is voice-only. ⌥⌘P pauses across a scroll.

Freehand marks. Multiple regions in one breath. Each mark gets its own words. Dwell ~0.2s resolves without a circle.

The agent-facing tools you will see: pinvari_next_instruction, pinvari_get_capture, pinvari_list_captures, pinvari_get_frame, pinvari_request_capture, pinvari_mark_done, pinvari_health.

pinvari_mark_done closes the instruction after the edit. Do not leave it hanging.

Heads up

If /mcp shows PinVari as failed, the app is not running or port 3402 is blocked. Start the app first. Then reconnect. Pencil being green does not prove the screen server is up.

A prompt that works once both servers are live: "Read the selected Pencil frame for spacing tokens. Then take the next PinVari instruction. Edit only the named element. If confidence is below 0.8, ask."

Do not say "match the screenshot." The crop is evidence. The AX path is the address.

Deixis is bound to the pointer trail. "Make this 8px tighter" knows what "this" was at the instant you said it.

Multi-display: each mark remembers its monitor. One capture can span screens. The crop is from the display you drew on.

Bring your own agent. PinVari does not call an LLM. Transcription and OCR stay on-device. Pencil MCP still talks to the local .pen file. Keep those boundaries in your head.

If you are new to the CLI, the how to use Claude Code walkthrough covers /mcp, permissions, and session habits.

How do I debug a dead Pencil MCP for Claude Code session?

Run claude mcp list. You want pencil (or pen.dev's current name) and pinvari both present.

Inside a session, /mcp is the live check. A configured server can still be disconnected.

pen.dev not running. Start it, open the .pen, restart Claude Code in that directory.

You started Claude Code first. Quit the session. Start pen.dev. Open the file. Start claude again.

Auth expired. Re-run claude and complete login. "Invalid API key" in pen.dev's troubleshooting usually means Claude Code is not authenticated, not that Pencil is broken.

Scope surprise: you allowed mcp__pencil__* in repo A and opened repo B with a tighter permission file. Re-check settings.

Claude Code version lag. claude --version. Then restart both apps.

Canvas-only surfaces in the running app still need OCR. AX will be empty. That is not a Pencil MCP bug.

Jam.dev is still excellent for browser console logs. It cannot see a native Mac window or your IDE. Marker.io is browser annotation on a subscription. Neither replaces a named AX hit.

CleanShot X remains the screenshot king. It does not name the control.

FAQ

Does Pencil MCP for Claude Code replace screenshots?

No. Pencil MCP for Claude Code replaces guessing at the design file. A cropped screenshot is still useful evidence for a visual bug. The named AX element is the address the agent should edit.

Do I have to hand-write an mcpServers.pencil block?

Usually no. Start pen.dev, open a .pen file, then start Claude Code. Confirm with /mcp. Only add a manual command block if the official path stays empty.

Why did Claude Code implement a different button than the one I circled?

You probably sent a Pencil node and no live instruction. Or two live buttons share a label and confidence dropped. Check provenance. Circled beats dwelled when both exist.

Can I keep Pencil at project scope and PinVari at user scope?

Yes. Project-scope Pencil is reasonable if the repo owns the .pen file. Keep the screen connector at user scope. It is a personal Mac tool, not a repo secret.

What if AX is empty on a canvas or game view?

OCR fallback. Whole-screen on-device OCR is optional. Confidence will often sit below 0.8. The agent should ask, not invent a selector.

Is anything uploaded when I circle a live control?

Not by PinVari's default path. Capture stays on the Mac. The connector is local. Pencil MCP is also local to the .pen file. Those are separate pipes from whatever LLM you already pay for.

Hand your agent the exact element

PinVari resolves what you point at into a named, executable instruction — on-device, no keys, your own agent. One click inside PinVari connects Claude Code, Cursor, VS Code or Codex — or paste one CLI line from pinvari.com/connect.

PinVari → Connect → your agent (one click)
Get PinVari — $39 →