@atomixstudio/mcp 1.0.20 → 1.0.22
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/dist/{chunk-FFAGTYRZ.js → chunk-BXWOCXYT.js} +2 -1
- package/dist/chunk-BXWOCXYT.js.map +1 -0
- package/dist/figma-bridge-protocol.d.ts +1 -1
- package/dist/figma-bridge-protocol.js +1 -1
- package/dist/index.js +122 -34
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-FFAGTYRZ.js.map +0 -1
|
@@ -10,6 +10,7 @@ var BRIDGE_METHODS = [
|
|
|
10
10
|
"create_paint_styles",
|
|
11
11
|
"create_text_styles",
|
|
12
12
|
"create_number_variables",
|
|
13
|
+
"create_effect_styles",
|
|
13
14
|
"apply_fill_to_selection",
|
|
14
15
|
"create_design_placeholder",
|
|
15
16
|
"design_create_frame",
|
|
@@ -41,4 +42,4 @@ export {
|
|
|
41
42
|
normalizeBridgeMethod,
|
|
42
43
|
isAllowedMethod
|
|
43
44
|
};
|
|
44
|
-
//# sourceMappingURL=chunk-
|
|
45
|
+
//# sourceMappingURL=chunk-BXWOCXYT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/figma-bridge-protocol.ts"],"sourcesContent":["/**\n * Bridge wire protocol (merged from figma-bridge).\n * All messages are JSON. Only whitelisted methods are allowed.\n * Used by the in-process Figma bridge (WebSocket server in mcp-user).\n */\n\nexport const BRIDGE_METHODS = [\n \"get_document_info\",\n \"get_selection\",\n \"get_node_info\",\n \"get_figma_variables_and_styles\",\n \"create_color_variables\",\n \"create_paint_styles\",\n \"create_text_styles\",\n \"create_number_variables\",\n \"create_effect_styles\",\n \"apply_fill_to_selection\",\n \"create_design_placeholder\",\n \"design_create_frame\",\n \"design_create_text\",\n \"design_create_rectangle\",\n \"design_set_auto_layout\",\n \"design_set_layout_constraints\",\n \"design_append_child\",\n \"get_design_screenshot\",\n \"finalize_design_frame\",\n] as const;\n\nexport type BridgeMethod = (typeof BRIDGE_METHODS)[number];\n\nexport interface BridgeRequest {\n id: string;\n method: string;\n params?: Record<string, unknown>;\n}\n\nexport interface BridgeSuccessResponse {\n id: string;\n result: unknown;\n}\n\nexport interface BridgeErrorResponse {\n id: string;\n error: string;\n}\n\nexport type BridgeResponse = BridgeSuccessResponse | BridgeErrorResponse;\n\nexport function isBridgeRequest(msg: unknown): msg is BridgeRequest {\n if (!msg || typeof msg !== \"object\") return false;\n const m = msg as Record<string, unknown>;\n return (\n typeof m.id === \"string\" &&\n m.id.length > 0 &&\n typeof m.method === \"string\" &&\n m.method.length > 0\n );\n}\n\n/** Convert camelCase to snake_case for bridge (e.g. getFigmaVariablesAndStyles -> get_figma_variables_and_styles). */\nexport function normalizeBridgeMethod(method: string): string {\n if (typeof method !== \"string\" || !method) return method;\n return method.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);\n}\n\nexport function isAllowedMethod(method: string): method is BridgeMethod {\n const normalized = normalizeBridgeMethod(method);\n return (BRIDGE_METHODS as readonly string[]).includes(normalized);\n}\n"],"mappings":";;;AAMO,IAAM,iBAAiB;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAsBO,SAAS,gBAAgB,KAAoC;AAClE,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,QAAM,IAAI;AACV,SACE,OAAO,EAAE,OAAO,YAChB,EAAE,GAAG,SAAS,KACd,OAAO,EAAE,WAAW,YACpB,EAAE,OAAO,SAAS;AAEtB;AAGO,SAAS,sBAAsB,QAAwB;AAC5D,MAAI,OAAO,WAAW,YAAY,CAAC,OAAQ,QAAO;AAClD,SAAO,OAAO,QAAQ,UAAU,CAAC,MAAM,IAAI,EAAE,YAAY,CAAC,EAAE;AAC9D;AAEO,SAAS,gBAAgB,QAAwC;AACtE,QAAM,aAAa,sBAAsB,MAAM;AAC/C,SAAQ,eAAqC,SAAS,UAAU;AAClE;","names":[]}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* All messages are JSON. Only whitelisted methods are allowed.
|
|
4
4
|
* Used by the in-process Figma bridge (WebSocket server in mcp-user).
|
|
5
5
|
*/
|
|
6
|
-
declare const BRIDGE_METHODS: readonly ["get_document_info", "get_selection", "get_node_info", "get_figma_variables_and_styles", "create_color_variables", "create_paint_styles", "create_text_styles", "create_number_variables", "apply_fill_to_selection", "create_design_placeholder", "design_create_frame", "design_create_text", "design_create_rectangle", "design_set_auto_layout", "design_set_layout_constraints", "design_append_child", "get_design_screenshot", "finalize_design_frame"];
|
|
6
|
+
declare const BRIDGE_METHODS: readonly ["get_document_info", "get_selection", "get_node_info", "get_figma_variables_and_styles", "create_color_variables", "create_paint_styles", "create_text_styles", "create_number_variables", "create_effect_styles", "apply_fill_to_selection", "create_design_placeholder", "design_create_frame", "design_create_text", "design_create_rectangle", "design_set_auto_layout", "design_set_layout_constraints", "design_append_child", "get_design_screenshot", "finalize_design_frame"];
|
|
7
7
|
type BridgeMethod = (typeof BRIDGE_METHODS)[number];
|
|
8
8
|
interface BridgeRequest {
|
|
9
9
|
id: string;
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
isAllowedMethod,
|
|
4
4
|
normalizeBridgeMethod
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-BXWOCXYT.js";
|
|
6
6
|
|
|
7
7
|
// src/index.ts
|
|
8
8
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -1480,6 +1480,25 @@ function figmaColorNameWithGroup(key) {
|
|
|
1480
1480
|
const groupDisplay = group.charAt(0).toUpperCase() + group.slice(1).toLowerCase();
|
|
1481
1481
|
return `${groupDisplay} / ${name}`;
|
|
1482
1482
|
}
|
|
1483
|
+
var FIGMA_COLOR_GROUP_ORDER = {
|
|
1484
|
+
background: 0,
|
|
1485
|
+
text: 1,
|
|
1486
|
+
border: 2,
|
|
1487
|
+
icon: 3,
|
|
1488
|
+
brand: 4,
|
|
1489
|
+
action: 5,
|
|
1490
|
+
feedback: 6
|
|
1491
|
+
};
|
|
1492
|
+
var FIGMA_SHADOW_ORDER = {
|
|
1493
|
+
none: 0,
|
|
1494
|
+
xs: 1,
|
|
1495
|
+
sm: 2,
|
|
1496
|
+
md: 3,
|
|
1497
|
+
lg: 4,
|
|
1498
|
+
xl: 5,
|
|
1499
|
+
"2xl": 6,
|
|
1500
|
+
focus: 7
|
|
1501
|
+
};
|
|
1483
1502
|
function tokenValueToNumber(s) {
|
|
1484
1503
|
if (typeof s !== "string" || !s.trim()) return 0;
|
|
1485
1504
|
const t = s.trim();
|
|
@@ -1593,6 +1612,25 @@ function buildFigmaPayloadsFromDS(data) {
|
|
|
1593
1612
|
}
|
|
1594
1613
|
}
|
|
1595
1614
|
if (variables.length === 0 && modes.length === 0) modes.push("Light");
|
|
1615
|
+
const colorSortKey = (figmaName) => {
|
|
1616
|
+
const slash = figmaName.indexOf(" / ");
|
|
1617
|
+
const group = slash >= 0 ? figmaName.slice(0, slash).toLowerCase() : "";
|
|
1618
|
+
const name = slash >= 0 ? figmaName.slice(slash + 3) : figmaName;
|
|
1619
|
+
const order = FIGMA_COLOR_GROUP_ORDER[group] ?? 999;
|
|
1620
|
+
return [order, name];
|
|
1621
|
+
};
|
|
1622
|
+
variables.sort((a, b) => {
|
|
1623
|
+
const [oA, nA] = colorSortKey(a.name);
|
|
1624
|
+
const [oB, nB] = colorSortKey(b.name);
|
|
1625
|
+
if (oA !== oB) return oA - oB;
|
|
1626
|
+
return nA.localeCompare(nB);
|
|
1627
|
+
});
|
|
1628
|
+
paintStyles.sort((a, b) => {
|
|
1629
|
+
const [oA, nA] = colorSortKey(a.name);
|
|
1630
|
+
const [oB, nB] = colorSortKey(b.name);
|
|
1631
|
+
if (oA !== oB) return oA - oB;
|
|
1632
|
+
return nA.localeCompare(nB);
|
|
1633
|
+
});
|
|
1596
1634
|
const collectionName = data.meta?.name ? `${data.meta.name} Colors` : "Atomix Colors";
|
|
1597
1635
|
const textStyles = [];
|
|
1598
1636
|
const sizeToPx = (val, basePx = 16) => {
|
|
@@ -1619,8 +1657,8 @@ function buildFigmaPayloadsFromDS(data) {
|
|
|
1619
1657
|
};
|
|
1620
1658
|
const firstFont = (obj) => {
|
|
1621
1659
|
if (typeof obj === "string") {
|
|
1622
|
-
const
|
|
1623
|
-
return
|
|
1660
|
+
const primary = obj.split(",")[0].trim().replace(/^['"]|['"]$/g, "");
|
|
1661
|
+
return primary || "Inter";
|
|
1624
1662
|
}
|
|
1625
1663
|
if (obj && typeof obj === "object" && !Array.isArray(obj)) {
|
|
1626
1664
|
const v = obj.body ?? obj.heading ?? obj.display ?? Object.values(obj)[0];
|
|
@@ -1693,49 +1731,70 @@ function buildFigmaPayloadsFromDS(data) {
|
|
|
1693
1731
|
textStyles.push(payload);
|
|
1694
1732
|
}
|
|
1695
1733
|
}
|
|
1696
|
-
|
|
1734
|
+
textStyles.sort((a, b) => {
|
|
1735
|
+
if (a.fontSize !== b.fontSize) return a.fontSize - b.fontSize;
|
|
1736
|
+
return (a.name || "").localeCompare(b.name || "");
|
|
1737
|
+
});
|
|
1697
1738
|
const dsName = data.meta?.name ?? "Atomix";
|
|
1698
|
-
const
|
|
1739
|
+
const numberVariableCollections = [];
|
|
1699
1740
|
const spacing = tokens?.spacing;
|
|
1700
1741
|
if (spacing?.scale && typeof spacing.scale === "object") {
|
|
1742
|
+
const variables2 = [];
|
|
1701
1743
|
for (const [key, val] of Object.entries(spacing.scale)) {
|
|
1702
1744
|
const n = tokenValueToNumber(val);
|
|
1703
|
-
if (n >= 0)
|
|
1745
|
+
if (n >= 0) variables2.push({ name: key, value: n });
|
|
1704
1746
|
}
|
|
1747
|
+
variables2.sort((a, b) => a.value - b.value);
|
|
1748
|
+
if (variables2.length > 0) numberVariableCollections.push({ collectionName: `${dsName} Spacing`, categoryKey: "Spacing", variables: variables2, scopes: ["GAP"] });
|
|
1705
1749
|
}
|
|
1706
1750
|
const radius = tokens?.radius;
|
|
1707
1751
|
if (radius?.scale && typeof radius.scale === "object") {
|
|
1752
|
+
const variables2 = [];
|
|
1708
1753
|
for (const [key, val] of Object.entries(radius.scale)) {
|
|
1709
1754
|
const n = tokenValueToNumber(val);
|
|
1710
|
-
if (n >= 0)
|
|
1755
|
+
if (n >= 0) variables2.push({ name: key, value: n });
|
|
1711
1756
|
}
|
|
1757
|
+
variables2.sort((a, b) => a.value - b.value);
|
|
1758
|
+
if (variables2.length > 0) numberVariableCollections.push({ collectionName: `${dsName} Radius`, categoryKey: "Radius", variables: variables2, scopes: ["CORNER_RADIUS"] });
|
|
1712
1759
|
}
|
|
1713
1760
|
const borders = tokens?.borders;
|
|
1714
1761
|
if (borders?.width && typeof borders.width === "object") {
|
|
1762
|
+
const variables2 = [];
|
|
1715
1763
|
for (const [key, val] of Object.entries(borders.width)) {
|
|
1716
1764
|
const n = tokenValueToNumber(val);
|
|
1717
|
-
if (n >= 0)
|
|
1765
|
+
if (n >= 0) variables2.push({ name: key, value: n });
|
|
1718
1766
|
}
|
|
1767
|
+
variables2.sort((a, b) => a.value - b.value);
|
|
1768
|
+
if (variables2.length > 0) numberVariableCollections.push({ collectionName: `${dsName} Borders`, categoryKey: "Borders", variables: variables2, scopes: ["STROKE_FLOAT"] });
|
|
1719
1769
|
}
|
|
1720
1770
|
const sizing = tokens?.sizing;
|
|
1721
1771
|
if (sizing?.height && typeof sizing.height === "object") {
|
|
1772
|
+
const variables2 = [];
|
|
1722
1773
|
for (const [key, val] of Object.entries(sizing.height)) {
|
|
1723
1774
|
const n = tokenValueToNumber(val);
|
|
1724
|
-
if (n >= 0)
|
|
1775
|
+
if (n >= 0) variables2.push({ name: key, value: n });
|
|
1725
1776
|
}
|
|
1777
|
+
variables2.sort((a, b) => a.value - b.value);
|
|
1778
|
+
if (variables2.length > 0) numberVariableCollections.push({ collectionName: `${dsName} Height`, categoryKey: "Height", variables: variables2, scopes: ["WIDTH_HEIGHT"] });
|
|
1726
1779
|
}
|
|
1727
1780
|
if (sizing?.icon && typeof sizing.icon === "object") {
|
|
1781
|
+
const variables2 = [];
|
|
1728
1782
|
for (const [key, val] of Object.entries(sizing.icon)) {
|
|
1729
1783
|
const n = tokenValueToNumber(val);
|
|
1730
|
-
if (n >= 0)
|
|
1784
|
+
if (n >= 0) variables2.push({ name: key, value: n });
|
|
1731
1785
|
}
|
|
1786
|
+
variables2.sort((a, b) => a.value - b.value);
|
|
1787
|
+
if (variables2.length > 0) numberVariableCollections.push({ collectionName: `${dsName} Icon`, categoryKey: "Icon", variables: variables2, scopes: ["WIDTH_HEIGHT"] });
|
|
1732
1788
|
}
|
|
1733
1789
|
const layout = tokens?.layout;
|
|
1734
1790
|
if (layout?.breakpoint && typeof layout.breakpoint === "object") {
|
|
1791
|
+
const variables2 = [];
|
|
1735
1792
|
for (const [key, val] of Object.entries(layout.breakpoint)) {
|
|
1736
1793
|
const n = tokenValueToNumber(val);
|
|
1737
|
-
if (n >= 0)
|
|
1794
|
+
if (n >= 0) variables2.push({ name: key, value: n });
|
|
1738
1795
|
}
|
|
1796
|
+
variables2.sort((a, b) => a.value - b.value);
|
|
1797
|
+
if (variables2.length > 0) numberVariableCollections.push({ collectionName: `${dsName} Breakpoint`, categoryKey: "Breakpoint", variables: variables2, scopes: ["WIDTH_HEIGHT"] });
|
|
1739
1798
|
}
|
|
1740
1799
|
const effectStyles = [];
|
|
1741
1800
|
const shadows = tokens?.shadows;
|
|
@@ -1757,22 +1816,33 @@ function buildFigmaPayloadsFromDS(data) {
|
|
|
1757
1816
|
effectStyles.push({ name: "Shadow / focus", effects });
|
|
1758
1817
|
}
|
|
1759
1818
|
}
|
|
1819
|
+
effectStyles.sort((a, b) => {
|
|
1820
|
+
const nameA = a.name.startsWith("Shadow / ") ? a.name.slice(9) : a.name;
|
|
1821
|
+
const nameB = b.name.startsWith("Shadow / ") ? b.name.slice(9) : b.name;
|
|
1822
|
+
const orderA = FIGMA_SHADOW_ORDER[nameA] ?? 100;
|
|
1823
|
+
const orderB = FIGMA_SHADOW_ORDER[nameB] ?? 100;
|
|
1824
|
+
if (orderA !== orderB) return orderA - orderB;
|
|
1825
|
+
return nameA.localeCompare(nameB);
|
|
1826
|
+
});
|
|
1760
1827
|
return {
|
|
1761
1828
|
colorVariables: { collectionName, modes, variables },
|
|
1762
1829
|
paintStyles,
|
|
1763
1830
|
textStyles,
|
|
1764
|
-
|
|
1831
|
+
numberVariableCollections,
|
|
1765
1832
|
effectStyles
|
|
1766
1833
|
};
|
|
1767
1834
|
}
|
|
1768
1835
|
function getExpectedFigmaNamesFromDS(data) {
|
|
1769
1836
|
const payloads = buildFigmaPayloadsFromDS(data);
|
|
1837
|
+
const numberVariableNames = payloads.numberVariableCollections.flatMap(
|
|
1838
|
+
(c) => c.variables.map((v) => `${c.categoryKey} / ${v.name}`)
|
|
1839
|
+
);
|
|
1770
1840
|
return {
|
|
1771
1841
|
colorVariableNames: payloads.colorVariables.variables.map((v) => v.name),
|
|
1772
1842
|
paintStyleNames: payloads.paintStyles.map((s) => s.name),
|
|
1773
1843
|
textStyleNames: payloads.textStyles.map((s) => s.name),
|
|
1774
1844
|
effectStyleNames: payloads.effectStyles.map((s) => s.name),
|
|
1775
|
-
numberVariableNames
|
|
1845
|
+
numberVariableNames
|
|
1776
1846
|
};
|
|
1777
1847
|
}
|
|
1778
1848
|
function parseArgs() {
|
|
@@ -1810,8 +1880,8 @@ function hasValidAuthConfig() {
|
|
|
1810
1880
|
}
|
|
1811
1881
|
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.";
|
|
1812
1882
|
var lastChangeSummary = null;
|
|
1813
|
-
var
|
|
1814
|
-
|
|
1883
|
+
var FIGMA_SYNC_TOOL_NAME = "syncToFigma";
|
|
1884
|
+
var FIGMA_DESIGN_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
1815
1885
|
"getFigmaVariablesAndStyles",
|
|
1816
1886
|
"createDesignPlaceholder",
|
|
1817
1887
|
"resolveFigmaIdsForTokens",
|
|
@@ -1824,6 +1894,7 @@ var FIGMA_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
|
1824
1894
|
"getDesignScreenshot",
|
|
1825
1895
|
"finalizeDesignFrame"
|
|
1826
1896
|
]);
|
|
1897
|
+
var FIGMA_TOOL_NAMES = /* @__PURE__ */ new Set([FIGMA_SYNC_TOOL_NAME, ...FIGMA_DESIGN_TOOL_NAMES]);
|
|
1827
1898
|
var lastSyncAffectedTokens = null;
|
|
1828
1899
|
function getLastChangeSummary() {
|
|
1829
1900
|
return lastChangeSummary;
|
|
@@ -1860,7 +1931,7 @@ var TOKEN_CATEGORIES = ["colors", "typography", "spacing", "sizing", "shadows",
|
|
|
1860
1931
|
var server = new Server(
|
|
1861
1932
|
{
|
|
1862
1933
|
name: "atomix-mcp-user",
|
|
1863
|
-
version: "1.0.
|
|
1934
|
+
version: "1.0.22"
|
|
1864
1935
|
},
|
|
1865
1936
|
{
|
|
1866
1937
|
capabilities: {
|
|
@@ -1883,7 +1954,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
1883
1954
|
console.error("[Atomix MCP] Resolved tier = pro. Figma sync/design tools are available.");
|
|
1884
1955
|
} else if (cachedMcpTier === "free") {
|
|
1885
1956
|
console.error(
|
|
1886
|
-
"[Atomix MCP] Resolved tier = free. Figma
|
|
1957
|
+
"[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."
|
|
1887
1958
|
);
|
|
1888
1959
|
}
|
|
1889
1960
|
} catch (err) {
|
|
@@ -2212,7 +2283,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2212
2283
|
}
|
|
2213
2284
|
}
|
|
2214
2285
|
];
|
|
2215
|
-
const tools = cachedMcpTier === "pro" ? toolsList : toolsList.filter((t) => !
|
|
2286
|
+
const tools = cachedMcpTier === "pro" ? toolsList : toolsList.filter((t) => !FIGMA_DESIGN_TOOL_NAMES.has(t.name));
|
|
2216
2287
|
return { tools };
|
|
2217
2288
|
});
|
|
2218
2289
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
@@ -2229,12 +2300,12 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
2229
2300
|
try {
|
|
2230
2301
|
const shouldForceRefresh = name === "syncAll";
|
|
2231
2302
|
const data = await fetchDesignSystemForMCP(shouldForceRefresh);
|
|
2232
|
-
if (
|
|
2303
|
+
if (FIGMA_DESIGN_TOOL_NAMES.has(name) && cachedMcpTier !== "pro") {
|
|
2233
2304
|
return {
|
|
2234
2305
|
content: [
|
|
2235
2306
|
{
|
|
2236
2307
|
type: "text",
|
|
2237
|
-
text: "This design system does not have Pro Figma access. Figma
|
|
2308
|
+
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."
|
|
2238
2309
|
}
|
|
2239
2310
|
],
|
|
2240
2311
|
isError: true
|
|
@@ -2880,7 +2951,7 @@ ${tokenResponseText}` : summary;
|
|
|
2880
2951
|
variables: payloads.colorVariables.variables,
|
|
2881
2952
|
paintStyles: payloads.paintStyles,
|
|
2882
2953
|
textStyles: payloads.textStyles,
|
|
2883
|
-
|
|
2954
|
+
numberVariableCollections: payloads.numberVariableCollections,
|
|
2884
2955
|
effectStyles: payloads.effectStyles
|
|
2885
2956
|
};
|
|
2886
2957
|
return {
|
|
@@ -2897,12 +2968,18 @@ ${tokenResponseText}` : summary;
|
|
|
2897
2968
|
if (payloads.paintStyles.length > 0) {
|
|
2898
2969
|
out.paintStyles = await sendBridgeRequest("create_paint_styles", { styles: payloads.paintStyles });
|
|
2899
2970
|
}
|
|
2900
|
-
if (payloads.
|
|
2971
|
+
if (payloads.numberVariableCollections.length > 0) {
|
|
2972
|
+
const numberResults = [];
|
|
2901
2973
|
try {
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2974
|
+
for (const coll of payloads.numberVariableCollections) {
|
|
2975
|
+
const result = await sendBridgeRequest("create_number_variables", {
|
|
2976
|
+
collectionName: coll.collectionName,
|
|
2977
|
+
variables: coll.variables,
|
|
2978
|
+
scopes: coll.scopes
|
|
2979
|
+
});
|
|
2980
|
+
numberResults.push({ collectionName: coll.collectionName, result });
|
|
2981
|
+
}
|
|
2982
|
+
out.numberVariables = numberResults;
|
|
2906
2983
|
} catch (e) {
|
|
2907
2984
|
const msg = e instanceof Error ? e.message : String(e);
|
|
2908
2985
|
out.numberVariables = { error: msg };
|
|
@@ -2923,7 +3000,7 @@ ${tokenResponseText}` : summary;
|
|
|
2923
3000
|
variables: payloads.colorVariables.variables,
|
|
2924
3001
|
paintStyles: payloads.paintStyles,
|
|
2925
3002
|
textStyles: payloads.textStyles,
|
|
2926
|
-
|
|
3003
|
+
numberVariableCollections: payloads.numberVariableCollections,
|
|
2927
3004
|
effectStyles: payloads.effectStyles
|
|
2928
3005
|
};
|
|
2929
3006
|
} catch (e) {
|
|
@@ -2934,7 +3011,7 @@ ${tokenResponseText}` : summary;
|
|
|
2934
3011
|
variables: payloads.colorVariables.variables,
|
|
2935
3012
|
paintStyles: payloads.paintStyles,
|
|
2936
3013
|
textStyles: payloads.textStyles,
|
|
2937
|
-
|
|
3014
|
+
numberVariableCollections: payloads.numberVariableCollections,
|
|
2938
3015
|
effectStyles: payloads.effectStyles
|
|
2939
3016
|
};
|
|
2940
3017
|
const errMsg = out.error.toLowerCase();
|
|
@@ -3049,9 +3126,20 @@ ${tokenResponseText}` : summary;
|
|
|
3049
3126
|
const response = raw;
|
|
3050
3127
|
const variableByName = /* @__PURE__ */ new Map();
|
|
3051
3128
|
if (response.variableCollections) {
|
|
3129
|
+
const numberCategorySuffixes = [" Spacing", " Radius", " Borders", " Height", " Icon", " Breakpoint"];
|
|
3052
3130
|
for (const coll of response.variableCollections) {
|
|
3053
|
-
|
|
3054
|
-
|
|
3131
|
+
if (coll.name.endsWith(" Colors")) {
|
|
3132
|
+
for (const v of coll.variables || []) {
|
|
3133
|
+
variableByName.set(v.name, v.id);
|
|
3134
|
+
}
|
|
3135
|
+
continue;
|
|
3136
|
+
}
|
|
3137
|
+
const numberSuffix = numberCategorySuffixes.find((s) => coll.name.endsWith(s));
|
|
3138
|
+
if (numberSuffix) {
|
|
3139
|
+
const category = numberSuffix.slice(1);
|
|
3140
|
+
for (const v of coll.variables || []) {
|
|
3141
|
+
variableByName.set(`${category} / ${v.name}`, v.id);
|
|
3142
|
+
}
|
|
3055
3143
|
}
|
|
3056
3144
|
}
|
|
3057
3145
|
}
|
|
@@ -3495,7 +3583,7 @@ Get your DS ID and token from the Export modal or Settings \u2192 Regenerate Ato
|
|
|
3495
3583
|
}
|
|
3496
3584
|
throw new Error(`Unknown resource: ${uri}`);
|
|
3497
3585
|
});
|
|
3498
|
-
var
|
|
3586
|
+
var FIGMA_DESIGN_PROMPT_NAMES = /* @__PURE__ */ new Set(["--design-in-figma"]);
|
|
3499
3587
|
server.setRequestHandler(ListPromptsRequestSchema, async () => {
|
|
3500
3588
|
if (!hasValidAuthConfig()) {
|
|
3501
3589
|
authFailedNoTools = true;
|
|
@@ -3520,7 +3608,7 @@ server.setRequestHandler(ListPromptsRequestSchema, async () => {
|
|
|
3520
3608
|
{ name: "--sync-to-figma", description: "Push this design system to Figma (variables, color + typography styles). Uses local bridge + plugin; no Figma token." },
|
|
3521
3609
|
{ 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." }
|
|
3522
3610
|
];
|
|
3523
|
-
const prompts = cachedMcpTier === "pro" ? allPrompts : allPrompts.filter((p) => !
|
|
3611
|
+
const prompts = cachedMcpTier === "pro" ? allPrompts : allPrompts.filter((p) => !FIGMA_DESIGN_PROMPT_NAMES.has(p.name));
|
|
3524
3612
|
return { prompts };
|
|
3525
3613
|
});
|
|
3526
3614
|
server.setRequestHandler(GetPromptRequestSchema, async (request) => {
|
|
@@ -3622,7 +3710,7 @@ Both are required. Configure the MCP server in your Cursor settings, then restar
|
|
|
3622
3710
|
}
|
|
3623
3711
|
throw error;
|
|
3624
3712
|
}
|
|
3625
|
-
if (
|
|
3713
|
+
if (FIGMA_DESIGN_PROMPT_NAMES.has(name) && cachedMcpTier !== "pro") {
|
|
3626
3714
|
return {
|
|
3627
3715
|
description: "Pro Figma required",
|
|
3628
3716
|
messages: [
|
|
@@ -3630,7 +3718,7 @@ Both are required. Configure the MCP server in your Cursor settings, then restar
|
|
|
3630
3718
|
role: "user",
|
|
3631
3719
|
content: {
|
|
3632
3720
|
type: "text",
|
|
3633
|
-
text: "This design system does not have Pro Figma access.
|
|
3721
|
+
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."
|
|
3634
3722
|
}
|
|
3635
3723
|
}
|
|
3636
3724
|
]
|