@rainbow-robotics/muscat-plugin-kit 1.10.2-dev.2 → 1.10.2-dev.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -29,6 +29,33 @@ const UI_RULES = [
29
29
  "Colors and type come from tokens (bg-bg-*, text-fg-*, typo-*), not hex values or arbitrary Tailwind colors.",
30
30
  ];
31
31
 
32
+ // plugin-ui 1.x replaced the remote-dom components and the connect() bootstrap. The project check
33
+ // (update, MCP check_project) flags these; the migration rules below tell an agent how to fix them.
34
+ export const LEGACY_SUBPATHS = {
35
+ connect: "removed — drop `connect(App)` and `export default App` instead (the host renders the entry's default export)",
36
+ elements: "removed — use the RB* components from @rainbow-robotics/plugin-ui/react",
37
+ "dist-browser": "removed — import from @rainbow-robotics/plugin-ui/react",
38
+ };
39
+ export const LEGACY_COMPONENTS = {
40
+ Slider: "RBSlider",
41
+ Button: "RBLabelButton",
42
+ IconButton: "RBIconButton",
43
+ Text: "a plain element or RBTextLabel",
44
+ TextInput: "RBTextInput / RBTextField",
45
+ Switch: "RBSwitch",
46
+ Select: "RBSelectBox",
47
+ };
48
+ const MIGRATION_RULES = [
49
+ "After `muscat-pk update`, or when the UI fails to build or the preview says \"no default export\", call check_project and fix every item it lists. Call it again until it reports no issues.",
50
+ "Each top-level ui/*.tsx is an entry and ends in `export default App`. The old `connect(App)` bootstrap and @rainbow-robotics/plugin-ui/connect are gone.",
51
+ "vite.config.ts uses the muscat() preset (`plugins: [muscat()]` from @rainbow-robotics/muscat-plugin-kit/vite); keep any other plugins the project adds. A hand-written config drops the entry's default export from the build.",
52
+ "rb.toast takes one object: rb.toast({ message, type }).",
53
+ `Old components → new: ${Object.entries(LEGACY_COMPONENTS).map(([o, n]) => `${o} → ${n}`).join(", ")}. Their props differ (no event.detail) — call get_component_example for the new component before rewriting.`,
54
+ ];
55
+
56
+ // Claude Code reads this to start the MCP server; `muscat-pk` hands off to the project's local kit.
57
+ export const MCP_JSON = `${JSON.stringify({ mcpServers: { muscat: { command: "muscat-pk", args: ["mcp"] } } }, null, 2)}\n`;
58
+
32
59
  const nativeTable = () => NATIVE_TO_RB.map(([el, rb]) => `- ${el}: ${rb}`).join("\n");
33
60
 
34
61
  export const SERVER_INSTRUCTIONS = `Muscat plugin UI (ui/*.tsx) is built only from @rainbow-robotics/plugin-ui/react, styled with the design-token Tailwind classes (list_design_tokens).
@@ -39,6 +66,9 @@ ${UI_RULES.map((r) => `- ${r}`).join("\n")}
39
66
  Native element -> plugin-ui component:
40
67
  ${nativeTable()}
41
68
 
69
+ Upgrading a project made with an older kit:
70
+ ${MIGRATION_RULES.map((r) => `- ${r}`).join("\n")}
71
+
42
72
  Backend, manifest and SDK questions: search_rb_sdk, list_rb_sdk, get_rb_sdk_api.`;
43
73
 
44
74
  // AGENTS.md (Codex, Cursor, Gemini CLI, Copilot …). CLAUDE.md imports it with `@AGENTS.md`.
@@ -64,6 +94,13 @@ ${UI_RULES.map((r) => `- ${r}`).join("\n")}
64
94
  Native element → plugin-ui component:
65
95
 
66
96
  ${nativeTable()}
97
+
98
+ ## Upgrading from an older kit
99
+
100
+ \`muscat-pk update\` bumps the kit, plugin-ui and preview-host and lists what the project must change.
101
+ The MCP tool \`check_project\` runs the same check (known old APIs + \`tsc --noEmit\`).
102
+
103
+ ${MIGRATION_RULES.map((r) => `- ${r}`).join("\n")}
67
104
  `;
68
105
  }
69
106
 
package/cli/src/mcp.mjs CHANGED
@@ -43,6 +43,7 @@ import { PYTHON_DEV_IMAGE } from "./python.mjs";
43
43
  import { SHIPPED_STORIES_SRC, SHIPPED_DESIGN_TOKENS } from "./storybook.mjs";
44
44
  import { CPP_DEV_IMAGE } from "./cpp.mjs";
45
45
  import { NATIVE_TO_RB, SERVER_INSTRUCTIONS } from "./ai-rules.mjs";
46
+ import { checkProject, formatProjectCheck } from "./projectCheck.mjs";
46
47
 
47
48
  const TEMPLATE_READMES = { python: "common/README.md", cpp: "readme-cpp/README.md" };
48
49
  // Design tokens: prefer the shipped copy, fall back to the monorepo source.
@@ -1090,6 +1091,35 @@ print(json.dumps(res))
1090
1091
  },
1091
1092
  );
1092
1093
 
1094
+ server.registerTool(
1095
+ "check_project",
1096
+ {
1097
+ title: "Check the plugin project for changes the installed plugin-ui needs",
1098
+ description:
1099
+ "List what the plugin project must change to work with the plugin-ui it has installed: old APIs " +
1100
+ "(connect(App), Slider/Text/Switch…, rb.toast(message, type), a vite.config without the muscat() " +
1101
+ "preset, entries without a default export) and `tsc --noEmit` errors, each as file:line. Same check " +
1102
+ "as `muscat-pk update`. Call it after an update or when the UI fails to build, fix each item " +
1103
+ "(get_component_example for replacement components), and call it again until it reports no issues.",
1104
+ inputSchema: {
1105
+ path: z.string().optional().describe("Plugin project directory (default: the server's working directory)"),
1106
+ },
1107
+ },
1108
+ async ({ path }) => {
1109
+ let root;
1110
+ try {
1111
+ root = findPluginRoot(path ? resolve(path) : process.cwd());
1112
+ } catch (err) {
1113
+ return { isError: true, content: [{ type: "text", text: err.message }] };
1114
+ }
1115
+ const lines = formatProjectCheck(checkProject(root));
1116
+ const text = lines.length
1117
+ ? `${root}: ${lines.filter((l) => /:\d+ {2}/.test(l)).length} item(s) to fix\n${lines.join("\n")}`
1118
+ : `${root}: no issues — the project matches the installed plugin-ui.`;
1119
+ return { content: [{ type: "text", text }] };
1120
+ },
1121
+ );
1122
+
1093
1123
  const transport = new StdioServerTransport();
1094
1124
  await server.connect(transport);
1095
1125
  }
package/cli/src/new.mjs CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  } from "node:fs";
14
14
  import { basename, dirname, resolve } from "node:path";
15
15
  import { color, ensureIdeVenv, hasBin, kitVersion, parseArgs, prompt, templatesDir, log } from "./util.mjs";
16
- import { agentsMd, CLAUDE_MD } from "./ai-rules.mjs";
16
+ import { agentsMd, CLAUDE_MD, MCP_JSON } from "./ai-rules.mjs";
17
17
 
18
18
  // Like cpSync(src, dst, {recursive:true}) but reads from the embedded snapshot
19
19
  // when the templates dir doesn't exist on disk (compiled binary mode).
@@ -281,6 +281,7 @@ export async function runNew(args) {
281
281
  // Rules for AI agents, generated from the same source as the MCP server's instructions.
282
282
  writeFileSync(resolve(target, "AGENTS.md"), agentsMd({ pluginName }));
283
283
  writeFileSync(resolve(target, "CLAUDE.md"), CLAUDE_MD);
284
+ writeFileSync(resolve(target, ".mcp.json"), MCP_JSON);
284
285
 
285
286
  if (!opts["no-install"]) {
286
287
  try {
@@ -0,0 +1,102 @@
1
+ // What a project must change for the plugin-ui it has installed: known old APIs (ai-rules.mjs) plus
2
+ // `tsc --noEmit`. Shared by `muscat-pk update` and the MCP tool check_project, so a user and an
3
+ // agent see the same list.
4
+ import { spawnSync } from "node:child_process";
5
+ import { existsSync, readdirSync, readFileSync } from "node:fs";
6
+ import { join, relative, resolve } from "node:path";
7
+ import { LEGACY_COMPONENTS, LEGACY_SUBPATHS } from "./ai-rules.mjs";
8
+
9
+ const isBinaryMode = typeof Bun !== "undefined";
10
+
11
+ // The clause can't hold quotes or `;`, so a match can't start at an earlier import statement.
12
+ const PLUGIN_UI_IMPORT = /import\s+([^;'"]*?)\s+from\s+["']@rainbow-robotics\/plugin-ui\/([\w-]+)["']/g;
13
+
14
+ function listUiFiles(dir) {
15
+ return readdirSync(dir, { withFileTypes: true }).flatMap((e) =>
16
+ e.isDirectory() ? listUiFiles(join(dir, e.name)) : /\.[jt]sx?$/.test(e.name) ? [join(dir, e.name)] : [],
17
+ );
18
+ }
19
+
20
+ // rb.toast takes one { message, type } object now; flag a string or multi-argument call.
21
+ const TOAST_CALL = /\.toast\(([^()]*)\)/g;
22
+
23
+ /** Uses of the pre-1.x plugin-ui API in the project (ui/ and vite.config), as { file, line, text }. */
24
+ function findLegacyUiUsage(root) {
25
+ const uiDir = resolve(root, "ui");
26
+ if (!existsSync(uiDir)) return [];
27
+ const found = [];
28
+ // The old hand-written config builds entries without their exports (connect() rendered as a side
29
+ // effect), so `export default App` is dropped from dist. The muscat() preset keeps it.
30
+ const viteConfig = ["vite.config.ts", "vite.config.mts", "vite.config.js", "vite.config.mjs"].find((f) => existsSync(resolve(root, f)));
31
+ if (viteConfig && !readFileSync(resolve(root, viteConfig), "utf8").includes("@rainbow-robotics/muscat-plugin-kit/vite")) {
32
+ found.push({
33
+ file: viteConfig,
34
+ line: 1,
35
+ text: 'not using the muscat() preset — the build drops the entry\'s default export. Use: import { muscat } from "@rainbow-robotics/muscat-plugin-kit/vite"; defineConfig({ plugins: [muscat()] })',
36
+ });
37
+ }
38
+ for (const file of listUiFiles(uiDir)) {
39
+ const src = readFileSync(file, "utf8");
40
+ const rel = relative(root, file);
41
+ const lineOf = (index) => src.slice(0, index).split("\n").length;
42
+ for (const m of src.matchAll(PLUGIN_UI_IMPORT)) {
43
+ const [, clause, subpath] = m;
44
+ if (LEGACY_SUBPATHS[subpath]) {
45
+ found.push({ file: rel, line: lineOf(m.index), text: `@rainbow-robotics/plugin-ui/${subpath} ${LEGACY_SUBPATHS[subpath]}` });
46
+ } else if (subpath === "react") {
47
+ const named = clause.match(/\{([\s\S]*)\}/)?.[1] ?? "";
48
+ for (const spec of named.split(",")) {
49
+ const name = spec.trim().replace(/^type\s+/, "").split(/\s+as\s+/)[0];
50
+ if (LEGACY_COMPONENTS[name]) {
51
+ found.push({ file: rel, line: lineOf(m.index), text: `${name} → ${LEGACY_COMPONENTS[name]}` });
52
+ }
53
+ }
54
+ }
55
+ }
56
+ for (const m of src.matchAll(TOAST_CALL)) {
57
+ const arg = m[1].trim();
58
+ if (!arg.startsWith("{") && (/^["'`]/.test(arg) || arg.includes(","))) {
59
+ found.push({ file: rel, line: lineOf(m.index), text: "rb.toast(message, type) → rb.toast({ message, type })" });
60
+ }
61
+ }
62
+ // Top-level ui/ files are the entries; the host mounts their default export.
63
+ if (relative(uiDir, file).split(/[\\/]/).length === 1 && !/export\s+default\b/.test(src)) {
64
+ found.push({ file: rel, line: 1, text: "no default export — the host renders the entry's default export" });
65
+ }
66
+ }
67
+ return found;
68
+ }
69
+
70
+ // The known-API list above only knows past changes. Type-checking against the plugin-ui that was
71
+ // just installed catches whatever a later release removes or reshapes, with no list to keep up.
72
+ function typeScriptErrors(root) {
73
+ const tsc = resolve(root, "node_modules/typescript/bin/tsc");
74
+ if (!existsSync(tsc) || !existsSync(resolve(root, "tsconfig.json"))) return [];
75
+ const runtime = isBinaryMode ? "node" : process.execPath;
76
+ const r = spawnSync(runtime, [tsc, "--noEmit", "-p", root, "--pretty", "false"], { cwd: root, encoding: "utf8" });
77
+ return `${r.stdout ?? ""}`
78
+ .split("\n")
79
+ .map((l) => /^(.+?)\((\d+),\d+\): error (TS\d+): (.*)$/.exec(l))
80
+ .filter(Boolean)
81
+ .map(([, file, line, code, text]) => ({ file: relative(root, resolve(root, file)), line: Number(line), text: `${code} ${text}` }));
82
+ }
83
+
84
+ /** Everything the project must change, as { file, line, text, source: "known" | "tsc" }. */
85
+ export function checkProject(root) {
86
+ return [
87
+ ...findLegacyUiUsage(root).map((f) => ({ ...f, source: "known" })),
88
+ ...typeScriptErrors(root).map((e) => ({ ...e, source: "tsc" })),
89
+ ];
90
+ }
91
+
92
+ /** Plain-text lines for a checkProject() result (empty when there is nothing to fix). */
93
+ export function formatProjectCheck(items) {
94
+ if (!items.length) return [];
95
+ const line = (i) => ` ${i.file}:${i.line} ${i.text}`;
96
+ const tsc = items.filter((i) => i.source === "tsc");
97
+ return [
98
+ ...items.filter((i) => i.source !== "tsc").map(line),
99
+ ...(tsc.length ? [" TypeScript (tsc --noEmit):", ...tsc.map(line)] : []),
100
+ " For working examples, generate a fresh project and read its ui/content.tsx: muscat-pk new <dir>",
101
+ ];
102
+ }
@@ -11,8 +11,10 @@
11
11
  // After updating the CLI itself, also bumps the plugin project's local deps
12
12
  // and migrates the project structure if it's outdated (src/ → ui/, root main.py → py/).
13
13
  import { execSync, spawn, spawnSync } from "node:child_process";
14
- import { chmodSync, existsSync, mkdirSync, readdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
15
- import { join, relative, resolve } from "node:path";
14
+ import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
15
+ import { join, resolve } from "node:path";
16
+ import { agentsMd, CLAUDE_MD, MCP_JSON } from "./ai-rules.mjs";
17
+ import { checkProject, formatProjectCheck } from "./projectCheck.mjs";
16
18
  import {
17
19
  compareKitVersions, findPluginRoot, isLocalKitInstall, KIT_PUBLISHED_NAME, kitVersion, log, parseArgs, prompt,
18
20
  resolveLocalCliBin,
@@ -227,108 +229,13 @@ function updateLocalDeps(root, tag) {
227
229
  }
228
230
  }
229
231
 
230
- // ── legacy plugin-ui API ──────────────────────────────────────────────────────
231
- // plugin-ui 1.x replaced the remote-dom components and connect() bootstrap. update can't rewrite
232
- // UI code, so after bumping it lists what the user has to change.
233
-
234
- const LEGACY_SUBPATHS = {
235
- connect: "removed — drop `connect(App)` and `export default App` instead (the host renders the entry's default export)",
236
- elements: "removed — use the RB* components from @rainbow-robotics/plugin-ui/react",
237
- "dist-browser": "removed — import from @rainbow-robotics/plugin-ui/react",
238
- };
239
- const LEGACY_COMPONENTS = {
240
- Slider: "RBSlider",
241
- Button: "RBLabelButton",
242
- IconButton: "RBIconButton",
243
- Text: "a plain element or RBTextLabel",
244
- TextInput: "RBTextInput / RBTextField",
245
- Switch: "RBSwitch",
246
- Select: "RBSelectBox",
247
- };
248
- // The clause can't hold quotes or `;`, so a match can't start at an earlier import statement.
249
- const PLUGIN_UI_IMPORT = /import\s+([^;'"]*?)\s+from\s+["']@rainbow-robotics\/plugin-ui\/([\w-]+)["']/g;
250
-
251
- function listUiFiles(dir) {
252
- return readdirSync(dir, { withFileTypes: true }).flatMap((e) =>
253
- e.isDirectory() ? listUiFiles(join(dir, e.name)) : /\.[jt]sx?$/.test(e.name) ? [join(dir, e.name)] : [],
254
- );
255
- }
256
-
257
- // rb.toast takes one { message, type } object now; flag a string or multi-argument call.
258
- const TOAST_CALL = /\.toast\(([^()]*)\)/g;
259
-
260
- /** Uses of the pre-1.x plugin-ui API in the project (ui/ and vite.config), as { file, line, text }. */
261
- export function findLegacyUiUsage(root) {
262
- const uiDir = resolve(root, "ui");
263
- if (!existsSync(uiDir)) return [];
264
- const found = [];
265
- // The old hand-written config builds entries without their exports (connect() rendered as a side
266
- // effect), so `export default App` is dropped from dist. The muscat() preset keeps it.
267
- const viteConfig = ["vite.config.ts", "vite.config.mts", "vite.config.js", "vite.config.mjs"].find((f) => existsSync(resolve(root, f)));
268
- if (viteConfig && !readFileSync(resolve(root, viteConfig), "utf8").includes("@rainbow-robotics/muscat-plugin-kit/vite")) {
269
- found.push({
270
- file: viteConfig,
271
- line: 1,
272
- text: 'not using the muscat() preset — the build drops the entry\'s default export. Use: import { muscat } from "@rainbow-robotics/muscat-plugin-kit/vite"; defineConfig({ plugins: [muscat()] })',
273
- });
274
- }
275
- for (const file of listUiFiles(uiDir)) {
276
- const src = readFileSync(file, "utf8");
277
- const rel = relative(root, file);
278
- const lineOf = (index) => src.slice(0, index).split("\n").length;
279
- for (const m of src.matchAll(PLUGIN_UI_IMPORT)) {
280
- const [, clause, subpath] = m;
281
- if (LEGACY_SUBPATHS[subpath]) {
282
- found.push({ file: rel, line: lineOf(m.index), text: `@rainbow-robotics/plugin-ui/${subpath} ${LEGACY_SUBPATHS[subpath]}` });
283
- } else if (subpath === "react") {
284
- const named = clause.match(/\{([\s\S]*)\}/)?.[1] ?? "";
285
- for (const spec of named.split(",")) {
286
- const name = spec.trim().replace(/^type\s+/, "").split(/\s+as\s+/)[0];
287
- if (LEGACY_COMPONENTS[name]) {
288
- found.push({ file: rel, line: lineOf(m.index), text: `${name} → ${LEGACY_COMPONENTS[name]}` });
289
- }
290
- }
291
- }
292
- }
293
- for (const m of src.matchAll(TOAST_CALL)) {
294
- const arg = m[1].trim();
295
- if (!arg.startsWith("{") && (/^["'`]/.test(arg) || arg.includes(","))) {
296
- found.push({ file: rel, line: lineOf(m.index), text: "rb.toast(message, type) → rb.toast({ message, type })" });
297
- }
298
- }
299
- // Top-level ui/ files are the entries; the host mounts their default export.
300
- if (relative(uiDir, file).split(/[\\/]/).length === 1 && !/export\s+default\b/.test(src)) {
301
- found.push({ file: rel, line: 1, text: "no default export — the host renders the entry's default export" });
302
- }
303
- }
304
- return found;
305
- }
306
-
307
- // The known-API list above only knows past changes. Type-checking against the plugin-ui that was
308
- // just installed catches whatever a later release removes or reshapes, with no list to keep up.
309
- function typeScriptErrors(root) {
310
- const tsc = resolve(root, "node_modules/typescript/bin/tsc");
311
- if (!existsSync(tsc) || !existsSync(resolve(root, "tsconfig.json"))) return [];
312
- const runtime = isBinaryMode ? "node" : process.execPath;
313
- const r = spawnSync(runtime, [tsc, "--noEmit", "-p", root, "--pretty", "false"], { cwd: root, encoding: "utf8" });
314
- return `${r.stdout ?? ""}`
315
- .split("\n")
316
- .map((l) => /^(.+?)\((\d+),\d+\): error (TS\d+): (.*)$/.exec(l))
317
- .filter(Boolean)
318
- .map(([, file, line, code, text]) => ({ file: relative(root, resolve(root, file)), line: Number(line), text: `${code} ${text}` }));
319
- }
232
+ const PROJECT_CHECK_HEADER = "This project needs changes for the updated plugin-ui. Fix these before `muscat-pk dev` / `build`:";
320
233
 
321
234
  function reportProject(root) {
322
- const found = findLegacyUiUsage(root);
323
- const tsErrors = typeScriptErrors(root);
324
- if (!found.length && !tsErrors.length) return;
325
- log.warn("This project needs changes for the updated plugin-ui. Fix these before `muscat-pk dev` / `build`:");
326
- for (const f of found) log.info(` ${f.file}:${f.line} ${f.text}`);
327
- if (tsErrors.length) {
328
- log.info(" TypeScript (tsc --noEmit):");
329
- for (const e of tsErrors) log.info(` ${e.file}:${e.line} ${e.text}`);
330
- }
331
- log.info(" For working examples, generate a fresh project and read its ui/content.tsx: muscat-pk new <dir>");
235
+ const lines = formatProjectCheck(checkProject(root));
236
+ if (!lines.length) return;
237
+ log.warn(PROJECT_CHECK_HEADER);
238
+ for (const l of lines) log.info(l);
332
239
  }
333
240
 
334
241
  /** `muscat-pk update:check` — the post-update project check, run by the freshly installed kit. */
@@ -351,6 +258,32 @@ function checkProjectAfterUpdate(root) {
351
258
  reportProject(root);
352
259
  }
353
260
 
261
+ // ── AI agent files ────────────────────────────────────────────────────────────
262
+ // Projects made before `new` scaffolded these have no MCP server or agent rules, so an agent asked
263
+ // to fix the update can't call check_project. Only missing files are written; edited ones stay.
264
+
265
+ function pluginNameOf(root) {
266
+ try {
267
+ const { name } = JSON.parse(readFileSync(resolve(root, "manifest.json"), "utf8"));
268
+ if (typeof name === "string") return name;
269
+ if (name && typeof name === "object") return name.en ?? Object.values(name)[0] ?? "";
270
+ } catch { /* fall through */ }
271
+ return "";
272
+ }
273
+
274
+ function ensureAiFiles(root) {
275
+ const files = {
276
+ ".mcp.json": () => MCP_JSON,
277
+ "AGENTS.md": () => agentsMd({ pluginName: pluginNameOf(root) || "Plugin" }),
278
+ "CLAUDE.md": () => CLAUDE_MD,
279
+ };
280
+ for (const [file, content] of Object.entries(files)) {
281
+ if (existsSync(resolve(root, file))) continue;
282
+ writeFileSync(resolve(root, file), content());
283
+ log.ok(`${file} added (MCP server / AI agent rules)`);
284
+ }
285
+ }
286
+
354
287
  // ── main ─────────────────────────────────────────────────────────────────────
355
288
 
356
289
  async function resolveTag(explicitTag) {
@@ -432,6 +365,12 @@ export async function runUpdate(args = []) {
432
365
  log.warn(`Structure check failed: ${err.message}`);
433
366
  }
434
367
 
368
+ try {
369
+ ensureAiFiles(root);
370
+ } catch (err) {
371
+ log.warn(`AI agent files: ${err.message}`);
372
+ }
373
+
435
374
  updateLocalDeps(root, tag);
436
375
 
437
376
  try {
@@ -1 +1 @@
1
- {"generatedAt":1792689973585,"userSince":1750997484097,"hasCustomBabel":false,"hasCustomWebpack":false,"hasStaticDirs":false,"hasStorybookEslint":true,"refCount":0,"testPackages":{"@vitest/browser":"3.2.4","@vitest/coverage-v8":"3.2.4","playwright":"1.59.1","vitest":"3.2.4"},"hasRouterPackage":false,"monorepo":"Turborepo","packageManager":{"type":"yarn","version":"berry","agent":"yarn@berry"},"preview":{"usesGlobals":false},"framework":{"name":"@storybook/react-vite","options":{}},"builder":"@storybook/builder-vite","renderer":"@storybook/react","portableStoriesFileCount":0,"applicationFileCount":0,"storybookVersion":"8.6.18","storybookVersionSpecifier":"^8.6.4","language":"typescript","storybookPackages":{"@chromatic-com/storybook":{"version":"3.2.7"},"@storybook/addon-essentials":{"version":"8.6.18"},"@storybook/addon-links":{"version":"8.6.18"},"@storybook/addon-onboarding":{"version":"8.6.18"},"@storybook/addon-themes":{"version":"8.6.18"},"@storybook/blocks":{"version":"8.6.18"},"@storybook/experimental-addon-test":{"version":"8.6.18"},"@storybook/react":{"version":"8.6.18"},"@storybook/react-vite":{"version":"8.6.18"},"@storybook/test":{"version":"8.6.18"},"@storybook/theming":{"version":"8.6.18"},"eslint-plugin-storybook":{"version":"0.11.6"},"storybook":{"version":"8.6.18"},"storybook-addon-react-docgen":{"version":"1.2.44"}},"addons":{"$SNIP/node_modules/@storybook/addon-links":{"version":null},"$SNIP/node_modules/@storybook/addon-essentials":{"version":null},"$SNIP/node_modules/@chromatic-com/storybook":{"version":null},"$SNIP/node_modules/@storybook/addon-themes":{"version":null},"$SNIP/node_modules/@storybook/experimental-addon-test":{"version":null}}}
1
+ {"generatedAt":1792691105012,"userSince":1750997484097,"hasCustomBabel":false,"hasCustomWebpack":false,"hasStaticDirs":false,"hasStorybookEslint":true,"refCount":0,"testPackages":{"@vitest/browser":"3.2.4","@vitest/coverage-v8":"3.2.4","playwright":"1.59.1","vitest":"3.2.4"},"hasRouterPackage":false,"monorepo":"Turborepo","packageManager":{"type":"yarn","version":"berry","agent":"yarn@berry"},"preview":{"usesGlobals":false},"framework":{"name":"@storybook/react-vite","options":{}},"builder":"@storybook/builder-vite","renderer":"@storybook/react","portableStoriesFileCount":0,"applicationFileCount":0,"storybookVersion":"8.6.18","storybookVersionSpecifier":"^8.6.4","language":"typescript","storybookPackages":{"@chromatic-com/storybook":{"version":"3.2.7"},"@storybook/addon-essentials":{"version":"8.6.18"},"@storybook/addon-links":{"version":"8.6.18"},"@storybook/addon-onboarding":{"version":"8.6.18"},"@storybook/addon-themes":{"version":"8.6.18"},"@storybook/blocks":{"version":"8.6.18"},"@storybook/experimental-addon-test":{"version":"8.6.18"},"@storybook/react":{"version":"8.6.18"},"@storybook/react-vite":{"version":"8.6.18"},"@storybook/test":{"version":"8.6.18"},"@storybook/theming":{"version":"8.6.18"},"eslint-plugin-storybook":{"version":"0.11.6"},"storybook":{"version":"8.6.18"},"storybook-addon-react-docgen":{"version":"1.2.44"}},"addons":{"$SNIP/node_modules/@storybook/addon-links":{"version":null},"$SNIP/node_modules/@storybook/addon-essentials":{"version":null},"$SNIP/node_modules/@chromatic-com/storybook":{"version":null},"$SNIP/node_modules/@storybook/addon-themes":{"version":null},"$SNIP/node_modules/@storybook/experimental-addon-test":{"version":null}}}
@@ -1132,6 +1132,10 @@ letting it guess. `muscat-pk mcp` is an MCP server exposing:
1132
1132
  backend) classes and signatures; with `lang: "cpp"`, the C++ SDK headers
1133
1133
  (`rainbow-rb-sdk-dev`, read out of the `muscat-pk` cpp dev image — build it
1134
1134
  once with `muscat-pk dev:back`).
1135
+ - `check_project` — what this project must change for the plugin-ui it has
1136
+ installed (old APIs such as `connect(App)` or `Slider`, a `vite.config` without
1137
+ the `muscat()` preset, `tsc` errors), the same list `muscat-pk update` prints.
1138
+ Ask the assistant to fix the project after an update; it re-checks until clean.
1135
1139
 
1136
1140
  **Browse the components live** with `muscat-pk storybook`.
1137
1141
 
@@ -898,6 +898,10 @@ letting it guess. `muscat-pk mcp` is an MCP server exposing:
898
898
  backend) classes and signatures; with `lang: "cpp"`, the C++ SDK headers
899
899
  (`rainbow-rb-sdk-dev`, read out of the `muscat-pk` cpp dev image — build it
900
900
  once with `muscat-pk dev:back`).
901
+ - `check_project` — what this project must change for the plugin-ui it has
902
+ installed (old APIs such as `connect(App)` or `Slider`, a `vite.config` without
903
+ the `muscat()` preset, `tsc` errors), the same list `muscat-pk update` prints.
904
+ Ask the assistant to fix the project after an update; it re-checks until clean.
901
905
 
902
906
  **Browse the components live** with `muscat-pk storybook`.
903
907
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rainbow-robotics/muscat-plugin-kit",
3
- "version": "1.10.2-dev.2",
3
+ "version": "1.10.2-dev.3",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": ">=20"
@@ -52,8 +52,8 @@
52
52
  },
53
53
  "dependencies": {
54
54
  "@modelcontextprotocol/sdk": "^1.29.0",
55
- "@rainbow-robotics/plugin-ui": "1.10.2-dev.2",
56
- "@rainbow-robotics/preview-host": "1.10.2-dev.2",
55
+ "@rainbow-robotics/plugin-ui": "1.10.2-dev.3",
56
+ "@rainbow-robotics/preview-host": "1.10.2-dev.3",
57
57
  "@types/react": "^19.0.10",
58
58
  "postcss": "^8.5.8",
59
59
  "typescript": "^5.8.0",
@@ -1,8 +0,0 @@
1
- {
2
- "mcpServers": {
3
- "muscat": {
4
- "command": "muscat-pk",
5
- "args": ["mcp"]
6
- }
7
- }
8
- }