Files
webstudio/packages/cli/local.js
Oleg Isonen d291e4b671 feat: Builder api runtime contracts guardrails for MCP (#5857)
This PR expands Webstudio MCP and CLI into a more complete agent
authoring interface. Agents can discover project capabilities, edit real
Webstudio content, use data/resources, verify visual output, and report
useful issues when workflows fail.

## MCP User Capabilities

- Create, update, duplicate, reorder, and delete pages.
- Create pages from templates and manage reusable page templates.
- Inspect project pages, instances, props, styles, assets, variables,
resources, and metadata.
- Insert Webstudio components and authored JSX fragments into pages.
- Edit text, props, styles, breakpoints, design tokens, and CSS
variables.
- Update page metadata, SEO fields, redirects, marketplace metadata, and
project settings.
- Create and use static data variables.
- Create and use dynamic resources fetched over HTTP.
- Use REST, GraphQL, and built-in system resources in authored pages.
- Bind data variables and resources to visible page content.
- Create resource-backed pages such as sitemap XML, structured SEO data,
and API-driven content sections.
- Preview current project state without requiring a publish step.
- Capture screenshots for visual verification.
- Verify responsive designs across desktop, tablet, and mobile
breakpoints.
- Use screenshot diff and OCR-style checks to inspect rendered output.
- Reset and refresh local MCP project state when needed.
- Discover available CLI/MCP commands from generated manuals.
- Use clearer examples for resources, data variables, JSX authoring,
previewing, and visual checks.
- Read marketplace product metadata without requiring a full project
snapshot.
- Get safer guidance when using low-level patch tools.
- Get a ready-to-copy Discord report template when MCP/CLI behavior is
confusing or broken.
2026-07-10 02:13:22 +02:00

64 lines
2.0 KiB
JavaScript
Executable File

#!/usr/bin/env node
import { spawnSync } from "node:child_process";
import { createRequire } from "node:module";
import { dirname, join, resolve } from "node:path";
import { fileURLToPath, pathToFileURL } from "node:url";
import { chdir, cwd } from "node:process";
const entrypointPath = fileURLToPath(import.meta.url);
const require = createRequire(import.meta.url);
const packageRoot = dirname(entrypointPath);
const bootstrappedEntrypoint = join(packageRoot, "local-main.js");
const localTsconfigPath = join(packageRoot, "tsconfig.local.json");
const shellCwd = process.env.PWD;
if (
shellCwd !== undefined &&
resolve(cwd()) === resolve(packageRoot) &&
resolve(shellCwd) !== resolve(packageRoot)
) {
chdir(shellCwd);
}
if (process.env.WEBSTUDIO_LOCAL_CLI_BOOTSTRAPPED !== "1") {
const conditionsArg = "--conditions=webstudio";
const hasWebstudioCondition = process.execArgv.some(
(arg, index, args) =>
arg === conditionsArg ||
(arg === "--conditions" && args[index + 1] === "webstudio")
);
const hasTsxImport = process.execArgv.some(
(arg, index, args) =>
arg === "--import=tsx" ||
(arg.startsWith("--import=") && arg.includes("tsx")) ||
(arg === "--import" && args[index + 1]?.includes("tsx"))
);
const execArgv = [
...process.execArgv,
...(hasWebstudioCondition ? [] : [conditionsArg]),
...(hasTsxImport
? []
: [`--import=${pathToFileURL(require.resolve("tsx")).href}`]),
];
const result = spawnSync(
process.execPath,
[...execArgv, bootstrappedEntrypoint, ...process.argv.slice(2)],
{
stdio: "inherit",
env: {
...process.env,
TSX_TSCONFIG_PATH: process.env.TSX_TSCONFIG_PATH ?? localTsconfigPath,
WEBSTUDIO_LOCAL_CLI_BOOTSTRAPPED: "1",
},
}
);
if (result.signal !== null) {
process.kill(process.pid, result.signal);
}
process.exit(result.status ?? 1);
}
throw Error("packages/cli/local.js must bootstrap through local-main.js");