figma-rust-mcp 3.0.5 β†’ 3.2.1

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
@@ -21,69 +21,94 @@ Enables AI agents (Google Antigravity, Claude Code, Cursor, Windsurf, VS Code, Z
21
21
 
22
22
  ---
23
23
 
24
- ## πŸ›οΈ Architecture
24
+ ## πŸ›οΈ Architecture & Zero-Touch Connection
25
25
 
26
26
  ```text
27
27
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
28
- β”‚ Terminal / Standalone Service β”‚
28
+ β”‚ Terminal / Background Service β”‚
29
29
  β”‚ figma-mcp (Pure Rust Engine) β”‚
30
30
  β”‚ β€’ MCP SSE Transport (/sse, /message) & Direct HTTP (/mcp) β”‚
31
+ β”‚ β€’ Dynamic Runtime Server (/plugin/code.js, /plugin/ui.html) β”‚
31
32
  β”‚ β€’ In-Memory Fast Index (<1ms Lookups & Incremental Diffs) β”‚
32
33
  β”‚ β€’ Design-to-Code Compiler (React/Tailwind, Vue, RN, SwiftUI) β”‚
33
34
  β”‚ β€’ Design Token Transformer (CSS, Tailwind, TypeScript, W3C DTCG) β”‚
34
35
  β”‚ β€’ Sandboxed JS Runtime (Boa ECMAScript Engine) β”‚
35
36
  β”‚ β€’ Binary MessagePack & Progressive Subtree Chunk Receiver β”‚
36
37
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–²β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–²β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
37
- β”‚ (ws://127.0.0.1:38451) β”‚ (http://127.0.0.1:38451/sse)
38
- β”‚ (MessagePack / JSON IPC) β”‚
38
+ β”‚ (ws://127.0.0.1:38451/ws) β”‚ (http://127.0.0.1:38451/sse)
39
+ β”‚ (Dynamic Code Streaming & Hot-Reload) β”‚ (JSON-RPC 2.0 / SSE)
39
40
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
40
41
  β”‚ Figma Desktop β”‚ β”‚ AI Assistant(s) β”‚
41
- β”‚ (Plugin Bridge) β”‚ β”‚ Google Antigravityβ”‚
42
+ β”‚ (Thin Loader) β”‚ β”‚ Google Antigravityβ”‚
42
43
  β”‚ β”‚ β”‚ Cursor / Windsurf β”‚
43
- β”‚ β€’ Canvas Tracker β”‚ β”‚ Claude Code / Zed β”‚
44
- β”‚ β€’ SVG/PNG Render β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
44
+ β”‚ β€’ Zero-Touch Sync β”‚ β”‚ Claude Code / Zed β”‚
45
+ β”‚ β€’ Live Hot-Reload β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
46
+ β”‚ β€’ SVG/PNG Render β”‚
45
47
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
46
48
  ```
47
49
 
50
+ ### πŸ”Œ How the Zero-Touch Connection Works:
51
+ 1. **Permanent Thin Loader**: You only import the Figma plugin **once** (`~/.figma-mcp/plugin/manifest.json`).
52
+ 2. **Dynamic Runtime Streaming**: Upon launch, the Thin Loader contacts `http://127.0.0.1:38451/plugin/code.js` to fetch and execute the latest runtime in memory.
53
+ 3. **Live WebSocket Hot-Reload**: The plugin connects to `ws://127.0.0.1:38451/ws`. When you upgrade `figma-rust-mcp` or restart the daemon, the plugin automatically detects the new server version and hot-reloads seamlessly β€” **no need to re-import or restart the plugin in Figma**.
54
+ 4. **Auto-Reconnect & Offline Buffer**: If Figma is opened before the Rust service starts, the plugin displays a waiting screen and connects automatically the instant the service is up.
55
+
48
56
  ---
49
57
 
50
58
  ## πŸš€ Quick Start
51
59
 
52
- ### 1. One-Line Launch with NPX (No Rust toolchain needed)
53
-
54
- Launch `figma-rust-mcp` on macOS, Linux, or Windows with zero manual setup:
60
+ ### 1. One-Line Setup & Launch with NPX (No Rust toolchain needed)
55
61
 
56
62
  ```bash
63
+ # Launch interactive MCP server
57
64
  npx figma-rust-mcp
58
65
  ```
66
+ *(Automatically downloads precompiled native binary for macOS Apple Silicon/Intel, Linux, or Windows).*
67
+
68
+ ---
69
+
70
+ ### 2. Install the Figma Plugin (Permanent One-Time Setup)
71
+
72
+ Create the permanent Thin Loader folder in your home directory:
73
+
74
+ ```bash
75
+ npx figma-rust-mcp --setup-plugin
76
+ ```
59
77
 
60
- This automatically downloads the prebuilt native binary for your OS and architecture and starts the server.
78
+ 1. Open **Figma Desktop**.
79
+ 2. Go to **Plugins** β†’ **Development** β†’ **Import plugin from manifest...**
80
+ 3. Select `~/.figma-mcp/plugin/manifest.json` (or `plugin/manifest.json` inside this repository).
81
+ 4. Run the plugin: **Plugins** β†’ **Development** β†’ **Figma MCP Bridge**.
82
+ 5. **Done!** Future updates to `figma-rust-mcp` will stream to Figma automatically.
61
83
 
62
84
  ---
63
85
 
64
- ### 2. Auto-Start as Background Service (Recommended for SSE)
86
+ ### 3. Run as Auto-Start Background Service (Recommended)
65
87
 
66
- To make `figma-rust-mcp` start automatically upon OS login and run in the background across all your AI IDEs:
88
+ Run `figma-rust-mcp` seamlessly in the background across all your AI editors without keeping a terminal open:
67
89
 
68
90
  ```bash
69
- # Install and start auto-start background service (macOS LaunchAgent, Linux systemd, Windows Task Scheduler)
91
+ # Install and start background service (macOS LaunchAgent, Linux systemd, Windows Task)
70
92
  npx figma-rust-mcp --install-service
71
93
 
72
- # Update/Upgrade to the latest version and hot-reload background service
73
- npx -y figma-rust-mcp@latest --install-service
74
-
75
- # Check service status
94
+ # Check live background service status & bridge health
76
95
  npx figma-rust-mcp --service-status
77
96
 
78
- # Uninstall background service
97
+ # One-command upgrade to latest version & auto-restart background service
98
+ npx figma-rust-mcp --upgrade
99
+
100
+ # Add convenient 'figma-mcp' alias to your shell profile (~/.zshrc, ~/.bashrc)
101
+ npx figma-rust-mcp --alias
102
+
103
+ # Stop and remove background service
79
104
  npx figma-rust-mcp --uninstall-service
80
105
  ```
81
106
 
82
107
  ---
83
108
 
84
- ### 3. Build from Source (Rust)
109
+ ### 4. Build from Source (Optional)
85
110
 
86
- Prerequisites: [Rust toolchain](https://rustup.rs/) (`cargo >= 1.80`).
111
+ If you prefer building directly with the [Rust toolchain](https://rustup.rs/) (`cargo >= 1.80`):
87
112
 
88
113
  ```bash
89
114
  git clone https://github.com/BuiHung1612/figma-mcp.git
@@ -94,16 +119,6 @@ cargo build --release
94
119
 
95
120
  ---
96
121
 
97
- ### 4. Install the Figma Plugin
98
-
99
- 1. Open **Figma Desktop**.
100
- 2. Go to **Plugins** β†’ **Development** β†’ **Import plugin from manifest...**
101
- 3. Select `plugin/manifest.json` from this repository.
102
- 4. Run the plugin (**Plugins** β†’ **Development** β†’ **Figma MCP Bridge**).
103
- 5. The plugin UI will display a green dot (**Connected**).
104
-
105
- ---
106
-
107
122
  ### 5. Configure Your MCP Client
108
123
 
109
124
  #### Google Antigravity (SSE Transport - Recommended)
package/bin/figma-mcp.js CHANGED
@@ -371,13 +371,151 @@ function isServiceInstalled() {
371
371
  return false;
372
372
  }
373
373
 
374
+ function setupPlugin(customDir) {
375
+ const pluginDir = customDir || path.join(os.homedir(), '.figma-mcp', 'plugin');
376
+ const sourcePluginDir = path.resolve(__dirname, '../plugin');
377
+
378
+ fs.mkdirSync(pluginDir, { recursive: true });
379
+
380
+ const files = ['manifest.json', 'code.js', 'ui.html', 'icon16.png', 'icon32.png'];
381
+ for (const f of files) {
382
+ const src = path.join(sourcePluginDir, f);
383
+ const dest = path.join(pluginDir, f);
384
+ if (fs.existsSync(src)) {
385
+ fs.copyFileSync(src, dest);
386
+ }
387
+ }
388
+
389
+ const manifestPath = path.join(pluginDir, 'manifest.json');
390
+ console.log(`\n\x1b[32mβœ“ Figma MCP Dynamic Thin Plugin installed to:\x1b[0m`);
391
+ console.log(` \x1b[36m${manifestPath}\x1b[0m\n`);
392
+ console.log(`\x1b[1mTo connect Figma (Do this ONCE forever):\x1b[0m`);
393
+ console.log(` 1. Open Figma Desktop`);
394
+ console.log(` 2. Go to Plugins β†’ Development β†’ Import plugin from manifest...`);
395
+ console.log(` 3. Select: ${manifestPath}`);
396
+ console.log(` 4. Done! All future updates load dynamically from figma-mcp without file re-imports.\n`);
397
+ return manifestPath;
398
+ }
399
+
400
+ function isNewer(latest, current) {
401
+ const pLatest = latest.split('.').map(n => parseInt(n, 10) || 0);
402
+ const pCurrent = current.split('.').map(n => parseInt(n, 10) || 0);
403
+ for (let i = 0; i < 3; i++) {
404
+ if ((pLatest[i] || 0) > (pCurrent[i] || 0)) return true;
405
+ if ((pLatest[i] || 0) < (pCurrent[i] || 0)) return false;
406
+ }
407
+ return false;
408
+ }
409
+
410
+ function checkForUpdatesAsync() {
411
+ const updateStateFile = path.join(os.homedir(), '.figma-mcp', 'update-check.json');
412
+ try {
413
+ if (fs.existsSync(updateStateFile)) {
414
+ const state = JSON.parse(fs.readFileSync(updateStateFile, 'utf8'));
415
+ const now = Date.now();
416
+ if (state.lastChecked && (now - state.lastChecked < 6 * 3600 * 1000)) {
417
+ if (state.latestVersion && isNewer(state.latestVersion, pkgVersion)) {
418
+ process.stderr.write(`\n\x1b[36m⚑ Update available: v${pkgVersion} β†’ v${state.latestVersion} (Run: npx figma-rust-mcp --upgrade)\x1b[0m\n\n`);
419
+ }
420
+ return;
421
+ }
422
+ }
423
+ } catch (_) {}
424
+
425
+ const req = https.get('https://registry.npmjs.org/figma-rust-mcp/latest', {
426
+ headers: { 'User-Agent': 'figma-mcp-updater' },
427
+ timeout: 2000
428
+ }, (res) => {
429
+ let data = '';
430
+ res.on('data', chunk => { data += chunk; });
431
+ res.on('end', () => {
432
+ try {
433
+ if (res.statusCode === 200) {
434
+ const json = JSON.parse(data);
435
+ const latest = json.version;
436
+ fs.mkdirSync(path.join(os.homedir(), '.figma-mcp'), { recursive: true });
437
+ fs.writeFileSync(updateStateFile, JSON.stringify({
438
+ lastChecked: Date.now(),
439
+ latestVersion: latest
440
+ }, null, 2));
441
+ if (latest && isNewer(latest, pkgVersion)) {
442
+ process.stderr.write(`\n\x1b[36m⚑ Update available: v${pkgVersion} β†’ v${latest}\x1b[0m\n\x1b[36m Run: npx figma-rust-mcp --upgrade\x1b[0m\n\n`);
443
+ }
444
+ }
445
+ } catch (_) {}
446
+ });
447
+ });
448
+ req.on('error', () => {});
449
+ req.on('timeout', () => req.destroy());
450
+ }
451
+
452
+ async function upgrade() {
453
+ console.log('\x1b[36m[figma-mcp]\x1b[0m Checking for updates and upgrading figma-rust-mcp...');
454
+ try {
455
+ execSync('npm install -g figma-rust-mcp@latest', { stdio: 'inherit' });
456
+ console.log('\x1b[32mβœ“ Upgraded figma-rust-mcp to latest version.\x1b[0m');
457
+ setupPlugin();
458
+ if (isServiceInstalled()) {
459
+ console.log('\x1b[36mUpdating background service binary...\x1b[0m');
460
+ const binPath = await findOrDownloadBinary();
461
+ await installService(binPath);
462
+ }
463
+ } catch (err) {
464
+ console.log('\x1b[33mTip: Run directly with latest version:\x1b[0m\n npx -y figma-rust-mcp@latest\n');
465
+ }
466
+ }
467
+
468
+ function setupAlias() {
469
+ const platform = process.platform;
470
+ if (platform === 'win32') {
471
+ console.log('\x1b[33mOn Windows, install globally for direct command access:\x1b[0m\n npm install -g figma-rust-mcp\n');
472
+ return;
473
+ }
474
+
475
+ const shellRc = process.env.SHELL && process.env.SHELL.includes('zsh')
476
+ ? path.join(os.homedir(), '.zshrc')
477
+ : path.join(os.homedir(), '.bashrc');
478
+
479
+ const aliasLine = "alias figma-mcp='npx figma-rust-mcp'";
480
+ try {
481
+ let content = fs.existsSync(shellRc) ? fs.readFileSync(shellRc, 'utf8') : '';
482
+ if (!content.includes('alias figma-mcp=')) {
483
+ fs.appendFileSync(shellRc, `\n# Figma MCP alias\n${aliasLine}\n`);
484
+ console.log(`\x1b[32mβœ“ Added alias to ${shellRc}:\x1b[0m`);
485
+ console.log(` ${aliasLine}`);
486
+ console.log(`\nRun \x1b[36msource ${shellRc}\x1b[0m to start using \x1b[1mfigma-mcp\x1b[0m command directly!`);
487
+ } else {
488
+ console.log(`\x1b[32mβœ“ Alias already exists in ${shellRc}\x1b[0m`);
489
+ }
490
+ } catch (err) {
491
+ console.error(`Failed to configure alias: ${err.message}`);
492
+ }
493
+ }
494
+
374
495
  // ─── MAIN ─────────────────────────────────────────────────────────────────────
375
496
 
376
497
  async function main() {
377
498
  const args = process.argv.slice(2);
378
499
 
500
+ if (args.includes('--upgrade') || args.includes('--update')) {
501
+ await upgrade();
502
+ return;
503
+ }
504
+
505
+ if (args.includes('--alias')) {
506
+ setupAlias();
507
+ return;
508
+ }
509
+
510
+ if (args.includes('--setup-plugin') || args.includes('--export-plugin') || args.includes('--setup')) {
511
+ const customDir = args.find(a => !a.startsWith('-') && a !== '--setup-plugin' && a !== '--export-plugin' && a !== '--setup');
512
+ setupPlugin(customDir);
513
+ return;
514
+ }
515
+
379
516
  if (args.includes('--install-service')) {
380
517
  try {
518
+ setupPlugin();
381
519
  const binPath = await findOrDownloadBinary();
382
520
  await installService(binPath);
383
521
  } catch (err) {
@@ -409,6 +547,9 @@ async function main() {
409
547
  return;
410
548
  }
411
549
 
550
+ // Non-blocking auto update check
551
+ checkForUpdatesAsync();
552
+
412
553
  try {
413
554
  const binPath = await findOrDownloadBinary();
414
555
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "figma-rust-mcp",
3
- "version": "3.0.5",
3
+ "version": "3.2.1",
4
4
  "description": "Claude Code to Figma β€” Bidirectional MCP bridge. AI draws UI on Figma canvas, reads designs back. Works with Claude, Cursor, VS Code, Windsurf, Antigravity. No API key needed.",
5
5
  "mcpName": "io.github.BuiHung1612/figma-mcp",
6
6
  "type": "module",