/**
* Build script for MCP Apps
* Builds each app individually to work with vite-plugin-singlefile
*/
import { build } from "vite";
import { viteSingleFile } from "vite-plugin-singlefile";
import path from "path";
import fs from "fs/promises";
const apps = [
{ name: "tasks", input: "src/apps/tasks.html" },
{ name: "data-viz", input: "src/apps/data-viz.html" },
{ name: "form", input: "src/apps/form-builder.html" },
{ name: "monitor", input: "src/apps/system-monitor.html" },
{ name: "playground", input: "src/apps/code-playground.html" },
];
const rootDir = path.resolve(import.meta.dirname, "..");
async function buildApp(app: { name: string; input: string }) {
console.log(`Building ${app.name}...`);
await build({
root: rootDir,
plugins: [viteSingleFile()],
build: {
outDir: "dist",
emptyDirFirst: false,
target: "esnext", // Support top-level await
rollupOptions: {
input: path.resolve(rootDir, app.input),
},
},
resolve: {
alias: {
"@anthropic-ai/mcp-app-client": "@modelcontextprotocol/ext-apps",
},
},
logLevel: "warn",
});
// Rename the output file to match the expected name
const inputName = path.basename(app.input, ".html");
const srcPath = path.join(rootDir, "dist", `${inputName}.html`);
const destPath = path.join(rootDir, "dist", `${app.name}.html`);
if (srcPath !== destPath) {
try {
await fs.rename(srcPath, destPath);
} catch {
// File might already have correct name
}
}
console.log(` ✓ ${app.name}.html`);
}
async function main() {
// Clean dist directory
const distDir = path.join(rootDir, "dist");
try {
await fs.rm(distDir, { recursive: true });
} catch {
// Directory might not exist
}
await fs.mkdir(distDir, { recursive: true });
console.log("Building MCP Apps...\n");
for (const app of apps) {
await buildApp(app);
}
console.log("\n✓ All apps built successfully!");
}
main().catch((err) => {
console.error("Build failed:", err);
process.exit(1);
});