# Penpot MCP Container

**URL:** <https://community.penpot.app/t/penpot-mcp-container/10095>\
**Category:** Self-host\
**Tags:** mcp\
**Created:** [November 19, 2025, 8:53am UTC](https://community.penpot.app/t/penpot-mcp-container/10095 "2025-11-19T08:53:17Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![mrkhachaturov](https://dub1.discourse-cdn.com/flex017/user_avatar/community.penpot.app/mrkhachaturov/32/9352_2.png) [@mrkhachaturov](https://community.penpot.app/u/mrkhachaturov)\
**Post date:** [November 19, 2025, 8:53am UTC](https://community.penpot.app/t/penpot-mcp-container/10095/1 "2025-11-19T08:53:17Z")

</div>

# Penpot MCP Container

A containerized deployment of the [Penpot MCP Server](https://github.com/penpot/penpot-mcp) that enables LLMs to interact directly with Penpot design projects using the Model Context Protocol (MCP).

## 📦 Container Image

**Container Registry:** `ghcr.io/astrateam-net/penpot-mcp:0.0.1`

```bash
docker pull ghcr.io/astrateam-net/penpot-mcp:0.0.1

```

**Source Code:** [View the build configuration and Dockerfile](https://github.com/astrateam-net/containers/tree/main/apps/penpot-mcp)

## 🚀 Why Use This Container?

### Solves the HTTP/Private Network Access Problem

The upstream Penpot MCP project has a known limitation with modern Chromium browsers (v142+):

> **Browser Compatibility Issue** : Starting with Chromium version 142, Google has hardened the private network access (PNA) enforcement layer. This means that newer Chromium-based browsers (Chrome, Edge, Vivaldi, Opera, Brave, etc.) will not allow Penpot to connect to a local plugin server by default.

**The workaround suggested in the upstream README:**

- Use Firefox, or
- Use an older version of a Chromium-based browser (up to Chromium version 141)

**Our solution:** Deploy this container behind a reverse proxy (Traefik, nginx, Caddy, etc.) with HTTPS, and the browser will allow the connection! 🎉

When accessed via HTTPS through a reverse proxy, the browser treats it as a secure connection, bypassing the private network access restrictions entirely.

### Additional Benefits

✅ **No local Node.js installation required** - Everything runs in the container  
✅ **Consistent environment** - Same setup across all machines  
✅ **Easy deployment** - Works with Docker Compose, Kubernetes, or any container orchestrator  
✅ **Production-ready** - Multi-platform builds (amd64 + arm64)  
✅ **Automatic updates** - Rebuild when upstream updates  
✅ **Isolated** - No conflicts with other Node.js projects on your system

## 📋 Quick Start

### Using Docker Compose with Traefik

```yaml
services:
  penpot-mcp:
    image: ghcr.io/astrateam-net/penpot-mcp:0.0.1
    container_name: penpot-mcp
    labels:
      - "traefik.enable=true"
      
      # Main router for plugin server (port 4400)
      - "traefik.http.routers.penpot-mcp.rule=Host(`penpot-api.yourdomain.com`)"
      - "traefik.http.routers.penpot-mcp.entrypoints=websecure"
      - "traefik.http.routers.penpot-mcp.tls.certresolver=letsencrypt"
      - "traefik.http.services.penpot-mcp-plugin.loadbalancer.server.port=4400"
      - "traefik.http.routers.penpot-mcp.service=penpot-mcp-plugin"
      
      # MCP router for /mcp and /sse (port 4401)
      - "traefik.http.routers.penpot-mcp-mcp.rule=Host(`penpot-api.yourdomain.com`) && (PathPrefix(`/mcp`) || PathPrefix(`/sse`))"
      - "traefik.http.routers.penpot-mcp-mcp.entrypoints=websecure"
      - "traefik.http.routers.penpot-mcp-mcp.tls.certresolver=letsencrypt"
      - "traefik.http.services.penpot-mcp-mcp.loadbalancer.server.port=4401"
      - "traefik.http.routers.penpot-mcp-mcp.service=penpot-mcp-mcp"
      - "traefik.http.routers.penpot-mcp-mcp.priority=10"
    networks:
      - traefik
    environment:
      - MCP_PORT=4401
      - PLUGIN_PORT=4400

```

### Using Docker Run

```bash
docker run -d \
  --name penpot-mcp \
  -p 4400:4400 \
  -p 4401:4401 \
  -e MCP_PORT=4401 \
  -e PLUGIN_PORT=4400 \
  ghcr.io/astrateam-net/penpot-mcp:0.0.1

```

## 🔧 Configuration

### Environment Variables

- `MCP_PORT` - Port for MCP server (default: `4401`)
  - Controls the `/mcp` and `/sse` endpoints

- `PLUGIN_PORT` - Port for plugin server (default: `4400`)
  - Controls where the plugin manifest is served

### Endpoints

Once deployed behind Traefik with HTTPS:

- **MCP Server (Modern HTTP)**: `https://penpot-api.yourdomain.com/mcp`
- **MCP Server (Legacy SSE)**: `https://penpot-api.yourdomain.com/sse`
- **Plugin Manifest** : `https://penpot-api.yourdomain.com/manifest.json`

## 📖 Usage

### 1. Deploy the Container

Deploy the container behind your reverse proxy (Traefik, nginx, etc.) with HTTPS enabled.

### 2. Load the Plugin in Penpot

1. Open Penpot in your browser
2. Navigate to a design file
3. Open the Plugins menu
4. Load the plugin using your HTTPS URL: `https://penpot-api.yourdomain.com/manifest.json`
5. Open the plugin UI
6. Click “Connect to MCP server”

The connection will work because it’s over HTTPS! ✅

### 3. Connect an MCP Client

#### For HTTP-capable clients (Claude Code, etc.):

```bash
claude mcp add penpot -t http https://penpot-api.yourdomain.com/mcp

```

#### For stdio-only clients (Claude Desktop):

Use `mcp-remote` with your HTTPS endpoint:

```json
{
    "mcpServers": {
        "penpot": {
            "command": "npx",
            "args": ["-y", "mcp-remote", "https://penpot-api.yourdomain.com/sse"]
        }
    }
}

```

Note: With HTTPS, you don’t need the `--allow-http` flag!

## 🏗 Architecture

The container runs two services:

1. **MCP Server** (port 4401) - Provides MCP tools to LLMs

2. **Plugin Server** (port 4400) - Serves the Penpot plugin

Both services run in the same container and can be routed via Traefik based on path prefixes.

## 🔄 Updating

The container builds from the upstream repository. To update:

1. Update the `GIT_REF` in `docker-bake.hcl` to point to a specific commit or branch
2. Rebuild the container
3. Deploy the new version

## 🐛 Troubleshooting

### Connection Issues

- **Ensure HTTPS is enabled** - The browser restriction only applies to HTTP
- **Check Traefik routing** - Verify both ports (4400, 4401) are properly routed
- **Check container logs** - `docker logs penpot-mcp` to see both services

### Plugin Not Loading

- Verify the plugin server is accessible: `curl https://penpot-api.yourdomain.com/manifest.json`
- Check browser console for CORS or network errors
- Ensure the plugin URL uses HTTPS, not HTTP

## 📝 Comparison: Container vs Local Installation

| Feature | Container | Local npm install |
| --- | --- | --- |
| **Browser Compatibility** | ✅ Works with all browsers via HTTPS | ❌ Requires Firefox or old Chromium |
| **Setup Complexity** | ✅ One command | ❌ Requires Node.js, npm, build steps |
| **Isolation** | ✅ Isolated environment | ❌ Can conflict with other projects |
| **Portability** | ✅ Same everywhere | ❌ Different per machine |
| **Production Ready** | ✅ Yes | ⚠ Requires process management |
| **Updates** | ✅ Rebuild container | ❌ Manual npm update + rebuild |

## 🔗 Links

- **Container Image** : `ghcr.io/astrateam-net/penpot-mcp:0.0.1`
- **Source Code** : [GitHub Repository](https://github.com/astrateam-net/containers/tree/main/apps/penpot-mcp)
- **Upstream Project** : [penpot/penpot-mcp](https://github.com/penpot/penpot-mcp)

## 🤝 Contributing

This container is built from the upstream [penpot/penpot-mcp](https://github.com/penpot/penpot-mcp) repository.

To contribute to the Penpot MCP project itself, please see the [upstream repository](https://github.com/penpot/penpot-mcp).

To contribute to this container build, see the [source repository](https://github.com/astrateam-net/containers).

## 📄 License

This container follows the same license as the upstream project (MPL-2.0).

## 🙏 Credits

- [Penpot MCP](https://github.com/penpot/penpot-mcp) - The upstream project
- [Penpot](https://penpot.app/) - The design tool

* * *

**Enjoy seamless Penpot MCP integration with any browser!** 🎨✨

---

<div class="post-metadata">

**Author:** ![opcode](https://avatars.discourse-cdn.com/v4/letter/o/bc79bd/32.png) [@opcode](https://community.penpot.app/u/opcode)\
**Post date:** [November 19, 2025, 10:44am UTC](https://community.penpot.app/t/penpot-mcp-container/10095/2 "2025-11-19T10:44:43Z")

</div>

Thanks for this contribution!

Note, however, that while it initially appeared that private network access was being restricted more heavily, it turned out that browsers are now implementing a popup-based access control mechanism, such that there actually isn’t a connectivity problem with (most) Chromium-based browsers. We have updated the [Penpot MCP README](https://github.com/penpot/penpot-mcp?tab=readme-ov-file#2-load-the-plugin-in-penpot-and-establish-the-connection) accordingly.

---

<div class="post-metadata">

**Author:** ![SkpChz](https://dub1.discourse-cdn.com/flex017/user_avatar/community.penpot.app/skpchz/32/9974_2.png) [@SkpChz](https://community.penpot.app/u/SkpChz)\
**Post date:** [February 24, 2026, 12:07am UTC](https://community.penpot.app/t/penpot-mcp-container/10095/3 "2026-02-24T00:07:25Z")

</div>

Note the original repo has now been archived as per 2026-02-03. The MCP server code is now under a folder under the main repo.

> **[penpot/mcp at develop · penpot/penpot](https://github.com/penpot/penpot/tree/develop/mcp)**
>
> Penpot: The open-source design tool for design and code collaboration - penpot/penpot
