Add mcp types generator build script

This commit is contained in:
Andrey Antukh
2026-02-04 11:07:05 +01:00
parent da55653844
commit 08e8787568
7 changed files with 151 additions and 38 deletions

View File

@@ -2,9 +2,14 @@
# Penpot's Official MCP Server
Penpot integrates a LLM layer built on the Model Context Protocol (MCP) via Penpot's Plugin API to interact with a Penpot design file. Penpot's MCP server enables LLMs to perfom data queries, transformation and creation operations.
Penpot integrates a LLM layer built on the Model Context Protocol
(MCP) via Penpot's Plugin API to interact with a Penpot design
file. Penpot's MCP server enables LLMs to perfom data queries,
transformation and creation operations.
Penpot's MCP Server is unlike any other you've seen. You get design-to- design, code-to-design and design-code supercharged workflows.
Penpot's MCP Server is unlike any other you've seen. You get
design-to- design, code-to-design and design-code supercharged
workflows.
[![Penpot MCP video playlist](https://github.com/user-attachments/assets/204f1d99-ce51-41dd-a5dd-1ef739f8f089)](https://www.youtube.com/playlist?list=PLgcCPfOv5v57SKMuw1NmS0-lkAXevpn10)
@@ -12,9 +17,10 @@ Penpot's MCP Server is unlike any other you've seen. You get design-to- design,
## Architecture
The **Penpot MCP Server** exposes tools to AI clients (LLMs), which support the retrieval
of design data as well as the modification and creation of design elements.
The MCP server communicates with Penpot via the dedicated **Penpot MCP Plugin**,
The **Penpot MCP Server** exposes tools to AI clients (LLMs), which
support the retrieval of design data as well as the modification and
creation of design elements. The MCP server communicates with Penpot
via the dedicated **Penpot MCP Plugin**,
which connects to the MCP server via WebSocket.
This enables the LLM to carry out tasks in the context of a design file by
executing code that leverages the Penpot Plugin API.
@@ -44,23 +50,36 @@ Follow the steps below to enable the integration.
### Prerequisites
The project requires [Node.js](https://nodejs.org/) (tested with v22).
Following the installation of Node.js, the tools `npm` and `npx` should be
available in your terminal.
The project requires [Node.js](https://nodejs.org/) (tested with v22.x
with corepack).
You should probably be using penpot devenv, where all this dependencies are
already present and correctly setup.
Following the installation of Node.js, the tools `pnpm` and `npx`
should be available in your terminal. For ensure corepack installed
and enabled correctly, just execute the `./scripts/setup`.
It is also required to have `caddy` executeable in the path, it is
used for start a local server for generate types documentation from
the current branch. If you want to run it outside devenv where all
dependencies are already provided, please download caddy from
[here](https://caddyserver.com/download).
You should probably be using penpot devenv, where all this
dependencies are already present and correctly setup. But nothing
prevents you execute this outside of devenv if you satisfy the
specified dependencies.
### 1. Build & Launch the MCP Server and the Plugin Server
If it's your first execution, install the required dependencies:
```shell
cd mcp/
./scripts/setup
```
Then build all components and start the two servers:
```shell
pnpm run bootstrap
```
@@ -69,8 +88,34 @@ This bootstrap command will:
* install dependencies for all components (`pnpm -r run install`)
* build all components (`pnpm -r run build`)
* build plugins types (`pnpm run build-types`)
* start all components (`pnpm -r --parallel run start`)
If you want to have types scrapped from a remote repository, the best
apprach is executing the following:
```shell
PENPOT_PLUGINS_API_DOC_URL=https://doc.plugins.penpot.app pnpm run build:types
pnpm run bootstrap
```
Or this, if you want skip build step bacause you have already have all
build artifacts ready (per example from previous `bootstrap` command):
```
PENPOT_PLUGINS_API_DOC_URL=https://doc.plugins.penpot.app pnpm run build:types
pnpm run start
```
If you want just to update the types definitions with the plugins api doc from the
current branch:
```shell
pnpm run build:types
```
(That command will build plugins doc locally and will generate the types yaml from
the locally build documentation)
### 2. Load the Plugin in Penpot and Establish the Connection
@@ -80,14 +125,14 @@ This bootstrap command will:
> Starting with Chromium version 142, the private network access (PNA) restrictions have been hardened,
> and when connecting to `localhost` from a web application served from a different origin
> (such as https://design.penpot.app), the connection must explicitly be allowed.
>
>
> Most Chromium-based browsers (e.g. Chrome, Vivaldi) will display a popup requesting permission
> to access the local network. Be sure to approve the request to allow the connection.
>
>
> Some browsers take additional security measures, and you may need to disable them.
> For example, in Brave, disable the "Shield" for the Penpot website to allow local network access.
>
> If your browser refuses to connect to the locally served plugin, check its configuration or
>
> If your browser refuses to connect to the locally served plugin, check its configuration or
> try a different browser (e.g. Firefox) that does not enforce these restrictions.
1. Open Penpot in your browser

View File

@@ -5,10 +5,11 @@
"scripts": {
"build": "pnpm -r run build",
"build:multi-user": "pnpm -r run build:multi-user",
"build:types": "./scripts/build-types",
"start": "pnpm -r --parallel run start",
"start:multi-user": "pnpm -r --parallel --filter \"./packages/*\" run start:multi-user",
"bootstrap": "pnpm -r install && pnpm run build && pnpm run start",
"bootstrap:multi-user": "npm run install && npm run build:multi-user && pnpm run start:multi-user",
"bootstrap:multi-user": "pnpm -r install && pnpm run build:multi-user && pnpm run start:multi-user",
"fmt": "prettier --write packages/",
"fmt:check": "prettier --check packages/"
},

View File

@@ -30,6 +30,7 @@ Penpot:
currentFile: null | File;
currentPage: null | Page;
viewport: Viewport;
flags: Flags;
history: HistoryContext;
library: LibraryContext;
fonts: FontsContext;
@@ -268,6 +269,12 @@ Penpot:
```
const viewportSettings = context.viewport;console.log(viewportSettings);
```
flags: |-
```
readonly flags: Flags
```
Provides flags to customize the API behavior.
history: |-
```
readonly history: HistoryContext
@@ -4477,6 +4484,7 @@ Context:
currentFile: null | File;
currentPage: null | Page;
viewport: Viewport;
flags: Flags;
history: HistoryContext;
library: LibraryContext;
fonts: FontsContext;
@@ -4572,6 +4580,12 @@ Context:
```
const viewportSettings = context.viewport;console.log(viewportSettings);
```
flags: |-
```
readonly flags: Flags
```
Provides flags to customize the API behavior.
history: |-
```
readonly history: HistoryContext
@@ -6763,6 +6777,31 @@ Fill:
```
The optional image fill defined by an ImageData object.
Flags:
overview: |-
Interface Flags
===============
This subcontext allows the API o change certain defaults
```
interface Flags {
naturalChildOrdering: boolean;
}
```
Referenced by: Context, Penpot
members:
Properties:
naturalChildOrdering: |-
```
naturalChildOrdering: boolean
```
If `true` the .children property will be always sorted in the z-index ordering.
Also, appendChild method will be append the children in the top-most position.
The insertchild method is changed acordingly to respect this ordering.
Defaults to false
FlexLayout:
overview: |-
Interface FlexLayout

View File

@@ -2,6 +2,11 @@
# NOTE: this script should be called from the parent directory to
# properly work
SCRIPT_DIR=$(dirname $0);
URL=${1:-http://localhost:9090}
echo "Preparing bundle for types from $URL"
set -ex
corepack enable;
@@ -13,24 +18,12 @@ rm -rf node_modules;
rm -rf packages/server/dist;
rm -rf packages/server/node_modules;
pushd ../plugins
pnpm install
pnpm run build:doc
pushd $SCRIPT_DIR;
set +e
./build-types $URL;
set -e
popd
rsync -avr ../plugins/dist/doc/ ./types-generator/doc/
pushd types-generator
set +e;
pixi install;
pnpx concurrently --kill-others-on-fail -k \
"caddy file-server --root doc --listen :9090" \
"pixi run python prepare_api_docs.py http://localhost:9090";
rm -rf doc;
popd
set -e;
pnpm -r --filter "!mcp-plugin" install;
pnpm -r --filter "mcp-server" run build:multi-user;
@@ -39,6 +32,8 @@ rsync -avr packages/server/dist/ ./dist/;
cp packages/server/package.json ./dist/;
cp packages/server/pnpm-lock.yaml ./dist/;
touch ./dist/pnpm-workspace.yaml;
cat <<EOF | tee ./dist/setup
#/usr/bin/env bash
set -e;

23
mcp/scripts/build-types Executable file
View File

@@ -0,0 +1,23 @@
#!/usr/bin/env bash
SCRIPT_DIR=$(dirname $0);
URL=${PENPOT_PLUGINS_API_DOC_URL:-http://localhost:9090}
pushd $SCRIPT_DIR;
if [[ "$URL" = "http://localhost:9090" ]]; then
pushd ../../plugins
pnpm install
pnpm run build:doc
popd
fi
if [[ "$URL" = "http://localhost:9090" ]]; then
pnpx concurrently --kill-others-on-fail -s last -k \
"caddy file-server --root ../../plugins/dist/doc/ --listen :9090" \
"../types-generator/build $URL";
else
../types-generator/build $URL;
fi
popd

View File

@@ -1,6 +1,6 @@
# Types Generator
This subproject contains helper scripts used in the development of the
This subproject contains helper scripts used in the development of the
Penpot MCP server for generate the types yaml.
## Setup
@@ -8,20 +8,19 @@ Penpot MCP server for generate the types yaml.
This project uses [pixi](https://pixi.sh) for environment management
(already included in devenv).
Install the environment via
Install the environment via (optional, already handled by `build` script)
pixi install
## Scripts
### Preparation of API Documentation for the MCP Server
### Buld API types
The script `prepare_api_docs.py` reads API documentation from the Web
and collects it in a single yaml file, which is then used by an MCP
and collects it in a single yaml file, which is then used by an MCP
tool to provide API documentation to an LLM on demand.
Running the script:
pixi run python prepare_api_docs.py
./build <optional-url>
This will generate `../mcp-server/data/api_types.yml`.
This will generate `../packages/server/data/api_types.yml`.

11
mcp/types-generator/build Executable file
View File

@@ -0,0 +1,11 @@
#!/usr/bin/env bash
export URL=${1:-http://localhost:9090}
SCRIPT_DIR=$(dirname $0);
pushd $SCRIPT_DIR;
echo "Scrapping $URL..."
set -e
pixi install;
pixi run python prepare_api_docs.py $URL;