Model or dataset
penpot/penpot-mcp avatar
penpot/penpot-mcp

Penpot MCP Server: design files as an LLM execution target

Penpot's official MCP Server

503 stars67 forksTypeScriptMPL-2.0

At a glance

What is it?
Penpot's official MCP server lets an LLM read and rewrite a design file by executing code through the Penpot Plugin API. The repository is archived and its contents now live in the main Penpot monorepo.
Who is it for?
Adopt it if you want an LLM to inspect and modify Penpot files through the Plugin API and you are willing to run two local servers and keep a browser tab open. Skip it if you need a headless service, a stdio-only client without a proxy, or a stable dependency pinned from a release tag, because this repository is archived with no releases and the code now lives in the main Penpot monorepo under mcp/.
Can I use it commercially?
Yes, with conditions. MPL-2.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
Is it still maintained?
Yes. The repository last received commits 180 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem: design tools that only humans can operate

A design file is a closed object. Tools read it through an export, and an export is a snapshot: once it is written, the structure behind it is gone. Penpot's MCP server takes a different route. It exposes tools to AI clients so an LLM can retrieve design data, transform it, and create new elements. The README frames the intended workflows as design-to-design, code-to-design and design-to-code. The audience is narrower than that phrasing suggests. This is for people already running Penpot who want an LLM to operate inside a live file rather than around a static export, and who accept that the operation happens in a browser session they keep open.

WebSocket bridge between the MCP server and a Penpot plugin

The architecture has three moving parts. The MCP server exposes tools to AI clients. A dedicated Penpot MCP Plugin runs inside Penpot and connects to that server over WebSocket. The plugin is what actually touches the design file, because it executes code against the Penpot Plugin API. The README states that the LLM is free to write and execute arbitrary code snippets within the Penpot Plugin environment. That sentence is the whole design in miniature. There is no fixed set of typed operations that map one-to-one onto design actions. The model composes code, the plugin runs it, and the result comes back over the socket. The consequence is that the server's capability surface is roughly the Plugin API surface, which is large, and the failure surface is equally large, because a generated snippet can do anything the plugin is permitted to do. The repository contains both the server and the supporting plugin, which is why the setup requires two servers rather than one.

Getting it running: bootstrap, plugin URL, two endpoints

Prerequisites are Node.js, tested with v22, plus npm and npx. The first run is npm install. Then npm run bootstrap, which the README describes as running install:all, build:all and start:all in sequence. On the Penpot side, open a design file, open the Plugins menu, and load the plugin from the development URL, http://localhost:4400/manifest.json by default. The plugin UI then has a Connect to MCP server button, and the status should change from Not connected to Connected to MCP server. The server itself listens on port 4401 by default and offers two endpoints: a modern Streamable HTTP endpoint at http://localhost:4401/mcp and a legacy SSE endpoint at http://localhost:4401/sse. Claude Code can be pointed at the HTTP endpoint directly with claude mcp add penpot -t http http://localhost:4401/mcp. Clients that only speak stdio need a proxy. The README gives mcp-remote for that, installed with npm install -g mcp-remote and launched as npx -y mcp-remote http://localhost:4401/sse --allow-http. For Claude Desktop, the entry goes under mcpServers in claude_desktop_config.json, with paths %APPDATA%/Claude/claude_desktop_config.json on Windows, ~/Library/Application Support/Claude/claude_desktop_config.json on macOS and ~/.config/Claude/claude_desktop_config.json on Linux. The README is explicit that the app must be fully quit, not just closed, before the entry appears.

The constraint that breaks setups: localhost from a hosted origin

The plugin runs inside a page served from a different origin than the local server, and recent Chromium builds enforce private network access restrictions. The README notes that from Chromium version 142 the connection to localhost must be explicitly allowed, and that most Chromium-based browsers will show a permission popup that has to be approved. Some browsers go further. In Brave, the README says to disable the Shield for the Penpot website. If the browser refuses the connection, the suggested fallback is to check its configuration or try a browser that does not enforce these restrictions, with Firefox named as an example. This is not a configuration detail you can route around. It is the load-bearing assumption of the whole setup: a hosted web app reaching into a machine-local server. Any environment that blocks that path, a locked-down browser profile, a corporate policy, a remote desktop session where localhost is not where you think it is, fails before the LLM sees a single design element.

The plugin UI is a session dependency, not a control panel

The README carries one warning in bold that changes how you deploy this. Do not close the plugin's UI while using the MCP server, because closing it closes the connection. The plugin is not a launcher that starts something and steps aside. It is the transport. A long-running agent session therefore depends on a browser tab staying open, on the machine where Penpot is loaded, for the entire duration of the work. That rules out the obvious operational shapes: a scheduled job, a CI step, a server-side batch run. It also means the connection is tied to a human's browser session, and a crash, a reload or an accidental tab close ends the run mid-task. The README does offer diagnostics for this: WebSocket connection logs in the browser developer console, and connection messages in the MCP server terminal.

Archived code, no releases, and what that costs

The most important line in the README is at the top. The repository was archived on 2026-02-03 and its contents have been fully integrated into the main Penpot repository at github.com/penpot/penpot/tree/develop/mcp. No releases were retrieved for this repository. Two practical consequences follow. First, there is no versioned artifact to pin. If you want a fixed dependency, you are tracking a path inside a much larger monorepo on the develop branch, and the thing you depend on moves with that repository. Second, fixes and changes do not land here. A bug you find in this code has to be checked against the copy in the main repository before it is worth reporting. The monorepo layout described in the README has four main components, with common/ holding shared TypeScript definitions for the request and response protocol so the pieces stay type-safe against each other. That split is why the plugin and the server can be versioned together, and it is also why pulling just one directory out of the monorepo is likely to be awkward. The licence is MPL-2.0, a file-level copyleft licence. If you modify covered files and distribute them, the usual MPL obligations attach to those files. Nothing here is legal advice; check how MPL-2.0 interacts with your own distribution before you ship a modified copy.

Where a fixed-tool design server wins instead

The contrast worth drawing is with a design integration that exposes a fixed set of named operations, one per action, with typed inputs and outputs. That approach is narrower by construction: the model can only do what the tool list allows, and each call is inspectable in a log. Penpot's server takes the opposite position. The README says the LLM writes and executes arbitrary code snippets in the plugin environment, so the boundary is the Plugin API rather than a curated verb list. The trade is real in both directions. A fixed-tool server is predictable and auditable but cannot express anything its authors did not anticipate. This one can express nearly anything the plugin can do, which is exactly why the failure modes are harder to enumerate and why a bad snippet is not rejected by a schema. If your requirement is that every change to a design file be reproducible from a recorded, typed call, this architecture is the wrong shape, and no amount of prompt discipline turns generated code into a fixed interface.

Editorial conclusion

Adopt it if you want an LLM to inspect and modify Penpot files through the Plugin API and you are willing to run two local servers and keep a browser tab open. Skip it if you need a headless service, a stdio-only client without a proxy, or a stable dependency pinned from a release tag, because this repository is archived with no releases and the code now lives in the main Penpot monorepo under mcp/. Before writing anything, verify three things: that the plugin UI reports Connected to MCP server, that your browser permits a connection from design.penpot.app to localhost, and that your client can reach http://localhost:4401/mcp or /sse.

Official sources

  1. Issues
  2. License: MPL-2.0
  3. penpot/penpot-mcp on GitHub
  4. README
Community notes

Community notes