@atomixstudio/mcp 1.0.19 → 1.0.21

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,
@@ -1771,8 +1810,8 @@ function hasValidAuthConfig() {
1771
1810
  }
1772
1811
  var AUTH_REQUIRED_MESSAGE = "Atomix MCP requires authentication. Add both --ds-id and --atomix-token to your MCP config (Settings \u2192 MCP), then restart Cursor. Get your token from Atomix Studio: Export modal or Settings \u2192 Regenerate Atomix access token.";
1773
1812
  var lastChangeSummary = null;
1774
- var FIGMA_TOOL_NAMES = /* @__PURE__ */ new Set([
1775
- "syncToFigma",
1813
+ var FIGMA_SYNC_TOOL_NAME = "syncToFigma";
1814
+ var FIGMA_DESIGN_TOOL_NAMES = /* @__PURE__ */ new Set([
1776
1815
  "getFigmaVariablesAndStyles",
1777
1816
  "createDesignPlaceholder",
1778
1817
  "resolveFigmaIdsForTokens",
@@ -1785,6 +1824,7 @@ var FIGMA_TOOL_NAMES = /* @__PURE__ */ new Set([
1785
1824
  "getDesignScreenshot",
1786
1825
  "finalizeDesignFrame"
1787
1826
  ]);
1827
+ var FIGMA_TOOL_NAMES = /* @__PURE__ */ new Set([FIGMA_SYNC_TOOL_NAME, ...FIGMA_DESIGN_TOOL_NAMES]);
1788
1828
  var lastSyncAffectedTokens = null;
1789
1829
  function getLastChangeSummary() {
1790
1830
  return lastChangeSummary;
@@ -1821,7 +1861,7 @@ var TOKEN_CATEGORIES = ["colors", "typography", "spacing", "sizing", "shadows",
1821
1861
  var server = new Server(
1822
1862
  {
1823
1863
  name: "atomix-mcp-user",
1824
- version: "1.0.19"
1864
+ version: "1.0.21"
1825
1865
  },
1826
1866
  {
1827
1867
  capabilities: {
@@ -1844,7 +1884,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
1844
1884
  console.error("[Atomix MCP] Resolved tier = pro. Figma sync/design tools are available.");
1845
1885
  } else if (cachedMcpTier === "free") {
1846
1886
  console.error(
1847
- "[Atomix MCP] Resolved tier = free. Figma sync/design tools are hidden. Pro tools appear when the DS owner has Pro and the pro_figma_export flag is enabled."
1887
+ "[Atomix MCP] Resolved tier = free. Figma design tools and --design-in-figma are hidden. syncToFigma and /--sync-to-figma are available. Pro design tools appear when the DS owner has Pro and the pro_figma_export flag is enabled."
1848
1888
  );
1849
1889
  }
1850
1890
  } catch (err) {
@@ -2173,7 +2213,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
2173
2213
  }
2174
2214
  }
2175
2215
  ];
2176
- const tools = cachedMcpTier === "pro" ? toolsList : toolsList.filter((t) => !FIGMA_TOOL_NAMES.has(t.name));
2216
+ const tools = cachedMcpTier === "pro" ? toolsList : toolsList.filter((t) => !FIGMA_DESIGN_TOOL_NAMES.has(t.name));
2177
2217
  return { tools };
2178
2218
  });
2179
2219
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
@@ -2190,12 +2230,12 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
2190
2230
  try {
2191
2231
  const shouldForceRefresh = name === "syncAll";
2192
2232
  const data = await fetchDesignSystemForMCP(shouldForceRefresh);
2193
- if (FIGMA_TOOL_NAMES.has(name) && cachedMcpTier !== "pro") {
2233
+ if (FIGMA_DESIGN_TOOL_NAMES.has(name) && cachedMcpTier !== "pro") {
2194
2234
  return {
2195
2235
  content: [
2196
2236
  {
2197
2237
  type: "text",
2198
- text: "This design system does not have Pro Figma access. Figma sync and design tools are available when the design system owner has a Pro subscription."
2238
+ text: "This design system does not have Pro Figma access. Figma design tools (design-in-Figma, createDesignPlaceholder, resolveFigmaIdsForTokens, etc.) are available when the design system owner has a Pro subscription. Sync to Figma (syncToFigma) is available on all tiers."
2199
2239
  }
2200
2240
  ],
2201
2241
  isError: true
@@ -2755,7 +2795,7 @@ ${tokenResponseText}` : summary;
2755
2795
  };
2756
2796
  }
2757
2797
  case "getDependencies": {
2758
- const platform = args?.platform;
2798
+ const platform2 = args?.platform;
2759
2799
  const stack = args?.stack;
2760
2800
  const tokens = data.tokens;
2761
2801
  const typography = tokens?.typography;
@@ -2799,14 +2839,14 @@ ${tokenResponseText}` : summary;
2799
2839
  files: ["tokens.css", "tokens.json"],
2800
2840
  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
2841
  },
2802
- showcase: platform === "web" || !platform ? {
2842
+ showcase: platform2 === "web" || !platform2 ? {
2803
2843
  path: "atomix-setup-showcase.html",
2804
2844
  template: SHOWCASE_HTML_TEMPLATE,
2805
2845
  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
2846
  } : void 0,
2807
2847
  meta: {
2808
2848
  dsName: data.meta.name,
2809
- platform: platform ?? void 0,
2849
+ platform: platform2 ?? void 0,
2810
2850
  stack: stack ?? void 0,
2811
2851
  designSystemVersion: data.meta.version ?? "1.0.0",
2812
2852
  designSystemExportedAt: data.meta.exportedAt
@@ -3456,7 +3496,7 @@ Get your DS ID and token from the Export modal or Settings \u2192 Regenerate Ato
3456
3496
  }
3457
3497
  throw new Error(`Unknown resource: ${uri}`);
3458
3498
  });
3459
- var FIGMA_PROMPT_NAMES = /* @__PURE__ */ new Set(["--sync-to-figma", "--design-in-figma"]);
3499
+ var FIGMA_DESIGN_PROMPT_NAMES = /* @__PURE__ */ new Set(["--design-in-figma"]);
3460
3500
  server.setRequestHandler(ListPromptsRequestSchema, async () => {
3461
3501
  if (!hasValidAuthConfig()) {
3462
3502
  authFailedNoTools = true;
@@ -3481,7 +3521,7 @@ server.setRequestHandler(ListPromptsRequestSchema, async () => {
3481
3521
  { name: "--sync-to-figma", description: "Push this design system to Figma (variables, color + typography styles). Uses local bridge + plugin; no Figma token." },
3482
3522
  { name: "--design-in-figma", description: "Design UI in Figma: 3 passes (wireframe \u2192 tokens/rules \u2192 audit), getDesignScreenshot after each pass, then finalizeDesignFrame (rename + \u2705, remove placeholder) and summarise." }
3483
3523
  ];
3484
- const prompts = cachedMcpTier === "pro" ? allPrompts : allPrompts.filter((p) => !FIGMA_PROMPT_NAMES.has(p.name));
3524
+ const prompts = cachedMcpTier === "pro" ? allPrompts : allPrompts.filter((p) => !FIGMA_DESIGN_PROMPT_NAMES.has(p.name));
3485
3525
  return { prompts };
3486
3526
  });
3487
3527
  server.setRequestHandler(GetPromptRequestSchema, async (request) => {
@@ -3583,7 +3623,7 @@ Both are required. Configure the MCP server in your Cursor settings, then restar
3583
3623
  }
3584
3624
  throw error;
3585
3625
  }
3586
- if (FIGMA_PROMPT_NAMES.has(name) && cachedMcpTier !== "pro") {
3626
+ if (FIGMA_DESIGN_PROMPT_NAMES.has(name) && cachedMcpTier !== "pro") {
3587
3627
  return {
3588
3628
  description: "Pro Figma required",
3589
3629
  messages: [
@@ -3591,7 +3631,7 @@ Both are required. Configure the MCP server in your Cursor settings, then restar
3591
3631
  role: "user",
3592
3632
  content: {
3593
3633
  type: "text",
3594
- text: "This design system does not have Pro Figma access. Figma sync and design prompts are available when the design system owner has a Pro subscription."
3634
+ text: "This design system does not have Pro Figma access. The design-in-Figma prompt is available when the design system owner has a Pro subscription. Sync to Figma (/--sync-to-figma) is available on all tiers."
3595
3635
  }
3596
3636
  }
3597
3637
  ]