Skip to main content

penpot-api-mcp

MCP server wrapping the Penpot REST API for headless design automation. Provides read, search, and export access to Penpot projects, files, and design objects — without requiring a browser session.

Part of the Bodai Ecosystem alongside Mahavishnu, Akosha, Dhara, Session-Buddy, and Crackerjack.

Why this exists

The official @penpot/mcp (TypeScript) requires a live browser plugin to operate — it is the right tool for interactive canvas manipulation. This server targets the complementary use case: background automation, asset export pipelines, and AI-driven design queries that run without a browser.

Tools

Tool Description
list_projects List all projects for the authenticated user
get_project_files List design files in a project
get_file Fetch the full content of a design file
get_object_tree Return the design object hierarchy for a file
search_objects Search objects by name or type
export_object Export a design object as PNG/SVG (base64-encoded)

Setup

uv sync
touch .env             # then fill in credentials (see Configuration below)

Configuration

Environment variables (prefix PENPOT_):

Variable Description Default
PENPOT_ACCESS_TOKEN API access token (preferred)
PENPOT_EMAIL Email for password auth (fallback)
PENPOT_PASSWORD Password for password auth (fallback)
PENPOT_BASE_URL API base URL for self-hosted instances https://design.penpot.app/api

Either PENPOT_ACCESS_TOKEN or PENPOT_EMAIL + PENPOT_PASSWORD must be set.

Transport settings (prefix PENPOT_MCP_)

The CLI transport layer uses a separate env prefix from the Penpot API client. Override defaults via:

Variable Description Default
PENPOT_MCP_HTTP_HOST Bind host for the MCP HTTP server 127.0.0.1
PENPOT_MCP_HTTP_PORT Bind port for the MCP HTTP server 3051
PENPOT_MCP_ENABLE_HTTP_TRANSPORT Toggle HTTP transport on/off true

Note: PENPOT_HTTP_PORT (without the MCP_ segment) is not honored by the CLI; the active prefix is PENPOT_MCP_.

Running

# HTTP mode (default — Claude Code compatible)
uv run python -m penpot_api_mcp start --force

Server listens on http://localhost:3051/mcp. The server is HTTP-only; bare uv run python -m penpot_api_mcp without a subcommand falls through to Typer help and does not start a JSON-RPC loop. To bridge to stdio, run the HTTP server behind an external stdio-to-HTTP shim.

MCP configuration

{
  "mcpServers": {
    "penpot-api": {
      "type": "http",
      "url": "http://localhost:3051/mcp"
    }
  }
}

Installation via Bodai Marketplace

This repo ships a Bodai Claude Code plugin manifest (.claude-plugin/plugin.json) plus a colocated .mcp.json and three slash commands in commands/. To install via the Bodai marketplace, first register the marketplace with Claude Code, then install the plugin by name. Once installed, the slash commands /penpot-list, /penpot-search, and /penpot-export become available alongside the mcp__penpot-api__* tools, and the MCP client talks to the server over http://localhost:3051/mcp as configured in .mcp.json. Penpot credentials still need to be present in the environment (PENPOT_ACCESS_TOKEN or PENPOT_EMAIL + PENPOT_PASSWORD); the plugin manifest only wires the transport, it does not provision Penpot auth.

Development

uv run pytest                          # Run tests
uv run crackerjack                     # Full quality suite (ruff + mypy + pytest + bandit)
uv run ruff check --fix                # Lint
uv run mypy .                          # Type check

Architecture

penpot_api_mcp/
├── utils/transit.py      # Transit+JSON encode/decode (Penpot's wire format)
├── config/settings.py    # Pydantic settings (PENPOT_* env vars)
├── clients/              # httpx async client with dual auth
├── models/               # Pydantic models: Project, File, Object, ObjectTree
├── tools/                # FastMCP tool registrations
├── server.py             # FastMCP app + health endpoints
└── __main__.py           # MCPServerCLIFactory entrypoint (Oneiric)

Transit+JSON

Penpot's RPC layer uses Transit+JSON — a Clojure serialization format where map keys are ~:keyword and UUIDs are ~uUUID. The utils/transit.py module handles encode/decode at the API boundary, keeping all Python models clean.

Authentication

Two modes are supported:

  • API token (PENPOT_ACCESS_TOKEN): sent as Authorization: Token <token> header
  • Email + password: authenticates via /rpc/command/login-with-password, then relies on the httpx cookie jar (auth-token cookie) for all subsequent requests

License

BSD 3-Clause. See LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

penpot_api_mcp-0.3.0.tar.gz (46.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

penpot_api_mcp-0.3.0-py3-none-any.whl (24.4 kB view details)

Uploaded Python 3

File details

Details for the file penpot_api_mcp-0.3.0.tar.gz.

File metadata

  • Download URL: penpot_api_mcp-0.3.0.tar.gz
  • Upload date:
  • Size: 46.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for penpot_api_mcp-0.3.0.tar.gz
Algorithm Hash digest
SHA256 569d4d8b4260c0f3e5ebcd10d957c252a6b3a1655aff31b0cdd23b18ffd58e4a
MD5 6b6389a56ecbad599c0a3e652e327108
BLAKE2b-256 fc1d24bbbd9650971173c2e6af44bec02b1076e847803020eba1e985d5fbeffc

See more details on using hashes here.

File details

Details for the file penpot_api_mcp-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: penpot_api_mcp-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 24.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for penpot_api_mcp-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 411dc1c36ac90002c717ec72462578064a70a08f0c7f6ea172fc35b75875cb05
MD5 b41b830b10b255a610284f144a8ba725
BLAKE2b-256 6526272ae0fe29cec3daa94fd0d5a02304a23ab5d52f5290eba9ddcbe90a35f7

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 files

0.2.1

2 files

0.2.0

2 files

0.1.3

2 files

0.1.1

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page