Penpot MCP Skill

SkillFiles & storage

Use this skill whenever the user wants to use AI agents to work with Penpot design files via the Penpot MCP Server. Triggers include: using Penpot through an AI agent, design files, design systems, design tokens, Penpot MCP, design-to-code, generating UI from design, auditing a design system, creating components/variants, renaming layers, exporting assets from Penpot, adding flows, interactions, animations, overlays, or prototyping in Penpot, or prompting an AI agent to read/modify a Penpot file. Also triggers when the user wants to set up Penpot MCP, connect any MCP-compatible AI agent or IDE to Penpot, or produce production-ready HTML/CSS/React from a Penpot design. Use this skill for Penpot-agent workflows — design, code, audit, prototyping, or setup.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Penpot MCP Skill skill

What this skill tells your AI

The instructions your AI receives, as published by ar27111994/penpot-mcp in penpot-mcp/SKILL.md and read by ahel’s review.

AI-agent workflows for creating, auditing, and maintaining production-grade design projects and design systems — including flows, interactions, animations, tokens, and visual effects — in Penpot via the official MCP Server.

Compatible AI Agents

Works with any MCP-compatible client: Claude Code, Cursor, VS Code / Copilot, Codex / OpenCode, Amp, Cline, Windsurf, Claude Desktop (via mcp-remote), and any agent supporting HTTP or SSE MCP transport.


Architecture Overview

MCP Client (any MCP-compatible agent / IDE)
      ↕  HTTP  (or stdio via mcp-remote proxy)
MCP Server (hosted remote OR local npx)
      ↕  WebSocket / plugin bridge
Penpot Plugin (running inside the open design file)

MCP always acts on the currently focused page in the active Penpot browser tab. Only one tab can own MCP at a time.

MCP runs through the Penpot MCP plugin. It does not provide a documented way to enumerate, install, launch, or drive arbitrary installed community plugins. Coordinate with other plugins only when the user explicitly asks or when file-visible evidence makes a plugin relevant.


1. Connection Setup

Remote MCP (recommended for most users)

  1. Penpot → Your account → Integrations → MCP Server → enable
  2. Generate MCP key (shown once — store safely; only one key per user at a time)
  3. Copy server URL: https://<your-penpot-domain>/mcp/stream?userToken=YOUR_MCP_KEY
  4. Add to your MCP client config (see snippets below)
  5. Open a design file → File → MCP Server → Connect

Local MCP (advanced; extra file-system access)

npx @penpot/mcp@stable   # keep running; matches current Penpot release
npx @penpot/mcp@beta     # for beta/test environments
  • Load plugin: Plugins → Load from URLhttp://localhost:4400/manifest.json
  • Click Connect to MCP server in plugin UI → keep plugin window open at all times
  • Client URL: http://localhost:4401/mcp (no auth; preferred for single-client setups)
  • SSE fallback: http://localhost:4401/sse (use when /mcp transport conflicts occur, or with mcp-remote for stdio-only clients)

Client Config Snippets

Claude Code (.claude/settings.json):

{
  "mcpServers": {
    "penpot": { "transport": "http", "url": "REMOTE_OR_LOCAL_URL" }
  }
}

Cursor:

{ "mcpServers": { "penpot": { "url": "REMOTE_OR_LOCAL_URL", "type": "http" } } }

VS Code / Copilot (settings.json):

{
  "mcp.servers": {
    "penpot": { "transport": "http", "url": "REMOTE_OR_LOCAL_URL" }
  }
}

Codex / OpenCode:

{
  "servers": {
    "penpot": { "url": "REMOTE_OR_LOCAL_URL", "transport": { "type": "http" } }
  }
}

Claude Desktop (stdio-only — requires proxy):

npx -y mcp-remote http://localhost:4401/sse --allow-http

Troubleshooting Checklist

  • Restart MCP server process
  • Reconnect plugin (File → MCP Server → Connect)
  • Restart MCP client / reload tools
  • Error: Already connected to a transport → close other MCP clients; use /sse fallback if /mcp conflicts
  • Keep plugin window open while agents run at all times
  • Firefox preferred if Chromium blocks localhost from https://design.penpot.app
  • Expired MCP key → regenerate in Penpot → Integrations; update all client configs

2. Available MCP Tools

ToolModeDescription
high_level_overviewBothRead overall file structure, pages, layers, components
penpot_api_infoBothQuery Penpot plugin API documentation
execute_codeBothRun JavaScript in Penpot plugin context — primary read/write tool
export_shapeBothExport shape as PNG/SVG (remote: limited; may fail with HTTP error)
import_imageLocal onlyImport image from local file path into design

Remote MCP cannot import images from local paths. export_shape may fail with HTTP errors — always verify structurally via API rather than relying on export success.

Check connection first (always)

Before any setup steps, call penpot_api_info or high_level_overview first. If it succeeds, skip setup entirely.

Community plugin guardrails

  • Do not assume MCP can read the user's installed plugin list or invoke another plugin's UI/API.
  • Prefer MCP-native reads/writes for normal design, prototyping, token, and export tasks.
  • If a community plugin could materially help, first look for file-visible evidence: generated layers, library assets, comments, or namespaced shared plugin data.
  • If the user provides an installed-plugin inventory, treat it as user-provided context and select a plugin only when the task clearly maps to that plugin's stated capability.
  • Ask for user confirmation before using or relying on any community plugin. If it has its own UI, ask the user to run it manually, then re-inspect the file.
  • Never use a plugin marketplace/browser plugin such as Plugins list unless the user explicitly asks to browse, search, discover, or install plugins. Do not search/install plugins automatically for routine tasks.

JavaScript API

execute_code runs JS against the Penpot plugin API. Read references/penpot-api-patterns.md before any execute_code calls. It covers the full API including tokens, library creation, page management, visual effects, storage, and idempotency helpers.


3. Safety-First Workflow (ALWAYS follow this order)

1. READ   → Inspect, list, analyze (never skip)
2. PLAN   → Describe intended changes BEFORE applying
3. WRITE  → Small atomic batches; one logical unit per call
4. VERIFY → Structural read after each write batch (not export-based)

Write call limits — enforce strictly:

  • Max ~5–10 shape operations per execute_code call
  • Pause and verify between batches
  • Never "build everything" in one call — MCP writes time out on large batches, leaving partial updates with no error indication

Page switching — two-call pattern (mandatory on Penpot ≤ 2.16.x, defensive habit on 2.17+):

Call N:   penpot.openPage(page)    ← switch page (currentPage still reports OLD page on ≤ 2.16)
Call N+1: any operation            ← now on new page; currentPage updated

⚠️ Penpot ≤ 2.16.x only — fixed upstream in 2.17.0 (#10078): penpot.currentPage does NOT update until the next tool call after openPage(). Writing shapes in the same call as openPage() silently applies them to the previously active page. This is a plugin-bridge bug, not a permanent API contract. On Penpot ≥ 2.17.0, currentPage updates immediately after openPage() and the two-call pattern is unnecessary — keep it anyway as a harmless defensive habit.

remove() is unreliable across calls — Boards deleted via shape.remove() may reappear in subsequent structural queries (getPages()shapeStructure()). The remove appears to succeed in the current call, but stale boards from previous sessions can reappear when the page structure is re-read. (No upstream fix published through 2.18.0 — treat cleanup as best-effort and always verify structurally in a later call.)

Always verify the page before writing: after openPage(), always make a lightweight read-only call first (e.g. return penpot.currentPage?.name) before creating any shapes.

Use storage for large workflows:

// Call 1: compute and store your design token data
storage.tokenData = { colors: { primary: '#HEX' }, spacing: 8, ... };
// Call 2+: retrieve from storage instead of recomputing
const fallback = { colors: {}, spacing: 8 }; // safe default if session reset
const DS = storage.tokenData || fallback;

Starter prompts (always run first after connecting):

"List all pages in this file."
"Show all components on this page."
"Analyze the design structure and summarize the token system."

4. Role & Prompt Engineering

Define the agent role precisely

BAD:  "You are a creative designer."
GOOD: "You are a Senior Product Designer expert in design systems, WCAG accessibility,
       Penpot plugin API constraints, and Penpot-to-code workflows. You do not make
       product decisions without data. You never invent tokens, colors, or components
       not present in the file. You always work in small reversible batches."

Structured Brief Template

CONTEXT: [product name, target user, current state of file]
GOAL: [specific problem — e.g., "build design token system and foundations page"]
INPUTS: [page names, board names, component names, token paths, brand colors]
CONSTRAINTS:
  - Max ~10 shape operations per execute_code call
  - Always use idempotency helpers (ensureColor, ensureTypography, etc.)
  - Never switch page and write in the same call
  - Never invent font weights not confirmed installed for this family
  - Verify structurally after each batch — do not rely on export_shape
  - Store shared data in storage global for cross-call access
QUALITY CRITERIA: [how you'll know it's done]

Negatives (always include)

  • "Do not invent colors not in the token set."
  • "Do not use font weights not confirmed installed for this font family."
  • "Do not switch page and write in the same execute_code call."
  • "Do not rely on export_shape for verification — use structural API checks."
  • "Do not create duplicate colors/typographies — always check before creating."

Iteration pattern

1. Discovery  → read all pages, library assets, tokens, existing components
2. Proposal   → describe planned structure, wait for approval
3. Foundation → build token sets + themes + colors + typographies (batched)
4. Structure  → create pages (all in one call), then build boards per page (separate calls)
5. Components → register library components from source boards
6. Verify     → structural checklist — count colors, typographies, components, token sets

5. Token-Aware Prompting

Global RULESET block (prepend to every design-system prompt)

GLOBAL RULESET
- SOURCE: Penpot MCP only
- NO_GUESSING: true
- IF_MISSING: mark as TODO
- PREFER: structured data > prose
- OUTPUT: deterministic, stable ordering
- BATCH_LIMIT: ~10 ops per execute_code call
- PAGE_SWITCH: separate call from writes
- IDEMPOTENCY: always check-before-create
- STORAGE: use storage global for cross-call data
SIZE CONSTRAINTS
- design-system.json: tokens + mappings only
- components.catalog.json: real components only
- layout-and-rules.md: max ~300 lines
STYLE
- Use schemas, key:value, compact bullets
- No narrative explanations

Token hierarchy

Tier 1 (Global):    color.base.neutral.100, spacing.base.8
Tier 2 (Semantic):  color.bg.default, color.text.primary
Tier 3 (Component): color.button.primary.bg

Reference tokens can be other tokens: '{color.base.neutral.100}' — use curly brace syntax.


6. Workflow Recipes

Read the relevant reference before starting:

  • Full API, tokens, page management, storage, visual effectsreferences/penpot-api-patterns.md (mandatory before any execute_code calls)
  • Design system creation/auditreferences/design-system-workflows.md
  • Design-to-code generationreferences/design-to-code-workflows.md
  • Prototyping: flows, interactions, animationsreferences/prototyping-workflows.md

Quick reference: Common task prompts

Design system from scratch:

"Read all existing pages, colors, typographies, and token sets in this file."

"Build the token system: create token sets [base, theme-light, theme-dark],
populate with [color palette] + spacing (8px grid) + border radii + motion tokens.
Use addToken idempotency. Store DS object in storage. Max 15 tokens per call."

"Create library colors from the base token set.
Use ensureColor pattern. 5 colors per call, pause after each batch."

"Create typographies for the scale: [paste scale].
Use ensureTypography. Check installed font variants first."

Multi-page design system:

"Create pages: [Page1], [Page2], [Page3] — all in one call (list all pages to create).
Then report the current page list before doing anything else."

"Switch to page [PageName]. Confirm currentPage before writing."

"Build the [BoardName] board on the current [PageName] page.
Max 8 shapes per call. Pause after."

Prototyping tasks:

"List all boards on this page and their existing interactions."

"Create a prototype flow entry for '/flows/onboarding-start' using Page.createFlow."

"Add click→navigate interactions from [BoardA] to [BoardB] with Dissolve 300ms."

"Audit all interactions: list broken destinations and prototype coverage percentage."

Visual effects:

"Apply a backdrop blur effect to the [BoardName] overlay:
[N]px layer-blur, [N]px borderRadius, semi-transparent surface fill,
and a drop shadow. Describe the values you'll use before applying."

"Add linear gradient fill to [ShapeName]: brand primary → transparent, top to bottom."

7. Design File Best Practices

File & page structure

  • Choose one page organisation strategy:
    • Domain-based: e.g. Foundations, Mobile, Desktop
    • Atomic-level: e.g. Tokens, Primitives, Components, Patterns
  • Canvas: wireframes left → final design right
  • Every board has a clear purpose and visual entry point

Layer naming

  • Function-based: background, icon-close, label-primary
  • Not appearance-based: rectangle-23, blue-box
  • Hierarchy with /: component/card/default, overlay/confirm-delete

Components

  • Naming: mobile/card/default, mobile/nav-bar
  • Register from source shapes via createComponent([shapes])
  • Clone source shape first if it's already placed on a page

Spacing & layout

  • Base unit: 8px. All margins/paddings derived from it.
  • No invisible rectangles for spacing — use Flex/Grid layout

Visual effects & glassmorphism

  • Glass recipe: blurs: [{ type: 'layer-blur', value: 20 }] + borderRadius: 20 + shadow
  • Shadow color: { color: '#hex', opacity: 0.06 } (not r/g/b/a)
  • Ghost border only when accessibility explicitly requires it

Prototyping

  • Flow entry boards: prefix /flows/[journey]-start
  • Overlay boards: prefix overlay/
  • Create flows via page.createFlow('name', entryBoard) or Prototype panel

Accessibility

  • WCAG AA contrast minimum for all text
  • 44px min touch target (iOS) / 48dp (Android)
  • Never use color alone to communicate status

Handoff readiness

  • Component/variable names developer-readable
  • No duplicates — single source of truth

8. Model Selection

  • Always use frontier models (Claude Sonnet/Opus, GPT-4o, Gemini Pro)
  • VLM required for image-based tasks
  • More complex tasks → stronger model
  • Token-constrained workflows → apply RULESET block from §5

9. Key Gotchas

MCP/infrastructure:

GotchaMitigation
MCP acts on focused page onlyConfirm page focus before each write batch
Write ops immediate — no undo via MCPPlan + describe before applying
Large batches time out silentlyMax ~10 ops per call; verify after each
Page switch is asyncNever switch page and write in same call
export_shape may fail with HTTP errorVerify structurally via API; export is best-effort
Remote MCP can't read local file systemUse local MCP for import_image
Only one active MCP tabClose other Penpot tabs before running agents
Error: Already connected to a transportClose other MCP clients; use /sse fallback if /mcp conflicts
MCP key shown only onceCopy immediately; regenerate if lost
Expired key blocks all connectionsRegenerate in Integrations; update all configs
Chromium ≥142 blocks localhostUse Firefox, or allow local network explicitly

Penpot plugin API (full detail → references/penpot-api-patterns.md):

GotchaMitigation
shape.width / shape.height READ-ONLYUse shape.resize(w, h)
shape.x / shape.y READ-ONLY for parented shapesUse penpotUtils.setParentXY(shape, x, y)
shape.x / shape.y for root-level boards✅ Direct assignment works
appendChild ignores z-orderUse insertChild(index, shape)
Flex children reversed for column dirsLast inserted = top visually
penpot.createText(...) may return nullGuard before resize/style calls; return a clear error if unavailable
Text clips after resize()Always reset growType after every text.resize()
Font weight rejectionOnly use weights explicitly installed for the font family
Library fontSize must be string"16" not 16; library typographies use fontFamilies not fontFamily
LibraryColor.color for hex.color = '#hex' not .fillColor
shape.blurs is an arrayshape.blurs = [{ type: 'layer-blur', value: 20 }]
Shadow color format{ color: '#hex', opacity: 0.15 } not {r,g,b,a}
Typography fontId stays staleKnown API limitation; rendered layers use correct ID
storage resets on server restartAlways use a fallback value when reading
Page.findShapes() takes criteria objectpage.findShapes({ type: 'board' }) not a predicate
createComponent wraps an arraycreateComponent([shape]) not createComponent(shape)

Signals

GitHub stars
25
Forks
3
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
penpot-mcp
Source
github.com/ar27111994/penpot-mcp