@buoy-design/cli 0.6.1 → 0.7.0

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.
@@ -5,6 +5,7 @@ export { createAhoyCommand } from "./ahoy.js";
5
5
  export { createDesignMdCommand } from "./designmd/index.js";
6
6
  export { createSystemCommand } from "./system.js";
7
7
  export { createRescueCommand } from "./rescue.js";
8
+ export { createMcpCommand } from "./mcp.js";
8
9
  export { createCheckCommand } from "./check.js";
9
10
  export { createIgnoreCommand, loadIgnoreList, filterIgnored, } from "./ignore.js";
10
11
  export { createFixCommand } from "./fix.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAGlD,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,aAAa,GACd,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAG5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,aAAa,GACd,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC"}
@@ -5,6 +5,7 @@ export { createAhoyCommand } from "./ahoy.js";
5
5
  export { createDesignMdCommand } from "./designmd/index.js";
6
6
  export { createSystemCommand } from "./system.js";
7
7
  export { createRescueCommand } from "./rescue.js";
8
+ export { createMcpCommand } from "./mcp.js";
8
9
  // Re-exports for internal use (subcommands within groups)
9
10
  export { createCheckCommand } from "./check.js";
10
11
  export { createIgnoreCommand, loadIgnoreList, filterIgnored, } from "./ignore.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD,0DAA0D;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,aAAa,GACd,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE5C,0DAA0D;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,aAAa,GACd,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * buoy mcp - Connect coding agents to this repo's design system.
3
+ *
4
+ * buoy mcp serve stdio MCP server (tokens, drift checks, context)
5
+ * buoy mcp install [client] write .mcp.json / .cursor/mcp.json and the Claude Code hook
6
+ * buoy mcp hook Claude Code PostToolUse hook: check the edited file
7
+ */
8
+ import { Command } from "commander";
9
+ export declare function createMcpCommand(): Command;
10
+ //# sourceMappingURL=mcp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/commands/mcp.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYpC,wBAAgB,gBAAgB,IAAI,OAAO,CAoD1C"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * buoy mcp - Connect coding agents to this repo's design system.
3
+ *
4
+ * buoy mcp serve stdio MCP server (tokens, drift checks, context)
5
+ * buoy mcp install [client] write .mcp.json / .cursor/mcp.json and the Claude Code hook
6
+ * buoy mcp hook Claude Code PostToolUse hook: check the edited file
7
+ */
8
+ import { Command } from "commander";
9
+ import pkg from "../../package.json" with { type: "json" };
10
+ import { installClient, MCP_CLIENTS } from "../mcp/install.js";
11
+ import { filePathFromHookPayload, runHook } from "../mcp/hook.js";
12
+ async function readStdin() {
13
+ if (process.stdin.isTTY)
14
+ return "";
15
+ const chunks = [];
16
+ for await (const chunk of process.stdin)
17
+ chunks.push(chunk);
18
+ return Buffer.concat(chunks).toString("utf8");
19
+ }
20
+ export function createMcpCommand() {
21
+ const cmd = new Command("mcp").description("Connect coding agents (Claude Code, Cursor, Codex) to your design system");
22
+ cmd
23
+ .command("serve")
24
+ .description("Run the MCP server over stdio (agents start this for you)")
25
+ .action(async () => {
26
+ const { serveStdio } = await import("../mcp/server.js");
27
+ await serveStdio({ cwd: process.cwd(), version: pkg.version });
28
+ });
29
+ cmd
30
+ .command("install [client]")
31
+ .description(`Write agent config for ${MCP_CLIENTS.join(", ")} or "all" (default: claude)`)
32
+ .option("--no-hook", "Skip the Claude Code PostToolUse drift hook")
33
+ .action((client, options) => {
34
+ const wanted = client === "all" ? MCP_CLIENTS : [(client ?? "claude")];
35
+ for (const c of wanted) {
36
+ if (!MCP_CLIENTS.includes(c)) {
37
+ console.error(`Unknown client "${c}". Choose one of: ${MCP_CLIENTS.join(", ")}, all`);
38
+ process.exit(1);
39
+ }
40
+ }
41
+ for (const c of wanted) {
42
+ const result = installClient(c, process.cwd(), { hook: options.hook });
43
+ console.log(`${c}: wrote ${result.files.join(", ")}`);
44
+ }
45
+ console.log("");
46
+ console.log("Agents in this repo can now call list_design_tokens, find_token_for_value, check_design_drift and design_system_context.");
47
+ if (wanted.includes("claude") && options.hook !== false) {
48
+ console.log("Claude Code will also get drift feedback after every Edit/Write of a style file.");
49
+ }
50
+ });
51
+ cmd
52
+ .command("hook")
53
+ .description("PostToolUse hook: reads the Claude Code payload on stdin and reports drift in the edited file")
54
+ .option("--file <path>", "Check this file instead of reading stdin")
55
+ .action(async (options) => {
56
+ const file = options.file ?? filePathFromHookPayload(await readStdin());
57
+ try {
58
+ const result = await runHook(process.cwd(), file);
59
+ if (result.message)
60
+ console.error(result.message);
61
+ process.exit(result.exitCode);
62
+ }
63
+ catch (error) {
64
+ // A broken hook must never block the agent.
65
+ console.error(`Buoy hook skipped: ${error instanceof Error ? error.message : String(error)}`);
66
+ process.exit(0);
67
+ }
68
+ });
69
+ return cmd;
70
+ }
71
+ //# sourceMappingURL=mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../src/commands/mcp.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYpC,wBAAgB,SAAS,IAAI,OAAO,CAkDnC;AAGD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC,wBAAgB,SAAS,IAAI,OAAO,CAqDnC;AAGD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Command } from "commander";
2
2
  import pkg from "../package.json" with { type: "json" };
3
- import { createShowCommand, createDriftCommand, createDockCommand, createAhoyCommand, createDesignMdCommand, createSystemCommand, createRescueCommand, } from "./commands/index.js";
3
+ import { createShowCommand, createDriftCommand, createDockCommand, createAhoyCommand, createDesignMdCommand, createSystemCommand, createRescueCommand, createMcpCommand, } from "./commands/index.js";
4
4
  export function createCli() {
5
5
  const program = new Command();
6
6
  program
@@ -39,6 +39,8 @@ Quick Start:
39
39
  program.addCommand(createAhoyCommand());
40
40
  // === Design ===
41
41
  program.addCommand(createDesignMdCommand());
42
+ // Agent integration: MCP server, client config, Claude Code hook
43
+ program.addCommand(createMcpCommand());
42
44
  return program;
43
45
  }
44
46
  // Re-export config utilities for user config files
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,GAAG,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACxD,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,UAAU,SAAS;IACvB,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,MAAM,CAAC;SACZ,WAAW,CAAC,kDAAkD,CAAC;SAC/D,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;SACpB,aAAa,CAAC;QACb,eAAe,EAAE,KAAK;QACtB,cAAc,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE;KACpC,CAAC;SACD,WAAW,CACV,OAAO,EACP;;;;;;;;;;;;;;CAcL,CACI,CAAC;IAEJ,2BAA2B;IAC3B,OAAO,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC,CAAC;IACxC,OAAO,CAAC,UAAU,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAE1C,mCAAmC;IACnC,OAAO,CAAC,UAAU,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAE1C,wBAAwB;IACxB,OAAO,CAAC,UAAU,CAAC,kBAAkB,EAAE,CAAC,CAAC;IAEzC,gBAAgB;IAChB,OAAO,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC,CAAC;IAExC,gBAAgB;IAChB,OAAO,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC,CAAC;IAExC,iBAAiB;IACjB,OAAO,CAAC,UAAU,CAAC,qBAAqB,EAAE,CAAC,CAAC;IAE5C,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,mDAAmD;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,GAAG,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACxD,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,UAAU,SAAS;IACvB,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,MAAM,CAAC;SACZ,WAAW,CAAC,kDAAkD,CAAC;SAC/D,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;SACpB,aAAa,CAAC;QACb,eAAe,EAAE,KAAK;QACtB,cAAc,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE;KACpC,CAAC;SACD,WAAW,CACV,OAAO,EACP;;;;;;;;;;;;;;CAcL,CACI,CAAC;IAEJ,2BAA2B;IAC3B,OAAO,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC,CAAC;IACxC,OAAO,CAAC,UAAU,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAE1C,mCAAmC;IACnC,OAAO,CAAC,UAAU,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAE1C,wBAAwB;IACxB,OAAO,CAAC,UAAU,CAAC,kBAAkB,EAAE,CAAC,CAAC;IAEzC,gBAAgB;IAChB,OAAO,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC,CAAC;IAExC,gBAAgB;IAChB,OAAO,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC,CAAC;IAExC,iBAAiB;IACjB,OAAO,CAAC,UAAU,CAAC,qBAAqB,EAAE,CAAC,CAAC;IAE5C,iEAAiE;IACjE,OAAO,CAAC,UAAU,CAAC,gBAAgB,EAAE,CAAC,CAAC;IAEvC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,mDAAmD;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { DesignToken } from "@buoy-design/core";
2
+ import { type RawSignal } from "@buoy-design/scanners";
3
+ /** Split a shorthand value on spaces, keeping function calls like rgb(...) intact. */
4
+ export declare function splitCssValue(value: string): string[];
5
+ /** Value-level signals for one file's content. Pure; `path` is only used for locations. */
6
+ export declare function extractFileSignals(content: string, path: string): RawSignal[];
7
+ export interface FileIssue {
8
+ file: string;
9
+ line: number;
10
+ type: string;
11
+ severity: "warning" | "info";
12
+ message: string;
13
+ current: string;
14
+ suggested?: string;
15
+ tokenSuggestions?: string[];
16
+ }
17
+ /** Turn raw signals into issues, attaching the token that has the same value when one exists. */
18
+ export declare function issuesFromSignals(signals: RawSignal[], tokens: DesignToken[]): FileIssue[];
19
+ export declare function checkFiles(files: string[], projectRoot: string, tokens: DesignToken[]): Promise<FileIssue[]>;
20
+ //# sourceMappingURL=file-check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-check.d.ts","sourceRoot":"","sources":["../../src/mcp/file-check.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAgBL,KAAK,SAAS,EAEf,MAAM,uBAAuB,CAAC;AAU/B,sFAAsF;AACtF,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAgBrD;AAgFD,2FAA2F;AAC3F,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,CAgC7E;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,SAAS,GAAG,MAAM,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B;AAMD,iGAAiG;AACjG,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,SAAS,EAAE,CAyB1F;AAED,wBAAsB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAclH"}
@@ -0,0 +1,195 @@
1
+ /**
2
+ * Line-level drift check for a handful of files.
3
+ *
4
+ * The repo-wide DriftAnalysisService reasons about components; it does not
5
+ * look at literal values inside plain CSS, and it reports a component's line,
6
+ * not the value's. Agents need "line 12: #fff -> var(--color-white)", so this
7
+ * runs the same value-level extractors the PR reviewer uses, per file, and
8
+ * looks each value up in the repo's tokens.
9
+ */
10
+ import { readFile } from "node:fs/promises";
11
+ import { isAbsolute, join, relative } from "node:path";
12
+ import { extractBorderWidthSignals, extractColorSignals, extractDurationSignals, extractEasingSignals, extractFontFamilySignals, extractFontSizeSignals, extractFontWeightSignals, extractLetterSpacingSignals, extractLineHeightSignals, extractOpacitySignals, extractRadiusSignals, extractShadowSignals, extractSpacingSignals, extractTransitionShorthandSignals, extractZIndexSignals, } from "@buoy-design/scanners";
13
+ import { findTokensByValue } from "./project.js";
14
+ const COLOR_PART = /^(#[0-9a-f]{3,8}|rgba?\(|hsla?\(|oklch\(|oklab\(|color\()/i;
15
+ /** Split a shorthand value on spaces, keeping function calls like rgb(...) intact. */
16
+ export function splitCssValue(value) {
17
+ const parts = [];
18
+ let current = "";
19
+ let depth = 0;
20
+ for (const ch of value) {
21
+ if (ch === "(")
22
+ depth++;
23
+ if (ch === ")")
24
+ depth--;
25
+ if (ch === " " && depth === 0) {
26
+ if (current)
27
+ parts.push(current);
28
+ current = "";
29
+ }
30
+ else {
31
+ current += ch;
32
+ }
33
+ }
34
+ if (current)
35
+ parts.push(current);
36
+ return parts;
37
+ }
38
+ // Same routing as the cloud scanner container (containers/scanner/src/index.js).
39
+ const CSS_PROPERTY_EXTRACTORS = {
40
+ color: "color", "background-color": "color", "border-color": "color", "outline-color": "color",
41
+ "text-decoration-color": "color", fill: "color", stroke: "color", "caret-color": "color", "accent-color": "color",
42
+ padding: "spacing", "padding-top": "spacing", "padding-right": "spacing", "padding-bottom": "spacing", "padding-left": "spacing",
43
+ "padding-inline": "spacing", "padding-block": "spacing",
44
+ margin: "spacing", "margin-top": "spacing", "margin-right": "spacing", "margin-bottom": "spacing", "margin-left": "spacing",
45
+ "margin-inline": "spacing", "margin-block": "spacing",
46
+ gap: "spacing", "row-gap": "spacing", "column-gap": "spacing",
47
+ top: "spacing", right: "spacing", bottom: "spacing", left: "spacing", inset: "spacing",
48
+ "font-size": "fontSize", "font-family": "fontFamily", "font-weight": "fontWeight",
49
+ "line-height": "lineHeight", "letter-spacing": "letterSpacing",
50
+ "border-radius": "radius", "border-top-left-radius": "radius", "border-top-right-radius": "radius",
51
+ "border-bottom-left-radius": "radius", "border-bottom-right-radius": "radius",
52
+ "box-shadow": "shadow", "text-shadow": "shadow",
53
+ "z-index": "zIndex", opacity: "opacity",
54
+ "transition-duration": "duration", "animation-duration": "duration",
55
+ "transition-timing-function": "easing", "animation-timing-function": "easing",
56
+ transition: "transitionShorthand",
57
+ "border-width": "borderWidth", "border-top-width": "borderWidth", "border-right-width": "borderWidth",
58
+ "border-bottom-width": "borderWidth", "border-left-width": "borderWidth",
59
+ background: "colorShorthand", border: "colorShorthand", "border-top": "colorShorthand",
60
+ "border-right": "colorShorthand", "border-bottom": "colorShorthand", "border-left": "colorShorthand", outline: "colorShorthand",
61
+ };
62
+ const JSX_PROPERTY_EXTRACTORS = Object.fromEntries(Object.entries(CSS_PROPERTY_EXTRACTORS).map(([prop, extractor]) => [
63
+ prop.replace(/-([a-z])/g, (_, c) => c.toUpperCase()),
64
+ extractor,
65
+ ]));
66
+ // Signal type -> token category to search for a replacement.
67
+ const SIGNAL_CATEGORY = {
68
+ "color-value": "color",
69
+ "spacing-value": "spacing",
70
+ "radius-value": "border",
71
+ "shadow-value": "shadow",
72
+ "border-width": "border",
73
+ "font-size": "typography",
74
+ "font-family": "typography",
75
+ "font-weight": "typography",
76
+ "line-height": "typography",
77
+ "letter-spacing": "typography",
78
+ "z-index": "zIndex",
79
+ "motion-duration": "motion",
80
+ "motion-easing": "motion",
81
+ "opacity-value": undefined,
82
+ };
83
+ const CSS_PROP = /([a-z-]+)\s*:\s*([^;{}]+)/g;
84
+ const JSX_PROP = /(\w+)\s*:\s*(?:'([^']*)'|"([^"]*)"|(\d+\.?\d*)(?=[,}\s]))/g;
85
+ function route(extractor, value, path, line, property, ctx) {
86
+ switch (extractor) {
87
+ case "color": return extractColorSignals(value, path, line, property, ctx);
88
+ case "spacing": return extractSpacingSignals(value, path, line, property, ctx);
89
+ case "fontSize": return extractFontSizeSignals(value, path, line, ctx);
90
+ case "fontFamily": return extractFontFamilySignals(value, path, line, ctx);
91
+ case "fontWeight": return extractFontWeightSignals(value, path, line, ctx);
92
+ case "lineHeight": return extractLineHeightSignals(value, path, line, ctx);
93
+ case "letterSpacing": return extractLetterSpacingSignals(value, path, line, ctx);
94
+ case "radius": return extractRadiusSignals(value, path, line, property, ctx);
95
+ case "shadow": return extractShadowSignals(value, path, line, property, ctx);
96
+ case "zIndex": return extractZIndexSignals(value, path, line, ctx);
97
+ case "opacity": return extractOpacitySignals(value, path, line, ctx);
98
+ case "duration": return extractDurationSignals(value, path, line, property, ctx);
99
+ case "easing": return extractEasingSignals(value, path, line, property, ctx);
100
+ case "borderWidth": return extractBorderWidthSignals(value, path, line, property, ctx);
101
+ case "transitionShorthand": return extractTransitionShorthandSignals(value, path, line, ctx);
102
+ case "colorShorthand":
103
+ // background / border shorthands: only the colour part is a token candidate.
104
+ return splitCssValue(value)
105
+ .filter((part) => COLOR_PART.test(part))
106
+ .flatMap((part) => extractColorSignals(part, path, line, `${property}-color`, ctx));
107
+ }
108
+ }
109
+ /** Value-level signals for one file's content. Pure; `path` is only used for locations. */
110
+ export function extractFileSignals(content, path) {
111
+ const isCss = /\.(css|scss)$/.test(path);
112
+ const isJsx = /\.(tsx|jsx)$/.test(path);
113
+ if (!isCss && !isJsx)
114
+ return [];
115
+ const ctx = {
116
+ fileType: isCss ? "css" : "tsx",
117
+ framework: isJsx ? "react" : "css",
118
+ scope: "global",
119
+ isTokenized: false,
120
+ };
121
+ const signals = [];
122
+ const lines = content.split("\n");
123
+ for (let i = 0; i < lines.length; i++) {
124
+ const line = lines[i] ?? "";
125
+ // Already tokenised: var(--x), theme.x, tokens.x, $scss-var
126
+ if (line.includes("var(--") || line.includes("theme.") || line.includes("tokens.") || line.includes("$"))
127
+ continue;
128
+ const pattern = isCss ? CSS_PROP : JSX_PROP;
129
+ const table = isCss ? CSS_PROPERTY_EXTRACTORS : JSX_PROPERTY_EXTRACTORS;
130
+ pattern.lastIndex = 0;
131
+ let m;
132
+ while ((m = pattern.exec(line)) !== null) {
133
+ const property = (m[1] ?? "").trim();
134
+ const extractor = table[property];
135
+ if (!extractor)
136
+ continue;
137
+ let value = isCss ? (m[2] ?? "").trim() : (m[2] ?? m[3] ?? m[4]);
138
+ if (value === undefined || value === "")
139
+ continue;
140
+ // Bare numbers in JSX style objects are pixels.
141
+ if (isJsx && m[4] !== undefined)
142
+ value = `${value}px`;
143
+ signals.push(...route(extractor, value, path, i + 1, property, ctx));
144
+ }
145
+ }
146
+ return signals;
147
+ }
148
+ function tokenRef(token) {
149
+ return token.name.startsWith("--") ? `var(${token.name})` : token.name;
150
+ }
151
+ /** Turn raw signals into issues, attaching the token that has the same value when one exists. */
152
+ export function issuesFromSignals(signals, tokens) {
153
+ const seen = new Set();
154
+ const issues = [];
155
+ for (const s of signals) {
156
+ const current = String(s.value);
157
+ const key = `${s.location.path}:${s.location.line}:${s.type}:${current}`;
158
+ if (seen.has(key))
159
+ continue;
160
+ seen.add(key);
161
+ const category = SIGNAL_CATEGORY[s.type];
162
+ const matches = findTokensByValue(tokens, current, category);
163
+ const first = matches[0];
164
+ const label = s.type.replace(/-value$/, "").replace(/-/g, " ");
165
+ issues.push({
166
+ file: s.location.path,
167
+ line: s.location.line,
168
+ type: `hardcoded-${s.type.replace(/-value$/, "")}`,
169
+ severity: first ? "warning" : "info",
170
+ message: first
171
+ ? `Hardcoded ${label} ${current} has a token: ${first.name}`
172
+ : `Hardcoded ${label} ${current} (no matching token)`,
173
+ current,
174
+ ...(first ? { suggested: tokenRef(first), tokenSuggestions: matches.map(tokenRef) } : {}),
175
+ });
176
+ }
177
+ return issues;
178
+ }
179
+ export async function checkFiles(files, projectRoot, tokens) {
180
+ const issues = [];
181
+ for (const file of files) {
182
+ const abs = isAbsolute(file) ? file : join(projectRoot, file);
183
+ const rel = relative(projectRoot, abs) || file;
184
+ let content;
185
+ try {
186
+ content = await readFile(abs, "utf8");
187
+ }
188
+ catch {
189
+ continue; // deleted or unreadable: nothing to check
190
+ }
191
+ issues.push(...issuesFromSignals(extractFileSignals(content, rel), tokens));
192
+ }
193
+ return issues;
194
+ }
195
+ //# sourceMappingURL=file-check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-check.js","sourceRoot":"","sources":["../../src/mcp/file-check.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Claude Code PostToolUse hook: after the agent edits a file, check that
3
+ * file for drift and hand the issues back as feedback (exit code 2). Other
4
+ * agents can call `buoy mcp hook --file <path>` the same way.
5
+ */
6
+ import { type DriftCheck } from "./project.js";
7
+ /** Pull the edited path out of a Claude Code hook payload. */
8
+ export declare function filePathFromHookPayload(raw: string): string | null;
9
+ export declare function isStyleFile(path: string): boolean;
10
+ export declare function formatHookFeedback(file: string, check: DriftCheck): string;
11
+ export interface HookResult {
12
+ exitCode: 0 | 2;
13
+ message: string | null;
14
+ }
15
+ export declare function runHook(cwd: string, file: string | null): Promise<HookResult>;
16
+ //# sourceMappingURL=hook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../../src/mcp/hook.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAA2B,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAIxE,8DAA8D;AAC9D,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOlE;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,MAAM,CAU1E;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC;IAChB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,wBAAsB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC,CAMnF"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Claude Code PostToolUse hook: after the agent edits a file, check that
3
+ * file for drift and hand the issues back as feedback (exit code 2). Other
4
+ * agents can call `buoy mcp hook --file <path>` the same way.
5
+ */
6
+ import { checkDrift, loadProject } from "./project.js";
7
+ const STYLE_FILE = /\.(tsx|jsx|vue|svelte|css|scss|html)$/;
8
+ /** Pull the edited path out of a Claude Code hook payload. */
9
+ export function filePathFromHookPayload(raw) {
10
+ try {
11
+ const payload = JSON.parse(raw);
12
+ return payload.tool_input?.file_path ?? payload.tool_input?.path ?? payload.tool_response?.filePath ?? null;
13
+ }
14
+ catch {
15
+ return null;
16
+ }
17
+ }
18
+ export function isStyleFile(path) {
19
+ return STYLE_FILE.test(path);
20
+ }
21
+ export function formatHookFeedback(file, check) {
22
+ const lines = [`Buoy: ${check.summary.total} design drift issue${check.summary.total === 1 ? "" : "s"} in ${file}`];
23
+ for (const issue of check.issues.slice(0, 15)) {
24
+ const where = issue.line ? `:${issue.line}` : "";
25
+ const fix = issue.suggested ? ` -> use ${issue.suggested}` : issue.tokenSuggestions?.[0] ? ` -> ${issue.tokenSuggestions[0]}` : "";
26
+ lines.push(`- ${issue.file}${where} ${issue.message}${fix}`);
27
+ }
28
+ if (check.issues.length > 15)
29
+ lines.push(`- ... and ${check.issues.length - 15} more`);
30
+ lines.push("Replace the literal values with the tokens above, then continue.");
31
+ return lines.join("\n");
32
+ }
33
+ export async function runHook(cwd, file) {
34
+ if (!file || !isStyleFile(file))
35
+ return { exitCode: 0, message: null };
36
+ const project = await loadProject(cwd);
37
+ const check = await checkDrift(project, [file]);
38
+ if (check.summary.total === 0)
39
+ return { exitCode: 0, message: null };
40
+ return { exitCode: 2, message: formatHookFeedback(file, check) };
41
+ }
42
+ //# sourceMappingURL=hook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook.js","sourceRoot":"","sources":["../../src/mcp/hook.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAmB,MAAM,cAAc,CAAC;AAExE,MAAM,UAAU,GAAG,uCAAuC,CAAC;AAE3D,8DAA8D;AAC9D,MAAM,UAAU,uBAAuB,CAAC,GAAW;IACjD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAkG,CAAC;QACjI,OAAO,OAAO,CAAC,UAAU,EAAE,SAAS,IAAI,OAAO,CAAC,UAAU,EAAE,IAAI,IAAI,OAAO,CAAC,aAAa,EAAE,QAAQ,IAAI,IAAI,CAAC;IAC9G,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAY,EAAE,KAAiB;IAChE,MAAM,KAAK,GAAG,CAAC,SAAS,KAAK,CAAC,OAAO,CAAC,KAAK,sBAAsB,KAAK,CAAC,OAAO,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,OAAO,IAAI,EAAE,CAAC,CAAC;IACpH,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;QAC9C,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjD,MAAM,GAAG,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnI,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,IAAI,GAAG,KAAK,IAAI,KAAK,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC,CAAC;IAC/D,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,EAAE;QAAE,KAAK,CAAC,IAAI,CAAC,aAAa,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,EAAE,OAAO,CAAC,CAAC;IACvF,KAAK,CAAC,IAAI,CAAC,kEAAkE,CAAC,CAAC;IAC/E,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAOD,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,GAAW,EAAE,IAAmB;IAC5D,IAAI,CAAC,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACvE,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,GAAG,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAChD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,KAAK,CAAC;QAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACrE,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,kBAAkB,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC;AACnE,CAAC"}
@@ -0,0 +1,14 @@
1
+ export type McpClient = "claude" | "cursor" | "codex" | "windsurf";
2
+ export declare const MCP_CLIENTS: McpClient[];
3
+ /** Merge Buoy into an `mcpServers` map without touching other servers. */
4
+ export declare function mergeMcpServers(existing: Record<string, unknown>): Record<string, unknown>;
5
+ /** Add the PostToolUse hook to Claude Code settings unless it is already there. */
6
+ export declare function mergeClaudeHook(existing: Record<string, unknown>): Record<string, unknown>;
7
+ export interface InstallResult {
8
+ client: McpClient;
9
+ files: string[];
10
+ }
11
+ export declare function installClient(client: McpClient, cwd: string, options?: {
12
+ hook?: boolean;
13
+ }): InstallResult;
14
+ //# sourceMappingURL=install.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/mcp/install.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAC;AACnE,eAAO,MAAM,WAAW,EAAE,SAAS,EAA8C,CAAC;AAuBlF,0EAA0E;AAC1E,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAG1F;AAED,mFAAmF;AACnF,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQ1F;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,aAAa,CAwB7G"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Write the client-side config that connects an agent to `buoy mcp serve`.
3
+ * Every target is a JSON file in the project; existing entries are kept.
4
+ */
5
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
6
+ import { dirname, join } from "node:path";
7
+ export const MCP_CLIENTS = ["claude", "cursor", "codex", "windsurf"];
8
+ const SERVER_ENTRY = { command: "npx", args: ["-y", "@buoy-design/cli", "mcp", "serve"] };
9
+ const HOOK_ENTRY = {
10
+ matcher: "Edit|Write|MultiEdit",
11
+ hooks: [{ type: "command", command: "npx -y @buoy-design/cli mcp hook", timeout: 120 }],
12
+ };
13
+ function readJson(path) {
14
+ if (!existsSync(path))
15
+ return {};
16
+ try {
17
+ return JSON.parse(readFileSync(path, "utf8"));
18
+ }
19
+ catch {
20
+ throw new Error(`${path} is not valid JSON; fix or remove it and retry`);
21
+ }
22
+ }
23
+ function writeJson(path, value) {
24
+ mkdirSync(dirname(path), { recursive: true });
25
+ writeFileSync(path, JSON.stringify(value, null, 2) + "\n");
26
+ }
27
+ /** Merge Buoy into an `mcpServers` map without touching other servers. */
28
+ export function mergeMcpServers(existing) {
29
+ const servers = (existing.mcpServers && typeof existing.mcpServers === "object" ? existing.mcpServers : {});
30
+ return { ...existing, mcpServers: { ...servers, buoy: SERVER_ENTRY } };
31
+ }
32
+ /** Add the PostToolUse hook to Claude Code settings unless it is already there. */
33
+ export function mergeClaudeHook(existing) {
34
+ const hooks = (existing.hooks && typeof existing.hooks === "object" ? existing.hooks : {});
35
+ const post = Array.isArray(hooks.PostToolUse) ? hooks.PostToolUse : [];
36
+ const present = post.some((entry) => JSON.stringify(entry).includes("mcp hook"));
37
+ return {
38
+ ...existing,
39
+ hooks: { ...hooks, PostToolUse: present ? post : [...post, HOOK_ENTRY] },
40
+ };
41
+ }
42
+ export function installClient(client, cwd, options = {}) {
43
+ const files = [];
44
+ const upsert = (relative, merge) => {
45
+ const path = join(cwd, relative);
46
+ writeJson(path, merge(readJson(path)));
47
+ files.push(relative);
48
+ };
49
+ switch (client) {
50
+ case "claude":
51
+ upsert(".mcp.json", mergeMcpServers);
52
+ if (options.hook !== false)
53
+ upsert(".claude/settings.json", mergeClaudeHook);
54
+ break;
55
+ case "cursor":
56
+ upsert(".cursor/mcp.json", mergeMcpServers);
57
+ break;
58
+ case "windsurf":
59
+ upsert(".windsurf/mcp.json", mergeMcpServers);
60
+ break;
61
+ case "codex":
62
+ upsert(".codex/mcp.json", mergeMcpServers);
63
+ break;
64
+ }
65
+ return { client, files };
66
+ }
67
+ //# sourceMappingURL=install.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/mcp/install.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAG1C,MAAM,CAAC,MAAM,WAAW,GAAgB,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;AAElF,MAAM,YAAY,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,CAAC;AAE1F,MAAM,UAAU,GAAG;IACjB,OAAO,EAAE,sBAAsB;IAC/B,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,kCAAkC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;CACxF,CAAC;AAEF,SAAS,QAAQ,CAAC,IAAY;IAC5B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IACjC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAA4B,CAAC;IAC3E,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,gDAAgD,CAAC,CAAC;IAC3E,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,IAAY,EAAE,KAAc;IAC7C,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;AAC7D,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,eAAe,CAAC,QAAiC;IAC/D,MAAM,OAAO,GAAG,CAAC,QAAQ,CAAC,UAAU,IAAI,OAAO,QAAQ,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAA4B,CAAC;IACvI,OAAO,EAAE,GAAG,QAAQ,EAAE,UAAU,EAAE,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,CAAC;AACzE,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,eAAe,CAAC,QAAiC;IAC/D,MAAM,KAAK,GAAG,CAAC,QAAQ,CAAC,KAAK,IAAI,OAAO,QAAQ,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAA4B,CAAC;IACtH,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAE,KAAK,CAAC,WAA8C,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3G,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;IACjF,OAAO;QACL,GAAG,QAAQ;QACX,KAAK,EAAE,EAAE,GAAG,KAAK,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,EAAE;KACzE,CAAC;AACJ,CAAC;AAOD,MAAM,UAAU,aAAa,CAAC,MAAiB,EAAE,GAAW,EAAE,UAA8B,EAAE;IAC5F,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,MAAM,GAAG,CAAC,QAAgB,EAAE,KAA8D,EAAE,EAAE;QAClG,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QACjC,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACvC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACvB,CAAC,CAAC;IAEF,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,QAAQ;YACX,MAAM,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC;YACrC,IAAI,OAAO,CAAC,IAAI,KAAK,KAAK;gBAAE,MAAM,CAAC,uBAAuB,EAAE,eAAe,CAAC,CAAC;YAC7E,MAAM;QACR,KAAK,QAAQ;YACX,MAAM,CAAC,kBAAkB,EAAE,eAAe,CAAC,CAAC;YAC5C,MAAM;QACR,KAAK,UAAU;YACb,MAAM,CAAC,oBAAoB,EAAE,eAAe,CAAC,CAAC;YAC9C,MAAM;QACR,KAAK,OAAO;YACV,MAAM,CAAC,iBAAiB,EAAE,eAAe,CAAC,CAAC;YAC3C,MAAM;IACV,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,49 @@
1
+ import type { BuoyConfig } from "../config/schema.js";
2
+ import type { DesignToken, DriftSignal } from "@buoy-design/core";
3
+ export interface ProjectContext {
4
+ config: BuoyConfig;
5
+ projectRoot: string;
6
+ }
7
+ export declare function loadProject(cwd: string): Promise<ProjectContext>;
8
+ export interface TokenSummary {
9
+ name: string;
10
+ category: DesignToken["category"];
11
+ value: string;
12
+ source?: string;
13
+ deprecated?: boolean;
14
+ }
15
+ export declare function formatTokenValue(token: DesignToken): string;
16
+ export declare function summarizeToken(token: DesignToken): TokenSummary;
17
+ /** Normalise a CSS-ish value so `#FFF`, `#ffffff` and ` 8px ` compare equal. */
18
+ export declare function normalizeValue(value: string): string;
19
+ export declare function findTokensByValue(tokens: DesignToken[], value: string, category?: string): TokenSummary[];
20
+ export declare function scanTokens(project: ProjectContext): Promise<DesignToken[]>;
21
+ export interface DriftIssue {
22
+ file: string;
23
+ line?: number;
24
+ type: string;
25
+ severity: string;
26
+ message: string;
27
+ current?: unknown;
28
+ suggested?: string;
29
+ tokenSuggestions?: string[];
30
+ }
31
+ export declare function toIssue(drift: DriftSignal): DriftIssue;
32
+ export interface DriftCheck {
33
+ issues: DriftIssue[];
34
+ summary: {
35
+ total: number;
36
+ critical: number;
37
+ warning: number;
38
+ info: number;
39
+ fixable: number;
40
+ };
41
+ tokenCount: number;
42
+ }
43
+ /**
44
+ * With `files`: line-level literal values in those files, each matched to a
45
+ * token (fast, what an agent needs right after an edit). Without: the full
46
+ * repo analysis, which also covers components, unused tokens and contrast.
47
+ */
48
+ export declare function checkDrift(project: ProjectContext, files?: string[], tokens?: DesignToken[]): Promise<DriftCheck>;
49
+ //# sourceMappingURL=project.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/mcp/project.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAOtD,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAElE,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,UAAU,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAQtE;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAW3D;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,GAAG,YAAY,CAS/D;AAED,gFAAgF;AAChF,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMpD;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,YAAY,EAAE,CAMzG;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAIhF;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,WAAW,GAAG,UAAU,CActD;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7F,UAAU,EAAE,MAAM,CAAC;CACpB;AAgBD;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,EAAE,MAAM,CAAC,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAUvH"}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Project snapshot for the MCP server and the agent hook.
3
+ *
4
+ * Both need the same thing: this repo's tokens, and drift for some files.
5
+ * Everything here reuses the CLI's scan pipeline; nothing is re-detected.
6
+ */
7
+ import { dirname } from "node:path";
8
+ import { loadConfig, getConfigPath } from "../config/loader.js";
9
+ import { buildAutoConfig } from "../config/auto-detect.js";
10
+ import { ScanOrchestrator } from "../scan/orchestrator.js";
11
+ import { DriftAnalysisService } from "../services/drift-analysis.js";
12
+ import { filterScannableFiles } from "../commands/check.js";
13
+ import { checkFiles } from "./file-check.js";
14
+ export async function loadProject(cwd) {
15
+ const configPath = getConfigPath(cwd);
16
+ if (configPath) {
17
+ const loaded = await loadConfig(cwd);
18
+ return { config: loaded.config, projectRoot: loaded.configPath ? dirname(loaded.configPath) : cwd };
19
+ }
20
+ const auto = await buildAutoConfig(cwd);
21
+ return { config: auto.config, projectRoot: cwd };
22
+ }
23
+ export function formatTokenValue(token) {
24
+ const v = token.value;
25
+ switch (v.type) {
26
+ case "color": return v.hex;
27
+ case "spacing": return `${v.value}${v.unit}`;
28
+ case "typography": return `${v.fontFamily} ${v.fontSize}`;
29
+ case "shadow": return `${v.x}px ${v.y}px ${v.blur}px ${v.spread}px ${v.color}`;
30
+ case "border": return `${v.width}px ${v.style} ${v.color}`;
31
+ case "raw": return String(v.value);
32
+ default: return "(complex)";
33
+ }
34
+ }
35
+ export function summarizeToken(token) {
36
+ const source = "path" in token.source ? token.source.path : undefined;
37
+ return {
38
+ name: token.name,
39
+ category: token.category,
40
+ value: formatTokenValue(token),
41
+ ...(source ? { source } : {}),
42
+ ...(token.metadata?.deprecated ? { deprecated: true } : {}),
43
+ };
44
+ }
45
+ /** Normalise a CSS-ish value so `#FFF`, `#ffffff` and ` 8px ` compare equal. */
46
+ export function normalizeValue(value) {
47
+ let v = value.trim().toLowerCase().replace(/\s+/g, " ");
48
+ const shortHex = /^#([0-9a-f])([0-9a-f])([0-9a-f])$/.exec(v);
49
+ if (shortHex)
50
+ v = `#${shortHex[1]}${shortHex[1]}${shortHex[2]}${shortHex[2]}${shortHex[3]}${shortHex[3]}`;
51
+ v = v.replace(/(\d)\.0+(px|rem|em|%)?$/, "$1$2").replace(/^0(px|rem|em)$/, "0");
52
+ return v;
53
+ }
54
+ export function findTokensByValue(tokens, value, category) {
55
+ const wanted = normalizeValue(value);
56
+ return tokens
57
+ .filter((t) => !category || t.category === category)
58
+ .filter((t) => normalizeValue(formatTokenValue(t)) === wanted)
59
+ .map(summarizeToken);
60
+ }
61
+ export async function scanTokens(project) {
62
+ const orchestrator = new ScanOrchestrator(project.config, project.projectRoot);
63
+ const result = await orchestrator.scan();
64
+ return result.tokens;
65
+ }
66
+ export function toIssue(drift) {
67
+ const location = drift.source.location || "";
68
+ const [file, lineStr] = location.split(":");
69
+ const suggestions = drift.details?.suggestions;
70
+ return {
71
+ file: file || drift.source.entityName,
72
+ ...(lineStr ? { line: parseInt(lineStr, 10) } : {}),
73
+ type: drift.type,
74
+ severity: drift.severity,
75
+ message: drift.message,
76
+ ...(drift.details?.actual !== undefined ? { current: drift.details.actual } : {}),
77
+ ...(suggestions?.[0] ? { suggested: suggestions[0] } : typeof drift.details?.expected === "string" ? { suggested: drift.details.expected } : {}),
78
+ ...(drift.details?.tokenSuggestions?.length ? { tokenSuggestions: drift.details.tokenSuggestions } : {}),
79
+ };
80
+ }
81
+ function summarize(issues, tokenCount) {
82
+ return {
83
+ issues,
84
+ summary: {
85
+ total: issues.length,
86
+ critical: issues.filter((i) => i.severity === "critical").length,
87
+ warning: issues.filter((i) => i.severity === "warning").length,
88
+ info: issues.filter((i) => i.severity === "info").length,
89
+ fixable: issues.filter((i) => i.suggested || i.tokenSuggestions).length,
90
+ },
91
+ tokenCount,
92
+ };
93
+ }
94
+ /**
95
+ * With `files`: line-level literal values in those files, each matched to a
96
+ * token (fast, what an agent needs right after an edit). Without: the full
97
+ * repo analysis, which also covers components, unused tokens and contrast.
98
+ */
99
+ export async function checkDrift(project, files, tokens) {
100
+ if (files && files.length > 0) {
101
+ const scannable = filterScannableFiles(files);
102
+ const known = tokens ?? (await scanTokens(project));
103
+ const issues = scannable.length ? await checkFiles(scannable, project.projectRoot, known) : [];
104
+ return summarize(issues, known.length);
105
+ }
106
+ const service = new DriftAnalysisService(project.config, project.projectRoot);
107
+ const result = await service.analyze({ includeIgnored: false });
108
+ return summarize(result.drifts.map(toIssue), result.tokenCount);
109
+ }
110
+ //# sourceMappingURL=project.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/mcp/project.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * `buoy mcp serve`: a stdio MCP server that gives coding agents this repo's
3
+ * design tokens and drift checks, so hardcoded values are caught while the
4
+ * agent writes instead of on the PR.
5
+ */
6
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
7
+ export interface BuoyMcpOptions {
8
+ cwd: string;
9
+ version: string;
10
+ }
11
+ export declare function createBuoyMcpServer(options: BuoyMcpOptions): McpServer;
12
+ export declare function serveStdio(options: BuoyMcpOptions): Promise<void>;
13
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAiBpE,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,cAAc,GAAG,SAAS,CA4GtE;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAGvE"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * `buoy mcp serve`: a stdio MCP server that gives coding agents this repo's
3
+ * design tokens and drift checks, so hardcoded values are caught while the
4
+ * agent writes instead of on the PR.
5
+ */
6
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
7
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
8
+ import { z } from "zod";
9
+ import { generateContext } from "../services/context-generator.js";
10
+ import { ScanOrchestrator } from "../scan/orchestrator.js";
11
+ import { checkDrift, findTokensByValue, loadProject, scanTokens, summarizeToken, } from "./project.js";
12
+ const TOKEN_CACHE_MS = 30_000;
13
+ export function createBuoyMcpServer(options) {
14
+ const server = new McpServer({ name: "buoy", version: options.version });
15
+ let project = null;
16
+ let tokenCache = null;
17
+ const getProject = async () => (project ??= await loadProject(options.cwd));
18
+ const getTokens = async () => {
19
+ if (tokenCache && Date.now() - tokenCache.at < TOKEN_CACHE_MS)
20
+ return tokenCache.tokens;
21
+ const tokens = await scanTokens(await getProject());
22
+ tokenCache = { at: Date.now(), tokens };
23
+ return tokens;
24
+ };
25
+ const json = (value) => ({ content: [{ type: "text", text: JSON.stringify(value, null, 2) }] });
26
+ server.registerTool("list_design_tokens", {
27
+ title: "List design tokens",
28
+ description: "The design tokens defined in this repository (CSS custom properties, Tailwind theme, tokens.json, SCSS variables). Call this before writing any CSS, inline style or Tailwind class so you use an existing token instead of a literal value. Filter by category (color, spacing, typography, shadow, border, sizing, motion, zIndex) or a name substring.",
29
+ inputSchema: {
30
+ category: z.string().optional().describe("Only tokens in this category"),
31
+ query: z.string().optional().describe("Case-insensitive substring of the token name"),
32
+ limit: z.number().int().positive().max(500).optional().describe("Max tokens to return (default 200)"),
33
+ },
34
+ }, async ({ category, query, limit }) => {
35
+ const tokens = await getTokens();
36
+ const q = query?.toLowerCase();
37
+ const matched = tokens
38
+ .filter((t) => !category || t.category === category)
39
+ .filter((t) => !q || t.name.toLowerCase().includes(q));
40
+ const byCategory = {};
41
+ for (const t of tokens)
42
+ byCategory[t.category] = (byCategory[t.category] ?? 0) + 1;
43
+ return json({
44
+ total: tokens.length,
45
+ byCategory,
46
+ matched: matched.length,
47
+ tokens: matched.slice(0, limit ?? 200).map(summarizeToken),
48
+ ...(tokens.length === 0 ? { note: "No tokens found. Run `buoy dock tokens` to extract a token set from the values this codebase already uses." } : {}),
49
+ });
50
+ });
51
+ server.registerTool("find_token_for_value", {
52
+ title: "Find the token for a literal value",
53
+ description: "Given a literal CSS value you are about to write (for example '#1a73e8', '16px', '0.5rem'), return the design tokens in this repository that have exactly that value. Use the token instead of the literal. An empty result means there is no token for it; prefer the nearest token from list_design_tokens over inventing a new value.",
54
+ inputSchema: {
55
+ value: z.string().describe("The literal value, e.g. '#ffffff' or '8px'"),
56
+ category: z.string().optional().describe("Restrict to a category such as color or spacing"),
57
+ },
58
+ }, async ({ value, category }) => {
59
+ const matches = findTokensByValue(await getTokens(), value, category);
60
+ return json({ value, matches, suggestion: matches[0] ? `Use ${matches[0].name} instead of ${value}` : null });
61
+ });
62
+ server.registerTool("check_design_drift", {
63
+ title: "Check files for design drift",
64
+ description: "Run Buoy's drift analysis and return hardcoded values, unknown tokens and inconsistent components, each with the token to use instead when one exists. Pass the files you just edited to check only those; omit files for the whole repository. Run this after editing styles and fix every issue that has a suggestion.",
65
+ inputSchema: {
66
+ files: z.array(z.string()).optional().describe("Repository-relative or absolute paths to limit the check to"),
67
+ },
68
+ }, async ({ files }) => {
69
+ const result = await checkDrift(await getProject(), files, files?.length ? await getTokens() : undefined);
70
+ return json({
71
+ ...result,
72
+ instructions: result.issues.length === 0
73
+ ? "No design drift in the checked files."
74
+ : "Replace each `current` value with `suggested` (or one of `tokenSuggestions`), then run check_design_drift again.",
75
+ });
76
+ });
77
+ server.registerTool("design_system_context", {
78
+ title: "Design system overview",
79
+ description: "A Markdown summary of this repository's design system: token categories with example names, the component library, and the anti-patterns Buoy flags. Read it once at the start of a task that touches UI.",
80
+ inputSchema: {
81
+ detail: z.enum(["minimal", "standard", "comprehensive"]).optional().describe("How much to include (default standard)"),
82
+ },
83
+ }, async ({ detail }) => {
84
+ const proj = await getProject();
85
+ const orchestrator = new ScanOrchestrator(proj.config, proj.projectRoot);
86
+ const scan = await orchestrator.scan();
87
+ const { SemanticDiffEngine } = await import("@buoy-design/core/analysis");
88
+ const diff = new SemanticDiffEngine().analyzeComponents(scan.components, { availableTokens: scan.tokens });
89
+ const result = generateContext({ tokens: scan.tokens, components: scan.components, drifts: diff.drifts, projectName: proj.projectRoot.split("/").pop() || "project" }, { detailLevel: detail ?? "standard" });
90
+ return { content: [{ type: "text", text: result.content }] };
91
+ });
92
+ return server;
93
+ }
94
+ export async function serveStdio(options) {
95
+ const server = createBuoyMcpServer(options);
96
+ await server.connect(new StdioServerTransport());
97
+ }
98
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EACL,UAAU,EACV,iBAAiB,EACjB,WAAW,EACX,UAAU,EACV,cAAc,GAEf,MAAM,cAAc,CAAC;AAEtB,MAAM,cAAc,GAAG,MAAM,CAAC;AAO9B,MAAM,UAAU,mBAAmB,CAAC,OAAuB;IACzD,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAEzE,IAAI,OAAO,GAA0B,IAAI,CAAC;IAC1C,IAAI,UAAU,GAAiD,IAAI,CAAC;IAEpE,MAAM,UAAU,GAAG,KAAK,IAAI,EAAE,CAAC,CAAC,OAAO,KAAK,MAAM,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5E,MAAM,SAAS,GAAG,KAAK,IAAI,EAAE;QAC3B,IAAI,UAAU,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC,EAAE,GAAG,cAAc;YAAE,OAAO,UAAU,CAAC,MAAM,CAAC;QACxF,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,MAAM,UAAU,EAAE,CAAC,CAAC;QACpD,UAAU,GAAG,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,CAAC;QACxC,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;IACF,MAAM,IAAI,GAAG,CAAC,KAAc,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAElH,MAAM,CAAC,YAAY,CACjB,oBAAoB,EACpB;QACE,KAAK,EAAE,oBAAoB;QAC3B,WAAW,EACT,2VAA2V;QAC7V,WAAW,EAAE;YACX,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,8BAA8B,CAAC;YACxE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,8CAA8C,CAAC;YACrF,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,oCAAoC,CAAC;SACtG;KACF,EACD,KAAK,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE;QACnC,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;QACjC,MAAM,CAAC,GAAG,KAAK,EAAE,WAAW,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,MAAM;aACnB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC;aACnD,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QACzD,MAAM,UAAU,GAA2B,EAAE,CAAC;QAC9C,KAAK,MAAM,CAAC,IAAI,MAAM;YAAE,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QACnF,OAAO,IAAI,CAAC;YACV,KAAK,EAAE,MAAM,CAAC,MAAM;YACpB,UAAU;YACV,OAAO,EAAE,OAAO,CAAC,MAAM;YACvB,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC;YAC1D,GAAG,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,4GAA4G,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACvJ,CAAC,CAAC;IACL,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,sBAAsB,EACtB;QACE,KAAK,EAAE,oCAAoC;QAC3C,WAAW,EACT,0UAA0U;QAC5U,WAAW,EAAE;YACX,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,4CAA4C,CAAC;YACxE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,iDAAiD,CAAC;SAC5F;KACF,EACD,KAAK,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE;QAC5B,MAAM,OAAO,GAAG,iBAAiB,CAAC,MAAM,SAAS,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;QACtE,OAAO,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,eAAe,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAChH,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,oBAAoB,EACpB;QACE,KAAK,EAAE,8BAA8B;QACrC,WAAW,EACT,0TAA0T;QAC5T,WAAW,EAAE;YACX,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6DAA6D,CAAC;SAC9G;KACF,EACD,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;QAClB,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,MAAM,UAAU,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,SAAS,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAC1G,OAAO,IAAI,CAAC;YACV,GAAG,MAAM;YACT,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;gBACtC,CAAC,CAAC,uCAAuC;gBACzC,CAAC,CAAC,kHAAkH;SACvH,CAAC,CAAC;IACL,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,uBAAuB,EACvB;QACE,KAAK,EAAE,wBAAwB;QAC/B,WAAW,EACT,2MAA2M;QAC7M,WAAW,EAAE;YACX,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,UAAU,EAAE,eAAe,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,wCAAwC,CAAC;SACvH;KACF,EACD,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;QACnB,MAAM,IAAI,GAAG,MAAM,UAAU,EAAE,CAAC;QAChC,MAAM,YAAY,GAAG,IAAI,gBAAgB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QACzE,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,CAAC;QACvC,MAAM,EAAE,kBAAkB,EAAE,GAAG,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;QAC1E,MAAM,IAAI,GAAG,IAAI,kBAAkB,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,eAAe,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QAC3G,MAAM,MAAM,GAAG,eAAe,CAC5B,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,SAAS,EAAE,EACtI,EAAE,WAAW,EAAE,MAAM,IAAI,UAAU,EAAE,CACtC,CAAC;QACF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;IACxE,CAAC,CACF,CAAC;IAEF,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAAuB;IACtD,MAAM,MAAM,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC5C,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,oBAAoB,EAAE,CAAC,CAAC;AACnD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buoy-design/cli",
3
- "version": "0.6.1",
3
+ "version": "0.7.0",
4
4
  "description": "Catch design drift before it ships",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -35,6 +35,7 @@
35
35
  "@anthropic-ai/sdk": "^0.71.2",
36
36
  "@google/design.md": "0.1.1",
37
37
  "@inquirer/prompts": "^8.1.0",
38
+ "@modelcontextprotocol/sdk": "^1.30.0",
38
39
  "@octokit/rest": "^21.0.0",
39
40
  "chalk": "^5.3.0",
40
41
  "cli-table3": "^0.6.5",
@@ -47,8 +48,8 @@
47
48
  "yaml": "^2.8.2",
48
49
  "zod": "^3.24.1",
49
50
  "zod-validation-error": "^5.0.0",
50
- "@buoy-design/core": "0.6.1",
51
- "@buoy-design/scanners": "0.6.1"
51
+ "@buoy-design/core": "0.7.0",
52
+ "@buoy-design/scanners": "0.7.0"
52
53
  },
53
54
  "devDependencies": {
54
55
  "@types/node": "^22.10.2",