@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 +7 -3
- package/dist/index.js +54 -14
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
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
|
|
1775
|
-
|
|
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.
|
|
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
|
|
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) => !
|
|
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 (
|
|
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
|
|
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
|
|
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:
|
|
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:
|
|
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
|
|
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) => !
|
|
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 (
|
|
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.
|
|
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
|
]
|