@atomixstudio/mcp 1.0.19 → 1.0.20

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.
package/README.md CHANGED
@@ -65,7 +65,9 @@ Once connected, the AI can call these tools:
65
65
  | `exportMCPConfig(tool)` | Get MCP configuration for different tools |
66
66
  | `getSetupInstructions(tool)` | Get detailed setup guide |
67
67
  | `getDependencies(platform?, stack?)` | Get suggested dependencies (icons, fonts, SKILL.md, token files). Optional: `platform` (web, ios, android), `stack` (e.g. react, vue, next). Use with **/--get-started** prompt. |
68
- | `syncToFigma()` | Push design system to Figma (variables, paint styles, text styles, effect styles). Uses built-in bridge + Atomix plugin. If the plugin is not connected, the response includes `agentInstruction` to connect. |
68
+ | `syncToFigma()` | Push design system to Figma (variables, paint styles, text styles, effect styles). Uses built-in bridge + Atomix plugin. If the plugin is not connected, the response includes `agentInstruction` to connect. **Available on all tiers (Free and Pro).** |
69
+
70
+ Other Figma tools (getFigmaVariablesAndStyles, createDesignPlaceholder, resolveFigmaIdsForTokens, designCreateFrame, designCreateText, etc.) are **Pro only** — they appear when the design system owner has a Pro subscription.
69
71
 
70
72
  ### getDependencies
71
73
 
@@ -101,8 +103,8 @@ Run these prompts from your AI tool (e.g. **/--hello**, **/--get-started**):
101
103
  | **/--rules** | Governance rules for your AI tool (Cursor, Copilot, Windsurf, etc.). |
102
104
  | **/--sync** | Sync tokens, AI rules, skills files, and dependencies manifest (icons, fonts). Use **/--refactor** to migrate deprecated tokens. |
103
105
  | **/--refactor** | Migrate deprecated tokens in codebase. Run after **/--sync**. |
104
- | **/--sync-to-figma** | Push design system to Figma. Requires bridge + Atomix plugin; see [Sync to Figma](#sync-to-figma) below. |
105
- | **/--design-in-figma** | Design UI in Figma: **3 passes** (wireframe → tokens/rules → audit), **getDesignScreenshot** after each pass, then **finalizeDesignFrame** (rename + ✅, remove placeholder) and summarise. No code generation. |
106
+ | **/--sync-to-figma** | Push design system to Figma. Requires bridge + Atomix plugin; see [Sync to Figma](#sync-to-figma) below. **Available on all tiers (Free and Pro).** |
107
+ | **/--design-in-figma** | Design UI in Figma: **3 passes** (wireframe → tokens/rules → audit), **getDesignScreenshot** after each pass, then **finalizeDesignFrame** (rename + ✅, remove placeholder) and summarise. No code generation. **Pro only.** |
106
108
 
107
109
  ## --get-started (get started)
108
110
 
@@ -123,6 +125,8 @@ The **/--get-started** prompt suggests dependencies for your design system so yo
123
125
 
124
126
  **/--sync-to-figma** (or the **syncToFigma** tool) pushes your design system into the open Figma file: color variables, paint styles, number variables (spacing, radius, borders, sizing, breakpoints), text styles, and shadow effect styles. The **Figma bridge runs inside this MCP server** (no separate process). You only need the Atomix Figma plugin and "Connect to Cursor" (no Figma REST API or token).
125
127
 
128
+ **Tier:** Sync to Figma is available on **all tiers** (Free and Pro). The design-in-Figma prompt and design tools (getFigmaVariablesAndStyles, createDesignPlaceholder, resolveFigmaIdsForTokens, designCreateFrame, etc.) require a **Pro** subscription for the design system owner.
129
+
126
130
  **Flow:**
127
131
 
128
132
  1. **Plugin not connected?** The tool checks first. If the plugin is not connected, the response includes `bridgeNotRunning`, `agentInstruction`, and `userInstruction`. Ensure Cursor has this MCP server running, then in Figma run the Atomix plugin and click **Connect to Cursor**, then call **syncToFigma** again.
package/dist/index.js CHANGED
@@ -1291,6 +1291,8 @@ function getTokenStats(data) {
1291
1291
  // src/index.ts
1292
1292
  import * as path2 from "path";
1293
1293
  import * as fs2 from "fs";
1294
+ import { execSync } from "child_process";
1295
+ import { platform } from "os";
1294
1296
  import WebSocket, { WebSocketServer } from "ws";
1295
1297
  var FIGMA_BRIDGE_PORT = Number(process.env.FIGMA_BRIDGE_PORT) || 8765;
1296
1298
  var FIGMA_BRIDGE_HOST = process.env.FIGMA_BRIDGE_HOST || "127.0.0.1";
@@ -1304,9 +1306,46 @@ var FIGMA_CONNECTION_INSTRUCTIONS = {
1304
1306
  var bridgeWss = null;
1305
1307
  var pluginWs = null;
1306
1308
  var pendingBridgeRequests = /* @__PURE__ */ new Map();
1309
+ function ensureFigmaBridgePortFree(port) {
1310
+ const portStr = String(port);
1311
+ const ourPid = String(process.pid);
1312
+ try {
1313
+ if (platform() === "win32") {
1314
+ const out = execSync(`netstat -ano`, { encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] });
1315
+ const pids = /* @__PURE__ */ new Set();
1316
+ for (const line of out.split(/\r?\n/)) {
1317
+ if (line.includes(`:${portStr}`) && line.includes("LISTENING")) {
1318
+ const parts = line.trim().split(/\s+/);
1319
+ const pid = parts[parts.length - 1];
1320
+ if (/^\d+$/.test(pid) && pid !== ourPid) pids.add(pid);
1321
+ }
1322
+ }
1323
+ for (const pid of pids) {
1324
+ try {
1325
+ execSync(`taskkill /PID ${pid} /F`, { encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] });
1326
+ console.error(`[atomix-mcp] Freed Figma bridge port ${port} (killed PID ${pid})`);
1327
+ } catch (_) {
1328
+ }
1329
+ }
1330
+ } else {
1331
+ const out = execSync(`lsof -ti :${portStr}`, { encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] }).trim();
1332
+ if (!out) return;
1333
+ const pids = out.split(/\s+/).filter((p) => p && p !== ourPid);
1334
+ for (const pid of pids) {
1335
+ try {
1336
+ execSync(`kill -9 ${pid}`, { encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] });
1337
+ console.error(`[atomix-mcp] Freed Figma bridge port ${port} (killed PID ${pid})`);
1338
+ } catch (_) {
1339
+ }
1340
+ }
1341
+ }
1342
+ } catch {
1343
+ }
1344
+ }
1307
1345
  function startFigmaBridge() {
1308
1346
  if (bridgeWss) return;
1309
1347
  try {
1348
+ ensureFigmaBridgePortFree(FIGMA_BRIDGE_PORT);
1310
1349
  bridgeWss = new WebSocketServer({
1311
1350
  host: FIGMA_BRIDGE_HOST,
1312
1351
  port: FIGMA_BRIDGE_PORT,
@@ -2755,7 +2794,7 @@ ${tokenResponseText}` : summary;
2755
2794
  };
2756
2795
  }
2757
2796
  case "getDependencies": {
2758
- const platform = args?.platform;
2797
+ const platform2 = args?.platform;
2759
2798
  const stack = args?.stack;
2760
2799
  const tokens = data.tokens;
2761
2800
  const typography = tokens?.typography;
@@ -2799,14 +2838,14 @@ ${tokenResponseText}` : summary;
2799
2838
  files: ["tokens.css", "tokens.json"],
2800
2839
  copyInstructions: "Call the syncAll MCP tool to create the token file, skills, and atomix-dependencies.json; do not only suggest the user run sync later."
2801
2840
  },
2802
- showcase: platform === "web" || !platform ? {
2841
+ showcase: platform2 === "web" || !platform2 ? {
2803
2842
  path: "atomix-setup-showcase.html",
2804
2843
  template: SHOWCASE_HTML_TEMPLATE,
2805
2844
  substitutionInstructions: "Replace placeholders with values from the synced token file. MCP/sync/export use the --atmx- prefix. {{TOKENS_CSS_PATH}} = path to the synced token file (e.g. ./tokens.css, same as syncAll output). {{DS_NAME}} = design system name. {{BRAND_PRIMARY_VAR}} = var(--atmx-color-brand-primary). {{BRAND_PRIMARY_FOREGROUND_VAR}} = var(--atmx-color-brand-primary-foreground). {{HEADING_FONT_VAR}} = var(--atmx-typography-font-family-heading) or var(--atmx-typography-font-family-display). {{FONT_FAMILY_VAR}} = var(--atmx-typography-font-family-body). {{FONT_LINK_TAG}} = Google Fonts <link> for the font, or empty string. Do not invent CSS variable names; use only vars that exist in the export."
2806
2845
  } : void 0,
2807
2846
  meta: {
2808
2847
  dsName: data.meta.name,
2809
- platform: platform ?? void 0,
2848
+ platform: platform2 ?? void 0,
2810
2849
  stack: stack ?? void 0,
2811
2850
  designSystemVersion: data.meta.version ?? "1.0.0",
2812
2851
  designSystemExportedAt: data.meta.exportedAt