From 56a09f29e902fbadba068049e64193f3cdfd9e0c Mon Sep 17 00:00:00 2001 From: Fredrik Jensen Date: Sat, 6 Dec 2025 10:59:37 +0100 Subject: [PATCH] prepare library for npm --- package-lock.json | 146 ++++++++++++++++++--------- package.json | 18 ++-- packages/demo-server/package.json | 2 +- packages/inspector/package.json | 2 +- packages/library/build.mjs | 76 ++++++++++++++ packages/library/package.json | 72 +++++++++++-- packages/library/server/index.ts | 4 +- packages/library/tsconfig.build.json | 20 ++++ packages/library/tsconfig.json | 9 +- 9 files changed, 272 insertions(+), 77 deletions(-) create mode 100644 packages/library/build.mjs create mode 100644 packages/library/tsconfig.build.json diff --git a/package-lock.json b/package-lock.json index 59f7560..a26d652 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "mcp-ui", + "name": "mcp-ui-kit", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "mcp-ui", + "name": "mcp-ui-kit", "version": "1.0.0", "workspaces": [ "packages/*" @@ -812,12 +812,12 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@mcp-ui/demo-server": { - "resolved": "packages/server", + "node_modules/@mcp-ui-kit/inspector": { + "resolved": "packages/inspector", "link": true }, - "node_modules/@mcp-ui/inspector": { - "resolved": "packages/inspector", + "node_modules/@mcp-ui/kit": { + "resolved": "packages/library", "link": true }, "node_modules/@mcp-ui/library": { @@ -1833,6 +1833,10 @@ } } }, + "node_modules/demo-server": { + "resolved": "packages/demo-server", + "link": true + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -2017,15 +2021,6 @@ "@esbuild/win32-x64": "0.27.0" } }, - "node_modules/esbuild-plugin-globals": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/esbuild-plugin-globals/-/esbuild-plugin-globals-0.2.0.tgz", - "integrity": "sha512-y+6utQVWrETQWs0J8EGLV5gEOP59mmjX+fKWoQHn4TYwFMaj0FxQYflc566tHuokBCzl+uNW2iIlM1o1jfNy6w==", - "license": "MIT", - "engines": { - "node": ">=7" - } - }, "node_modules/esbuild/node_modules/@esbuild/aix-ppc64": { "version": "0.27.0", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.0.tgz", @@ -4038,40 +4033,7 @@ "zod": "^3.25 || ^4" } }, - "packages/inspector": { - "name": "@mcp-ui/inspector", - "version": "1.0.0", - "dependencies": { - "lucide-react": "^0.460.0", - "react": "^19.0.0", - "react-dom": "^19.0.0" - }, - "devDependencies": { - "@types/react": "^19.0.0", - "@types/react-dom": "^19.0.0", - "@vitejs/plugin-react": "^4.3.4", - "typescript": "^5.6.3", - "vite": "^6.0.0" - } - }, - "packages/library": { - "name": "@mcp-ui/library", - "version": "1.0.0", - "dependencies": { - "@mcp-ui/server": "^5.15.0", - "esbuild": "^0.27.0", - "esbuild-plugin-globals": "^0.2.0", - "react": "^19.2.0", - "react-dom": "^19.2.0" - }, - "devDependencies": { - "@types/react": "^19.2.7", - "@types/react-dom": "^19.2.3", - "typescript": "^5.6.3" - } - }, - "packages/server": { - "name": "@mcp-ui/demo-server", + "packages/demo-server": { "version": "1.0.0", "dependencies": { "@mcp-ui/library": "*", @@ -4088,7 +4050,7 @@ "typescript": "^5.6.3" } }, - "packages/server/node_modules/zod": { + "packages/demo-server/node_modules/zod": { "version": "3.25.76", "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", @@ -4096,6 +4058,90 @@ "funding": { "url": "https://github.com/sponsors/colinhacks" } + }, + "packages/inspector": { + "name": "@mcp-ui-kit/inspector", + "version": "1.0.0", + "dependencies": { + "lucide-react": "^0.460.0", + "react": "^19.0.0", + "react-dom": "^19.0.0" + }, + "devDependencies": { + "@types/react": "^19.0.0", + "@types/react-dom": "^19.0.0", + "@vitejs/plugin-react": "^4.3.4", + "typescript": "^5.6.3", + "vite": "^6.0.0" + } + }, + "packages/library": { + "name": "@mcp-ui/kit", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "@mcp-ui/server": "^5.15.0", + "esbuild": "^0.27.0" + }, + "devDependencies": { + "@types/node": "^20.10.0", + "@types/react": "^19.2.7", + "@types/react-dom": "^19.2.3", + "react": "^19.2.0", + "react-dom": "^19.2.0", + "typescript": "^5.6.3" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "packages/library/node_modules/@types/node": { + "version": "20.19.25", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.25.tgz", + "integrity": "sha512-ZsJzA5thDQMSQO788d7IocwwQbI8B5OPzmqNvpf3NY/+MHDAS759Wo0gd2WQeXYt5AAAQjzcrTVC6SKCuYgoCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "packages/library/node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "packages/server": { + "name": "@mcp-ui/demo-server", + "version": "1.0.0", + "extraneous": true, + "dependencies": { + "@mcp-ui/library": "*", + "@modelcontextprotocol/sdk": "^1.23.0", + "cors": "^2.8.5", + "express": "^5.1.0", + "zod": "^3.24.0" + }, + "devDependencies": { + "@types/cors": "^2.8.19", + "@types/express": "^5.0.5", + "nodemon": "^3.1.0", + "ts-node": "^10.9.2", + "typescript": "^5.6.3" + } } } } diff --git a/package.json b/package.json index 1bbea9f..bf95784 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "mcp-ui", + "name": "mcp-ui-kit", "version": "1.0.0", "private": true, "type": "module", @@ -7,15 +7,15 @@ "packages/*" ], "scripts": { - "dev": "npm run dev --workspace=@mcp-ui/inspector", - "dev:server": "npm run dev --workspace=@mcp-ui/demo-server", - "dev:library": "npm run dev --workspace=@mcp-ui/library", + "dev": "npm run dev --workspace=@mcp-ui-kit/inspector", + "dev:server": "npm run dev --workspace=demo-server", + "dev:library": "npm run dev --workspace=@mcp-ui-kit", "dev:all": "npm run dev:server & npm run dev:library & npm run dev", - "build": "npm run build --workspace=@mcp-ui/inspector", - "start": "npm run start --workspace=@mcp-ui/demo-server", - "watch": "npm run watch --workspace=@mcp-ui/demo-server", - "watch:library": "npm run watch --workspace=@mcp-ui/library", - "watch:inspector": "npm run watch --workspace=@mcp-ui/inspector", + "build": "npm run build --workspace=@mcp-ui-kit/inspector", + "start": "npm run start --workspace=demo-server", + "watch": "npm run watch --workspace=demo-server", + "watch:library": "npm run watch --workspace=@mcp-ui-kit", + "watch:inspector": "npm run watch --workspace=@mcp-ui-kit/inspector", "inspector": "npx @modelcontextprotocol/inspector", "nanobot": "dotenv -e .env -- nanobot run ./nanobot.yaml" }, diff --git a/packages/demo-server/package.json b/packages/demo-server/package.json index ebefe52..21b8d04 100644 --- a/packages/demo-server/package.json +++ b/packages/demo-server/package.json @@ -1,5 +1,5 @@ { - "name": "@mcp-ui/demo-server", + "name": "demo-server", "private": true, "version": "1.0.0", "type": "module", diff --git a/packages/inspector/package.json b/packages/inspector/package.json index 0cb6e30..5aa7b7a 100644 --- a/packages/inspector/package.json +++ b/packages/inspector/package.json @@ -1,5 +1,5 @@ { - "name": "@mcp-ui/inspector", + "name": "@mcp-ui-kit/inspector", "private": true, "version": "1.0.0", "type": "module", diff --git a/packages/library/build.mjs b/packages/library/build.mjs new file mode 100644 index 0000000..83cdb42 --- /dev/null +++ b/packages/library/build.mjs @@ -0,0 +1,76 @@ +import * as esbuild from "esbuild"; +import { execSync } from "child_process"; +import { cpSync, rmSync, mkdirSync, writeFileSync, readFileSync } from "fs"; + +// Clean dist +rmSync("dist", { recursive: true, force: true }); +mkdirSync("dist/server", { recursive: true }); +mkdirSync("dist/ui", { recursive: true }); + +const shared = { + bundle: true, + sourcemap: true, + minify: false, +}; + +// Build all formats in parallel +await Promise.all([ + // Server ESM + esbuild.build({ + ...shared, + entryPoints: ["server/index.ts"], + outfile: "dist/server/index.js", + format: "esm", + platform: "node", + target: "node18", + external: ["@mcp-ui/server", "esbuild"], + }), + // Server CJS + esbuild.build({ + ...shared, + entryPoints: ["server/index.ts"], + outfile: "dist/server/index.cjs", + format: "cjs", + platform: "node", + target: "node18", + external: ["@mcp-ui/server", "esbuild"], + }), + // UI ESM + esbuild.build({ + ...shared, + entryPoints: ["ui/index.ts"], + outfile: "dist/ui/index.js", + format: "esm", + platform: "browser", + target: "es2020", + external: ["react", "react-dom"], + }), + // UI CJS + esbuild.build({ + ...shared, + entryPoints: ["ui/index.ts"], + outfile: "dist/ui/index.cjs", + format: "cjs", + platform: "browser", + target: "es2020", + external: ["react", "react-dom"], + }), +]); + +console.log("✅ JS builds complete"); + +// Generate TypeScript declarations +execSync("tsc -p tsconfig.build.json", { stdio: "inherit" }); + +// Copy .d.ts to .d.cts for CJS compatibility +cpSync("dist/server/index.d.ts", "dist/server/index.d.cts"); +cpSync("dist/ui/index.d.ts", "dist/ui/index.d.cts"); + +// Remove internal declaration files (bundle, html) +rmSync("dist/server/bundle.d.ts", { force: true }); +rmSync("dist/server/bundle.d.ts.map", { force: true }); +rmSync("dist/server/html.d.ts", { force: true }); +rmSync("dist/server/html.d.ts.map", { force: true }); + +console.log("✅ Type declarations complete"); +console.log("✅ Build complete"); diff --git a/packages/library/package.json b/packages/library/package.json index 498d5e1..b237e85 100644 --- a/packages/library/package.json +++ b/packages/library/package.json @@ -1,25 +1,75 @@ { - "name": "@mcp-ui/library", + "name": "mcp-ui-kit", "version": "1.0.0", + "description": "MCP UI Kit - Create rich UI components for MCP servers", "type": "module", - "scripts": { - "build": "tsc", - "dev": "tsc --watch", - "watch": "tsc --watch" - }, + "main": "./dist/server/index.cjs", + "module": "./dist/server/index.js", + "types": "./dist/server/index.d.ts", "exports": { - "./server": "./server/index.ts", - "./ui": "./ui/index.ts" + "./server": { + "import": { + "types": "./dist/server/index.d.ts", + "default": "./dist/server/index.js" + }, + "require": { + "types": "./dist/server/index.d.cts", + "default": "./dist/server/index.cjs" + } + }, + "./ui": { + "import": { + "types": "./dist/ui/index.d.ts", + "default": "./dist/ui/index.js" + }, + "require": { + "types": "./dist/ui/index.d.cts", + "default": "./dist/ui/index.cjs" + } + } }, + "files": [ + "dist" + ], + "scripts": { + "build": "node build.mjs", + "prepublishOnly": "npm run build", + "typecheck": "tsc --noEmit", + "publish": "npm publish" + }, + "keywords": [ + "mcp", + "ui", + "model-context-protocol", + "react", + "components" + ], + "license": "MIT", "dependencies": { "@mcp-ui/server": "^5.15.0", - "esbuild": "^0.27.0", - "react": "^19.2.0", - "react-dom": "^19.2.0" + "esbuild": "^0.27.0" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } }, "devDependencies": { + "@types/node": "^20.10.0", "@types/react": "^19.2.7", "@types/react-dom": "^19.2.3", + "react": "^19.2.0", + "react-dom": "^19.2.0", "typescript": "^5.6.3" + }, + "engines": { + "node": ">=18.0.0" } } diff --git a/packages/library/server/index.ts b/packages/library/server/index.ts index 7578b6b..3b4d8f8 100644 --- a/packages/library/server/index.ts +++ b/packages/library/server/index.ts @@ -1,7 +1,7 @@ import { createUIResource, RESOURCE_URI_META_KEY, type UIResource } from "@mcp-ui/server"; import { fileURLToPath } from 'url'; -import { bundleComponent } from './bundle.ts'; -import { generateHtml } from './html.ts'; +import { bundleComponent } from './bundle.js'; +import { generateHtml } from './html.js'; type UIComponentProps = { props?: Record; diff --git a/packages/library/tsconfig.build.json b/packages/library/tsconfig.build.json new file mode 100644 index 0000000..526b490 --- /dev/null +++ b/packages/library/tsconfig.build.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "ES2020", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "moduleResolution": "bundler", + "skipLibCheck": true, + "resolveJsonModule": true, + "isolatedModules": true, + "declaration": true, + "declarationMap": true, + "emitDeclarationOnly": true, + "outDir": "dist", + "jsx": "react-jsx", + "strict": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true + }, + "include": ["server/index.ts", "ui/index.ts"] +} diff --git a/packages/library/tsconfig.json b/packages/library/tsconfig.json index 001e602..44445b9 100644 --- a/packages/library/tsconfig.json +++ b/packages/library/tsconfig.json @@ -3,17 +3,20 @@ "target": "ES2020", "lib": ["ES2020", "DOM", "DOM.Iterable"], "module": "ESNext", - "skipLibCheck": true, "moduleResolution": "bundler", - "allowImportingTsExtensions": true, + "skipLibCheck": true, "resolveJsonModule": true, "isolatedModules": true, + "declaration": true, + "declarationMap": true, "noEmit": true, "jsx": "react-jsx", "strict": true, "noUnusedLocals": true, "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true + "noFallthroughCasesInSwitch": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true }, "include": ["server", "ui"] }