faux-studio 0.3.8 → 0.3.10

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.
Files changed (2) hide show
  1. package/dist/index.js +162 -151
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2267,7 +2267,7 @@ var require_websocket = __commonJS({
2267
2267
  var protocolVersions = [8, 13];
2268
2268
  var readyStates = ["CONNECTING", "OPEN", "CLOSING", "CLOSED"];
2269
2269
  var subprotocolRegex = /^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/;
2270
- var WebSocket3 = class _WebSocket extends EventEmitter {
2270
+ var WebSocket2 = class _WebSocket extends EventEmitter {
2271
2271
  /**
2272
2272
  * Create a new `WebSocket`.
2273
2273
  *
@@ -2637,35 +2637,35 @@ var require_websocket = __commonJS({
2637
2637
  }
2638
2638
  }
2639
2639
  };
2640
- Object.defineProperty(WebSocket3, "CONNECTING", {
2640
+ Object.defineProperty(WebSocket2, "CONNECTING", {
2641
2641
  enumerable: true,
2642
2642
  value: readyStates.indexOf("CONNECTING")
2643
2643
  });
2644
- Object.defineProperty(WebSocket3.prototype, "CONNECTING", {
2644
+ Object.defineProperty(WebSocket2.prototype, "CONNECTING", {
2645
2645
  enumerable: true,
2646
2646
  value: readyStates.indexOf("CONNECTING")
2647
2647
  });
2648
- Object.defineProperty(WebSocket3, "OPEN", {
2648
+ Object.defineProperty(WebSocket2, "OPEN", {
2649
2649
  enumerable: true,
2650
2650
  value: readyStates.indexOf("OPEN")
2651
2651
  });
2652
- Object.defineProperty(WebSocket3.prototype, "OPEN", {
2652
+ Object.defineProperty(WebSocket2.prototype, "OPEN", {
2653
2653
  enumerable: true,
2654
2654
  value: readyStates.indexOf("OPEN")
2655
2655
  });
2656
- Object.defineProperty(WebSocket3, "CLOSING", {
2656
+ Object.defineProperty(WebSocket2, "CLOSING", {
2657
2657
  enumerable: true,
2658
2658
  value: readyStates.indexOf("CLOSING")
2659
2659
  });
2660
- Object.defineProperty(WebSocket3.prototype, "CLOSING", {
2660
+ Object.defineProperty(WebSocket2.prototype, "CLOSING", {
2661
2661
  enumerable: true,
2662
2662
  value: readyStates.indexOf("CLOSING")
2663
2663
  });
2664
- Object.defineProperty(WebSocket3, "CLOSED", {
2664
+ Object.defineProperty(WebSocket2, "CLOSED", {
2665
2665
  enumerable: true,
2666
2666
  value: readyStates.indexOf("CLOSED")
2667
2667
  });
2668
- Object.defineProperty(WebSocket3.prototype, "CLOSED", {
2668
+ Object.defineProperty(WebSocket2.prototype, "CLOSED", {
2669
2669
  enumerable: true,
2670
2670
  value: readyStates.indexOf("CLOSED")
2671
2671
  });
@@ -2678,10 +2678,10 @@ var require_websocket = __commonJS({
2678
2678
  "readyState",
2679
2679
  "url"
2680
2680
  ].forEach((property) => {
2681
- Object.defineProperty(WebSocket3.prototype, property, { enumerable: true });
2681
+ Object.defineProperty(WebSocket2.prototype, property, { enumerable: true });
2682
2682
  });
2683
2683
  ["open", "error", "close", "message"].forEach((method) => {
2684
- Object.defineProperty(WebSocket3.prototype, `on${method}`, {
2684
+ Object.defineProperty(WebSocket2.prototype, `on${method}`, {
2685
2685
  enumerable: true,
2686
2686
  get() {
2687
2687
  for (const listener of this.listeners(method)) {
@@ -2703,9 +2703,9 @@ var require_websocket = __commonJS({
2703
2703
  }
2704
2704
  });
2705
2705
  });
2706
- WebSocket3.prototype.addEventListener = addEventListener;
2707
- WebSocket3.prototype.removeEventListener = removeEventListener;
2708
- module.exports = WebSocket3;
2706
+ WebSocket2.prototype.addEventListener = addEventListener;
2707
+ WebSocket2.prototype.removeEventListener = removeEventListener;
2708
+ module.exports = WebSocket2;
2709
2709
  function initAsClient(websocket, address, protocols, options) {
2710
2710
  const opts = {
2711
2711
  allowSynchronousEvents: true,
@@ -2893,7 +2893,7 @@ var require_websocket = __commonJS({
2893
2893
  });
2894
2894
  req.on("upgrade", (res, socket, head) => {
2895
2895
  websocket.emit("upgrade", res);
2896
- if (websocket.readyState !== WebSocket3.CONNECTING) return;
2896
+ if (websocket.readyState !== WebSocket2.CONNECTING) return;
2897
2897
  req = websocket._req = null;
2898
2898
  const upgrade = res.headers.upgrade;
2899
2899
  if (upgrade === void 0 || upgrade.toLowerCase() !== "websocket") {
@@ -2965,7 +2965,7 @@ var require_websocket = __commonJS({
2965
2965
  }
2966
2966
  }
2967
2967
  function emitErrorAndClose(websocket, err) {
2968
- websocket._readyState = WebSocket3.CLOSING;
2968
+ websocket._readyState = WebSocket2.CLOSING;
2969
2969
  websocket._errorEmitted = true;
2970
2970
  websocket.emit("error", err);
2971
2971
  websocket.emitClose();
@@ -2982,7 +2982,7 @@ var require_websocket = __commonJS({
2982
2982
  return tls.connect(options);
2983
2983
  }
2984
2984
  function abortHandshake(websocket, stream, message) {
2985
- websocket._readyState = WebSocket3.CLOSING;
2985
+ websocket._readyState = WebSocket2.CLOSING;
2986
2986
  const err = new Error(message);
2987
2987
  Error.captureStackTrace(err, abortHandshake);
2988
2988
  if (stream.setHeader) {
@@ -3057,9 +3057,9 @@ var require_websocket = __commonJS({
3057
3057
  }
3058
3058
  function senderOnError(err) {
3059
3059
  const websocket = this[kWebSocket];
3060
- if (websocket.readyState === WebSocket3.CLOSED) return;
3061
- if (websocket.readyState === WebSocket3.OPEN) {
3062
- websocket._readyState = WebSocket3.CLOSING;
3060
+ if (websocket.readyState === WebSocket2.CLOSED) return;
3061
+ if (websocket.readyState === WebSocket2.OPEN) {
3062
+ websocket._readyState = WebSocket2.CLOSING;
3063
3063
  setCloseTimer(websocket);
3064
3064
  }
3065
3065
  this._socket.end();
@@ -3079,7 +3079,7 @@ var require_websocket = __commonJS({
3079
3079
  this.removeListener("close", socketOnClose);
3080
3080
  this.removeListener("data", socketOnData);
3081
3081
  this.removeListener("end", socketOnEnd);
3082
- websocket._readyState = WebSocket3.CLOSING;
3082
+ websocket._readyState = WebSocket2.CLOSING;
3083
3083
  if (!this._readableState.endEmitted && !websocket._closeFrameReceived && !websocket._receiver._writableState.errorEmitted && this._readableState.length !== 0) {
3084
3084
  const chunk = this.read(this._readableState.length);
3085
3085
  websocket._receiver.write(chunk);
@@ -3101,7 +3101,7 @@ var require_websocket = __commonJS({
3101
3101
  }
3102
3102
  function socketOnEnd() {
3103
3103
  const websocket = this[kWebSocket];
3104
- websocket._readyState = WebSocket3.CLOSING;
3104
+ websocket._readyState = WebSocket2.CLOSING;
3105
3105
  websocket._receiver.end();
3106
3106
  this.end();
3107
3107
  }
@@ -3110,7 +3110,7 @@ var require_websocket = __commonJS({
3110
3110
  this.removeListener("error", socketOnError);
3111
3111
  this.on("error", NOOP);
3112
3112
  if (websocket) {
3113
- websocket._readyState = WebSocket3.CLOSING;
3113
+ websocket._readyState = WebSocket2.CLOSING;
3114
3114
  this.destroy();
3115
3115
  }
3116
3116
  }
@@ -3121,7 +3121,7 @@ var require_websocket = __commonJS({
3121
3121
  var require_stream = __commonJS({
3122
3122
  "node_modules/ws/lib/stream.js"(exports, module) {
3123
3123
  "use strict";
3124
- var WebSocket3 = require_websocket();
3124
+ var WebSocket2 = require_websocket();
3125
3125
  var { Duplex } = __require("stream");
3126
3126
  function emitClose(stream) {
3127
3127
  stream.emit("close");
@@ -3271,7 +3271,7 @@ var require_websocket_server = __commonJS({
3271
3271
  var extension = require_extension();
3272
3272
  var PerMessageDeflate = require_permessage_deflate();
3273
3273
  var subprotocol = require_subprotocol();
3274
- var WebSocket3 = require_websocket();
3274
+ var WebSocket2 = require_websocket();
3275
3275
  var { CLOSE_TIMEOUT, GUID, kWebSocket } = require_constants();
3276
3276
  var keyRegex = /^[+/0-9A-Za-z]{22}==$/;
3277
3277
  var RUNNING = 0;
@@ -3331,7 +3331,7 @@ var require_websocket_server = __commonJS({
3331
3331
  host: null,
3332
3332
  path: null,
3333
3333
  port: null,
3334
- WebSocket: WebSocket3,
3334
+ WebSocket: WebSocket2,
3335
3335
  ...options
3336
3336
  };
3337
3337
  if (options.port == null && !options.server && !options.noServer || options.port != null && (options.server || options.noServer) || options.server && options.noServer) {
@@ -11071,56 +11071,35 @@ async function probeCdpPorts() {
11071
11071
  }
11072
11072
  return null;
11073
11073
  }
11074
- function killFigma() {
11075
- try {
11076
- if (process.platform === "darwin") {
11077
- execSync("pkill -x Figma", { stdio: "ignore" });
11078
- return true;
11079
- }
11080
- if (process.platform === "win32") {
11081
- execSync("taskkill /IM Figma.exe", { stdio: "ignore" });
11082
- return true;
11083
- }
11084
- execSync("pkill -x figma-linux", { stdio: "ignore" });
11085
- return true;
11086
- } catch {
11087
- return false;
11074
+ function launchFigmaProcess(figmaPath, port) {
11075
+ if (process.platform === "darwin") {
11076
+ const binary = `${figmaPath}/Contents/MacOS/Figma`;
11077
+ spawn2(binary, [`--remote-debugging-port=${port}`], {
11078
+ detached: true,
11079
+ stdio: "ignore"
11080
+ }).unref();
11081
+ } else {
11082
+ spawn2(figmaPath, [`--remote-debugging-port=${port}`], {
11083
+ detached: true,
11084
+ stdio: "ignore"
11085
+ }).unref();
11088
11086
  }
11089
11087
  }
11090
- async function launchFigmaWithCdp() {
11088
+ function launchFigma() {
11091
11089
  const figmaPath = findFigmaPath();
11092
11090
  if (!figmaPath) {
11093
11091
  throw new Error(
11094
11092
  "Figma Desktop is not installed. Download from https://figma.com/downloads"
11095
11093
  );
11096
11094
  }
11097
- const port = await findAvailablePort();
11098
- log(`Launching Figma Desktop (port ${port})...`);
11099
- launchFigmaProcess(figmaPath, port);
11100
- const startTime = Date.now();
11101
- while (Date.now() - startTime < CDP_WAIT_TIMEOUT_MS) {
11102
- await new Promise((r) => setTimeout(r, CDP_POLL_INTERVAL_MS));
11103
- const { alive, isFigma } = await isCdpAlive(port);
11104
- if (alive && isFigma) {
11105
- await new Promise((r) => setTimeout(r, 2e3));
11106
- const targets = await listTargets(port);
11107
- log("Figma Desktop started");
11108
- return { port, targets };
11109
- }
11110
- }
11111
- throw new Error(
11112
- `Figma did not respond on port ${port} within ${CDP_WAIT_TIMEOUT_MS / 1e3}s. Try again.`
11113
- );
11114
- }
11115
- function launchFigmaProcess(figmaPath, port) {
11095
+ log("Launching Figma Desktop...");
11116
11096
  if (process.platform === "darwin") {
11117
- const binary = `${figmaPath}/Contents/MacOS/Figma`;
11118
- spawn2(binary, [`--remote-debugging-port=${port}`], {
11097
+ spawn2("open", ["-a", figmaPath], {
11119
11098
  detached: true,
11120
11099
  stdio: "ignore"
11121
11100
  }).unref();
11122
11101
  } else {
11123
- spawn2(figmaPath, [`--remote-debugging-port=${port}`], {
11102
+ spawn2(figmaPath, [], {
11124
11103
  detached: true,
11125
11104
  stdio: "ignore"
11126
11105
  }).unref();
@@ -11212,6 +11191,7 @@ var PluginWsServer = class {
11212
11191
  // Server Lifecycle
11213
11192
  // -------------------------------------------------------------------------
11214
11193
  async start() {
11194
+ await this.shutdownExisting();
11215
11195
  for (let port = DEFAULT_PORT; port < DEFAULT_PORT + PORT_RANGE; port++) {
11216
11196
  try {
11217
11197
  await this.listen(port);
@@ -11227,6 +11207,53 @@ var PluginWsServer = class {
11227
11207
  `No available port in range ${DEFAULT_PORT}-${DEFAULT_PORT + PORT_RANGE - 1}. Another faux-studio instance may be running.`
11228
11208
  );
11229
11209
  }
11210
+ /**
11211
+ * Connect to any existing faux-studio WS servers and tell them to shut down
11212
+ * their listener. This ensures the plugin reconnects to the newest instance.
11213
+ */
11214
+ async shutdownExisting() {
11215
+ const promises = [];
11216
+ for (let port = DEFAULT_PORT; port < DEFAULT_PORT + PORT_RANGE; port++) {
11217
+ promises.push(this.sendShutdown(port));
11218
+ }
11219
+ await Promise.allSettled(promises);
11220
+ await new Promise((r) => setTimeout(r, 500));
11221
+ }
11222
+ sendShutdown(port) {
11223
+ return new Promise((resolve) => {
11224
+ try {
11225
+ const ws = new import_websocket.default(`ws://127.0.0.1:${port}`);
11226
+ const timer = setTimeout(() => {
11227
+ try {
11228
+ ws.close();
11229
+ } catch {
11230
+ }
11231
+ resolve();
11232
+ }, 1e3);
11233
+ ws.on("open", () => {
11234
+ ws.send(JSON.stringify({ type: "shutdown" }));
11235
+ clearTimeout(timer);
11236
+ setTimeout(() => {
11237
+ try {
11238
+ ws.close();
11239
+ } catch {
11240
+ }
11241
+ resolve();
11242
+ }, 200);
11243
+ });
11244
+ ws.on("error", () => {
11245
+ clearTimeout(timer);
11246
+ resolve();
11247
+ });
11248
+ ws.on("close", () => {
11249
+ clearTimeout(timer);
11250
+ resolve();
11251
+ });
11252
+ } catch {
11253
+ resolve();
11254
+ }
11255
+ });
11256
+ }
11230
11257
  listen(port) {
11231
11258
  return new Promise((resolve, reject) => {
11232
11259
  const wss = new import_websocket_server.default({ port, host: "127.0.0.1" });
@@ -11287,6 +11314,13 @@ var PluginWsServer = class {
11287
11314
  } catch {
11288
11315
  return;
11289
11316
  }
11317
+ if (!identified && msg.type === "shutdown") {
11318
+ clearTimeout(handshakeTimeout);
11319
+ ws.close(1e3, "Shutdown requested");
11320
+ log("Shutdown requested by newer faux-studio instance \u2014 releasing port");
11321
+ this.close();
11322
+ return;
11323
+ }
11290
11324
  if (!identified && msg.type === "handshake") {
11291
11325
  clearTimeout(handshakeTimeout);
11292
11326
  identified = true;
@@ -25591,7 +25625,7 @@ Resources provide quick read-only access to Figma state without tool calls:
25591
25625
  - Create components for reusable UI patterns.`;
25592
25626
  function createMcpServer(deps) {
25593
25627
  const server2 = new Server(
25594
- { name: "faux-studio", version: "0.3.8" },
25628
+ { name: "faux-studio", version: "0.3.10" },
25595
25629
  {
25596
25630
  capabilities: { tools: { listChanged: true }, resources: {}, logging: {} },
25597
25631
  instructions: INSTRUCTIONS
@@ -25606,15 +25640,10 @@ function createMcpServer(deps) {
25606
25640
  },
25607
25641
  {
25608
25642
  name: "setup_figma",
25609
- description: "Ensure Figma Desktop is running and connected. Call this before any design work. Checks plugin and CDP transports, launches Figma if needed, or restarts it with the debug port. Idempotent \u2014 safe to call multiple times. Returns connection status and active file info.",
25643
+ description: "Ensure Figma Desktop is running and the plugin is connected. Call this before any design work. Launches Figma if needed, waits for the plugin to connect, and provides setup guidance. Idempotent \u2014 safe to call multiple times. Returns connection status and active file info.",
25610
25644
  inputSchema: {
25611
25645
  type: "object",
25612
- properties: {
25613
- force_restart: {
25614
- type: "boolean",
25615
- description: "Restart Figma even if it is already running (e.g., to enable the debug port). Figma auto-recovers open files on restart. Only set this if instructed or if the previous call returned needs_restart."
25616
- }
25617
- },
25646
+ properties: {},
25618
25647
  required: []
25619
25648
  }
25620
25649
  }
@@ -25674,9 +25703,7 @@ function createMcpServer(deps) {
25674
25703
  }
25675
25704
  if (name === "setup_figma") {
25676
25705
  log("setup_figma called");
25677
- const result2 = await deps.setupFigma({
25678
- force_restart: params.force_restart === true
25679
- });
25706
+ const result2 = await deps.setupFigma(params);
25680
25707
  return {
25681
25708
  content: [{ type: "text", text: JSON.stringify(result2, null, 2) }],
25682
25709
  isError: result2.status === "not_installed"
@@ -25842,16 +25869,31 @@ async function generateWithAuth(toolName, params) {
25842
25869
  throw err;
25843
25870
  }
25844
25871
  }
25872
+ var PLUGIN_URL = "https://faux.design/plugin";
25873
+ var PLUGIN_WAIT_MS = 1e4;
25874
+ var PLUGIN_POLL_MS = 1e3;
25875
+ async function waitForPlugin() {
25876
+ if (pluginServer.hasConnections) return true;
25877
+ const start = Date.now();
25878
+ while (Date.now() - start < PLUGIN_WAIT_MS) {
25879
+ await new Promise((r) => setTimeout(r, PLUGIN_POLL_MS));
25880
+ if (pluginServer.hasConnections) return true;
25881
+ }
25882
+ return false;
25883
+ }
25884
+ function pluginReadyResult() {
25885
+ return {
25886
+ status: "ready",
25887
+ transport: "plugin",
25888
+ message: `Connected via plugin.${pluginServer.activeFileId ? ` Active file: ${pluginServer.activeFileId}` : ""} Ready to design.`,
25889
+ activeFile: pluginServer.activeFileId || void 0,
25890
+ pluginFiles: pluginServer.connectedFiles,
25891
+ port: pluginServer.port
25892
+ };
25893
+ }
25845
25894
  async function setupFigma(params) {
25846
- if (forceTransport !== "cdp" && pluginServer.hasConnections) {
25847
- return {
25848
- status: "ready",
25849
- transport: "plugin",
25850
- message: `Connected via plugin.${pluginServer.activeFileId ? ` Active file: ${pluginServer.activeFileId}` : ""} Ready to design.`,
25851
- activeFile: pluginServer.activeFileId || void 0,
25852
- pluginFiles: pluginServer.connectedFiles,
25853
- port: pluginServer.port
25854
- };
25895
+ if (pluginServer.hasConnections) {
25896
+ return pluginReadyResult();
25855
25897
  }
25856
25898
  if (forceTransport !== "plugin" && cdpClient?.connected && cdpClient.hasContext) {
25857
25899
  return {
@@ -25883,86 +25925,55 @@ async function setupFigma(params) {
25883
25925
  } catch {
25884
25926
  }
25885
25927
  }
25886
- return {
25887
- status: "no_design_file",
25888
- transport: "none",
25889
- message: "Figma is running with the debug port, but no design file is open. Ask the user to open a .fig file in Figma, then call setup_figma again.",
25890
- port: existing.port
25891
- };
25892
25928
  }
25893
25929
  }
25894
- if (isFigmaRunning()) {
25895
- if (params.force_restart) {
25896
- log("Restarting Figma with debug port...");
25897
- killFigma();
25898
- await new Promise((r) => setTimeout(r, 3e3));
25899
- try {
25900
- const conn = await launchFigmaWithCdp();
25901
- const target = findFigmaDesignTarget(conn.targets);
25902
- if (target) {
25903
- try {
25904
- const client = new CdpClient();
25905
- await client.connect(target.webSocketDebuggerUrl);
25906
- await client.discoverFigmaContext();
25907
- cdpClient = client;
25908
- } catch {
25909
- }
25910
- }
25911
- return {
25912
- status: "restarted",
25913
- transport: target ? "cdp" : "none",
25914
- message: target ? `Figma restarted with debug port. Connected to: ${target.title}. Ready to design.` : "Figma restarted with debug port. Waiting for a design file to be opened. Call setup_figma again once a file is open.",
25915
- activeFile: target?.title,
25916
- port: conn.port
25917
- };
25918
- } catch (err) {
25919
- return {
25920
- status: "not_installed",
25921
- transport: "none",
25922
- message: err instanceof Error ? err.message : "Failed to restart Figma."
25923
- };
25924
- }
25925
- }
25926
- return {
25927
- status: "needs_restart",
25928
- transport: "none",
25929
- message: "Figma is running but the debug port is not enabled. Figma needs to restart with the debug port for AI tools to work. Figma auto-recovers all open files on restart, so no work will be lost. Ask the user for permission, then call setup_figma again with force_restart: true."
25930
- };
25931
- }
25932
25930
  if (!findFigmaPath()) {
25933
25931
  return {
25934
25932
  status: "not_installed",
25935
25933
  transport: "none",
25936
- message: "Figma Desktop is not installed. Download from https://figma.com/downloads and install it, then call setup_figma again."
25934
+ message: `Figma Desktop is not installed.
25935
+
25936
+ 1. Download Figma: https://figma.com/downloads
25937
+ 2. Install and open it
25938
+ 3. Install the faux-studio plugin: ${PLUGIN_URL}
25939
+ 4. Call setup_figma again`
25937
25940
  };
25938
25941
  }
25939
- try {
25940
- log("Launching Figma Desktop...");
25941
- const conn = await launchFigmaWithCdp();
25942
- const target = findFigmaDesignTarget(conn.targets);
25943
- if (target) {
25944
- try {
25945
- const client = new CdpClient();
25946
- await client.connect(target.webSocketDebuggerUrl);
25947
- await client.discoverFigmaContext();
25948
- cdpClient = client;
25949
- } catch {
25950
- }
25942
+ if (!isFigmaRunning()) {
25943
+ try {
25944
+ launchFigma();
25945
+ } catch (err) {
25946
+ return {
25947
+ status: "not_installed",
25948
+ transport: "none",
25949
+ message: err instanceof Error ? err.message : "Failed to launch Figma."
25950
+ };
25951
25951
  }
25952
+ }
25953
+ log("Waiting for plugin connection...");
25954
+ const connected = await waitForPlugin();
25955
+ if (connected) {
25952
25956
  return {
25953
- status: "launched",
25954
- transport: target ? "cdp" : "none",
25955
- message: target ? `Figma launched and connected. Active file: ${target.title}. Ready to design.` : "Figma launched. Open a design file to start designing, then call setup_figma again.",
25956
- activeFile: target?.title,
25957
- port: conn.port
25958
- };
25959
- } catch (err) {
25960
- return {
25961
- status: "not_installed",
25962
- transport: "none",
25963
- message: err instanceof Error ? err.message : "Failed to launch Figma."
25957
+ ...pluginReadyResult(),
25958
+ status: isFigmaRunning() ? "ready" : "launched"
25964
25959
  };
25965
25960
  }
25961
+ return {
25962
+ status: "waiting_for_plugin",
25963
+ transport: "none",
25964
+ message: `Figma is running but the faux-studio plugin is not connected.
25965
+
25966
+ If this is your first time:
25967
+ 1. Download the plugin: ${PLUGIN_URL}
25968
+ 2. Unzip and import in Figma: Plugins \u2192 Development \u2192 Import plugin from manifest
25969
+
25970
+ Then run the plugin:
25971
+ 3. Open a design file in Figma
25972
+ 4. Plugins \u2192 Development \u2192 faux-studio
25973
+
25974
+ Call setup_figma again once the plugin shows "Ready".`,
25975
+ port: pluginServer.port
25976
+ };
25966
25977
  }
25967
25978
  async function main() {
25968
25979
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "faux-studio",
3
- "version": "0.3.8",
3
+ "version": "0.3.10",
4
4
  "description": "AI-powered Figma design via MCP — connect any AI client to Figma Desktop",
5
5
  "type": "module",
6
6
  "bin": {