diff --git a/mcp/.gitignore b/mcp/.gitignore index 8a245a5dca..bf71a5b82a 100644 --- a/mcp/.gitignore +++ b/mcp/.gitignore @@ -1,6 +1,7 @@ .idea node_modules dist +*.tgz *.bak *.orig temp diff --git a/mcp/README.md b/mcp/README.md index 0d482aeb00..e3feeb80ff 100644 --- a/mcp/README.md +++ b/mcp/README.md @@ -282,3 +282,5 @@ you may set the following environment variables to configure the two servers * The [contribution guidelines for Penpot](../CONTRIBUTING.md) apply * Auto-formatting: Use `pnpm run fmt` * Generating API type data: See [types-generator/README.md](types-generator/README.md) +* Packaging and publishing: + - Create npm package: `bash scripts/pack` (sets version and then calls `npm pack`) \ No newline at end of file diff --git a/mcp/bin/mcp-local.js b/mcp/bin/mcp-local.js new file mode 100644 index 0000000000..517762b4f9 --- /dev/null +++ b/mcp/bin/mcp-local.js @@ -0,0 +1,22 @@ +#!/usr/bin/env node + +const { execSync } = require("child_process"); +const path = require("path"); + +const root = path.resolve(__dirname, ".."); + +function run(command) { + execSync(command, { cwd: root, stdio: "inherit" }); +} + +try { + run("corepack pnpm run bootstrap"); +} catch (error) { + if (error.code === "ENOENT") { + console.error( + "corepack is required but was not found. It ships with Node.js >= 16." + ); + process.exit(1); + } + process.exit(error.status ?? 1); +} diff --git a/mcp/package.json b/mcp/package.json index fdb75dd03b..1b76f0b902 100644 --- a/mcp/package.json +++ b/mcp/package.json @@ -1,7 +1,10 @@ { - "name": "mcp-meta", + "name": "@penpot/mcp", "version": "1.0.0", - "description": "", + "description": "MCP server for Penpot integration", + "bin": { + "penpot-mcp": "./bin/mcp-local.js" + }, "scripts": { "build": "pnpm -r run build", "build:multi-user": "pnpm -r run build:multi-user", @@ -18,7 +21,6 @@ "url": "https://github.com/penpot/penpot.git" }, "packageManager": "pnpm@10.28.2+sha512.41872f037ad22f7348e3b1debbaf7e867cfd448f2726d9cf74c08f19507c31d2c8e7a11525b983febc2df640b5438dee6023ebb1f84ed43cc2d654d2bc326264", - "private": true, "devDependencies": { "concurrently": "^9.2.1", "prettier": "^3.0.0" diff --git a/mcp/packages/server/package.json b/mcp/packages/server/package.json index 09e47a4dce..ba2d5ea9d6 100644 --- a/mcp/packages/server/package.json +++ b/mcp/packages/server/package.json @@ -6,7 +6,7 @@ "main": "dist/index.js", "scripts": { "build:server": "esbuild src/index.ts --bundle --platform=node --target=node18 --format=esm --outfile=dist/index.js --external:@modelcontextprotocol/* --external:ws --external:express --external:class-transformer --external:class-validator --external:reflect-metadata --external:pino --external:pino-pretty --external:js-yaml --external:sharp", - "build": "pnpm run build:server && cp -r src/static dist/static && cp -r data dist/data", + "build": "pnpm run build:server && node scripts/copy-resources.js", "build:multi-user": "pnpm run build", "build:types": "tsc --emitDeclarationOnly --outDir dist", "start": "node dist/index.js", diff --git a/mcp/packages/server/scripts/copy-resources.js b/mcp/packages/server/scripts/copy-resources.js new file mode 100644 index 0000000000..08b3604f37 --- /dev/null +++ b/mcp/packages/server/scripts/copy-resources.js @@ -0,0 +1,5 @@ +import { cpSync } from "fs"; + +// copy static assets and data to dist +cpSync("src/static", "dist/static", { recursive: true }); +cpSync("data", "dist/data", { recursive: true }); diff --git a/mcp/scripts/pack b/mcp/scripts/pack new file mode 100644 index 0000000000..06826b2143 --- /dev/null +++ b/mcp/scripts/pack @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +# +# Sets the version from Git tags, then produces the npm tarball. +# Must be invoked directly (not via npm/pnpm) so that the version +# is written to package.json before npm reads it. + +set -euo pipefail + +cd "$(dirname "$0")/.." + +bash ./scripts/set-version +npm pack diff --git a/mcp/scripts/set-version b/mcp/scripts/set-version new file mode 100644 index 0000000000..170aa6267d --- /dev/null +++ b/mcp/scripts/set-version @@ -0,0 +1,51 @@ +#!/usr/bin/env bash +# +# Derives a valid npm semver version from the Git tag produced by +# `git describe` and writes it into the root package.json. +# +# Examples of the conversion: +# 2.14.0 -> 2.14.0 +# 2.14.0-RC1 -> 2.14.0-rc.1 +# 2.14.0-RC1-140-g9f2ca9965 -> 2.14.0-rc.1.140 +# 2.14.0-140-g9f2ca9965 -> 2.14.1-dev.140 +# +# The last case (commits after a release tag) bumps the patch level so +# the resulting semver sorts higher than the release. + +set -euo pipefail + +raw=$(git describe --tags --match "*.*.*") + +# Parse: ..[-