本文へ移動
cccskills
無料GitHub で公開

penpot-mcp

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.

インストール方法を見る

含まれるファイル(5)

  • SKILL.md23.8 KB
  • references/design-system-workflows.md7.4 KB
  • references/design-to-code-workflows.md9.3 KB
  • references/penpot-api-patterns.md42.8 KB
  • references/prototyping-workflows.md12.9 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Penpot MCP Skill

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 URL → http://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 — project-scoped MCP servers live in .mcp.json at the repo root, NOT in .claude/settings.json (that file only has enabledMcpjsonServers / enableAllProjectMcpServers, which toggle trust for servers already defined in .mcp.json — it never itself holds an mcpServers block):

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

Or register it without hand-editing a file:

claude mcp add --transport http penpot REMOTE_OR_LOCAL_URL

Cursor:

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

VS Code / Copilot (.vscode/mcp.json — VS Code expects a top-level servers object here, not an mcp.servers setting in settings.json):

{
  "servers": {
    "penpot": { "type": "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
  • The Penpot plugin tab appears to be suspended by the browser (no heartbeat for Ns) (server ≥ 2.18) → the server treats the tab as frozen when the plugin sends nothing for 30 s. It is not always a background tab: after a server upgrade the browser can keep serving the old plugin code, which never sends heartbeats. Clear the Penpot site data, hard-reload, then reopen the plugin and press Connect. Server log check: New WebSocket connection established followed by silence can indicate stale plugin code, especially after an upgrade — but a suspended background tab produces the same pattern, so treat it as a lead, not proof.
  • Since 2.18.0 the MCP key is no longer accepted as a regular Penpot API access token (security fix #10960/#10962). Integrations that call the REST API need their own access token.
  • No Penpot instance connected for user token → the plugin is not connected (panel closed, or it connected and closed again) or the plugin's MCP key differs from the userToken in the client URL

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.

export_shape takes mode: "shape" (default, the shape with descendants) or mode: "fill", which exports the raw image used as the shape's fill (PNG only).

Tool registration is conditional (server 2.18). The four "Both" tools are always registered. import_image exists only when the server has file-system access, so only in local mode. cljs_repl, cljs_compiler_output, clj_check_parentheses, import_penpot_file and read_taiga_issue are developer tools, registered only in a dev environment and never in multi-user mode. A remote team server therefore exposes exactly four tools. Do not plan work around the others.

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. The 2.18.0 types declare openPage(page: Page | string): Promise<void>, and their JSDoc example does await penpot.openPage(page) and then writes in the same call. Sources disagree, though: a live probe in penpot/penpot-ai-kit (dated 2026-08-10, after the fix) still saw the old two-call behaviour. Until it is probed on your instance, await the call and keep the two-call pattern.

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 effects → references/penpot-api-patterns.md (mandatory before any execute_code calls)
  • Design system creation/audit → references/design-system-workflows.md
  • Design-to-code generation → references/design-to-code-workflows.md
  • Prototyping: flows, interactions, animations → references/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
No heartbeat for 30 s = "tab suspended" (≥ 2.18)See Troubleshooting: stale plugin code after an upgrade looks the same as a frozen tab
Export after a 2.18 upgrade can differ from 2.17Observed in export_shape output after upgrading a self-hosted instance to 2.18.0: inner shadows painted over a board's children (an active nav item rendered empty), auto-width text clipped to a stale width. Check the canvas before blaming the design
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)
penpot.fonts.findByName matches by substring (penpot-ai-kit, unverified here)"Roboto" can return "Roboto Mono": filter penpot.fonts.all by exact name
layoutChild.horizontalSizing = "fill" may set flipX = true (penpot-ai-kit, unverified here)Read flipX back after sizing changes and reset it
Variant groups need a strict multi-step orderUse penpotUtils.createVariantContainer([{ shape, properties: { Size: 'S' } }, …]); on an instance switch with instance.switchVariant(pos, value)

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

このスキルの問題を報告する