figma-console-mcp-cli 0.2.1 → 0.4.0

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
@@ -16,9 +16,23 @@ The wizard walks you through:
16
16
  2. **Authentication** — prompts for your Figma Personal Access Token
17
17
  3. **Client detection** — finds installed AI clients and lets you pick which to configure
18
18
  4. **Configuration** — injects the MCP server config into each client
19
- 5. **Connection setup** — choose Bridge (plugin) or CDP (debug port) and get setup instructions
19
+ 5. **Connection setup** — install the Bridge plugin and get setup instructions
20
20
  6. **Health check** — verifies the connection to Figma is working
21
21
 
22
+ ## Doctor Command
23
+
24
+ Already set up? Use `doctor` to audit and manage your integrations:
25
+
26
+ ```bash
27
+ npx figma-console-mcp-cli doctor
28
+ ```
29
+
30
+ The doctor command scans all supported clients and shows their integration status, then lets you:
31
+
32
+ - **Update** your Figma token across all configured clients
33
+ - **Remove** the integration from selected clients
34
+ - **Add** the integration to newly-installed clients
35
+
22
36
  ## Supported Clients
23
37
 
24
38
  - Claude Code
@@ -26,10 +40,9 @@ The wizard walks you through:
26
40
  - Cursor
27
41
  - Windsurf
28
42
 
29
- ## Connection Methods
43
+ ## Connection Method
30
44
 
31
- - **Desktop Bridge Plugin** (recommended) — install a Figma plugin, no restart needed
32
- - **CDP Debug Mode** — relaunch Figma with remote debugging enabled on port 9222
45
+ - **Desktop Bridge Plugin** — install a Figma plugin, no restart needed
33
46
 
34
47
  ## Requirements
35
48
 
package/dist/index.js CHANGED
@@ -1,38 +1,58 @@
1
1
  #!/usr/bin/env node
2
- import { Command } from "commander";
3
- import chalk from "chalk";
4
- import { runSystemCheck } from "./steps/systemCheck.js";
5
- import { promptForToken } from "./steps/auth.js";
6
- import { detectAndSelectClients } from "./steps/clientDetect.js";
7
- import { configureClients } from "./steps/configure.js";
8
- import { setupConnection } from "./steps/connection.js";
9
- import { runHealthCheck } from "./steps/healthCheck.js";
2
+ import { Command } from 'commander';
3
+ import chalk from 'chalk';
4
+ import { runSystemCheck } from './steps/systemCheck.js';
5
+ import { promptForToken } from './steps/auth.js';
6
+ import { detectAndSelectClients } from './steps/clientDetect.js';
7
+ import { configureClients } from './steps/configure.js';
8
+ import { selectInstallMethod } from './steps/installMethod.js';
9
+ import { setupConnection } from './steps/connection.js';
10
+ import { runHealthCheck } from './steps/healthCheck.js';
11
+ import { runDoctor } from './steps/doctor.js';
10
12
  const program = new Command();
11
13
  program
12
- .name("figma-console-mcp-cli")
13
- .description("Configure Figma Console MCP across AI coding clients")
14
- .version("1.0.0")
14
+ .name('figma-console-mcp-cli')
15
+ .description('Configure Figma Console MCP across AI coding clients')
16
+ .version('0.2.1')
15
17
  .action(async () => {
16
- console.log(chalk.bold.cyan("\n Figma Console MCP — Setup Wizard\n"));
18
+ console.log(chalk.bold.cyan('\n Figma Console MCP — Setup Wizard\n'));
17
19
  try {
18
20
  await runSystemCheck();
19
- const token = await promptForToken();
20
21
  const clients = await detectAndSelectClients();
21
22
  if (clients.length === 0) {
22
- console.log(chalk.yellow("\nNo clients selected. Exiting.\n"));
23
+ console.log(chalk.yellow('\nNo clients selected. Exiting.\n'));
23
24
  return;
24
25
  }
25
- const configured = await configureClients(clients, token);
26
+ const token = await promptForToken();
27
+ const installMethod = await selectInstallMethod();
28
+ const configured = await configureClients(clients, token, installMethod);
26
29
  if (configured.length === 0) {
27
- console.log(chalk.yellow("\nNo clients were configured. Exiting.\n"));
30
+ console.log(chalk.yellow('\nNo clients were configured. Exiting.\n'));
28
31
  return;
29
32
  }
30
- const method = await setupConnection();
31
- await runHealthCheck(configured, method);
33
+ await setupConnection(installMethod);
34
+ await runHealthCheck(configured);
35
+ }
36
+ catch (err) {
37
+ if (err.name === 'ExitPromptError') {
38
+ console.log(chalk.dim('\nSetup cancelled.\n'));
39
+ return;
40
+ }
41
+ console.error(chalk.red(`\nError: ${err instanceof Error ? err.message : err}\n`));
42
+ process.exit(1);
43
+ }
44
+ });
45
+ program
46
+ .command('doctor')
47
+ .description('Diagnose and manage Figma Console MCP integrations')
48
+ .action(async () => {
49
+ console.log(chalk.bold.cyan('\n Figma Console MCP — Doctor\n'));
50
+ try {
51
+ await runDoctor();
32
52
  }
33
53
  catch (err) {
34
- if (err.name === "ExitPromptError") {
35
- console.log(chalk.dim("\nSetup cancelled.\n"));
54
+ if (err.name === 'ExitPromptError') {
55
+ console.log(chalk.dim('\nDoctor cancelled.\n'));
36
56
  return;
37
57
  }
38
58
  console.error(chalk.red(`\nError: ${err instanceof Error ? err.message : err}\n`));
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,uBAAuB,CAAC;KAC7B,WAAW,CAAC,sDAAsD,CAAC;KACnE,OAAO,CAAC,OAAO,CAAC;KAChB,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC,CAAC;IAEvE,IAAI,CAAC;QACH,MAAM,cAAc,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,MAAM,cAAc,EAAE,CAAC;QACrC,MAAM,OAAO,GAAG,MAAM,sBAAsB,EAAE,CAAC;QAE/C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,mCAAmC,CAAC,CAAC,CAAC;YAC/D,OAAO;QACT,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,gBAAgB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAE1D,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,0CAA0C,CAAC,CAAC,CAAC;YACtE,OAAO;QACT,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,eAAe,EAAE,CAAC;QACvC,MAAM,cAAc,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAC3C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAAyB,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;YAC1D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC,CAAC;YAC/C,OAAO;QACT,CAAC;QACD,OAAO,CAAC,KAAK,CACX,KAAK,CAAC,GAAG,CAAC,YAAY,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CACpE,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -5,9 +5,14 @@ export async function promptForToken() {
5
5
  console.log(` Generate a Personal Access Token at:\n ${chalk.cyan('https://developers.figma.com/docs/rest-api/authentication/#generate-a-personal-access-token')}\n`);
6
6
  while (true) {
7
7
  const token = await password({
8
- message: 'Paste your Figma Personal Access Token:',
8
+ message: 'Paste your Figma Personal Access Token (or leave empty to exit):',
9
9
  mask: '*',
10
10
  });
11
+ if (!token) {
12
+ const error = new Error('Setup cancelled');
13
+ error.name = 'ExitPromptError';
14
+ throw error;
15
+ }
11
16
  if (token.startsWith('figd_')) {
12
17
  console.log(chalk.green(' ✓ Token accepted'));
13
18
  return token;
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/steps/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC,CAAC;IACvD,OAAO,CAAC,GAAG,CACT,6CAA6C,KAAK,CAAC,IAAI,CACrD,6FAA6F,CAC9F,IAAI,CACN,CAAC;IAEF,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC;YAC3B,OAAO,EAAE,yCAAyC;YAClD,IAAI,EAAE,GAAG;SACV,CAAC,CAAC;QAEH,IAAI,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC;YAC/C,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,2DAA2D,CAAC,CAAC,CAAC;IACtF,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/steps/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC,CAAC;IACvD,OAAO,CAAC,GAAG,CACT,6CAA6C,KAAK,CAAC,IAAI,CACrD,6FAA6F,CAC9F,IAAI,CACN,CAAC;IAEF,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC;YAC3B,OAAO,EACL,kEAAkE;YACpE,IAAI,EAAE,GAAG;SACV,CAAC,CAAC;QAEH,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;YAC3C,KAAK,CAAC,IAAI,GAAG,iBAAiB,CAAC;YAC/B,MAAM,KAAK,CAAC;QACd,CAAC;QAED,IAAI,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC;YAC/C,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,GAAG,CAAC,2DAA2D,CAAC,CACvE,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -3,5 +3,7 @@ export interface Client {
3
3
  id: string;
4
4
  configPath: string | null;
5
5
  detected: boolean;
6
+ configured: boolean;
6
7
  }
8
+ export declare function getClients(): Promise<Client[]>;
7
9
  export declare function detectAndSelectClients(): Promise<Client[]>;
@@ -1,57 +1,101 @@
1
1
  import fs from 'node:fs';
2
- import { execSync } from 'node:child_process';
2
+ import { exec } from 'node:child_process';
3
3
  import { checkbox } from '@inquirer/prompts';
4
4
  import chalk from 'chalk';
5
- import { getPlatform, getAppDataPath, resolveConfigPath } from '../utils/platform.js';
6
- function isCommandAvailable(cmd) {
5
+ import { getPlatform, getAppDataPath, resolveConfigPath, } from '../utils/platform.js';
6
+ import { readJsonConfig } from '../utils/config.js';
7
+ function execAsync(cmd) {
8
+ return new Promise((resolve, reject) => {
9
+ exec(cmd, { encoding: 'utf-8' }, (err, stdout) => {
10
+ if (err)
11
+ reject(err);
12
+ else
13
+ resolve(stdout);
14
+ });
15
+ });
16
+ }
17
+ async function isCommandAvailable(cmd) {
7
18
  try {
8
- execSync(`which ${cmd}`, { stdio: 'ignore' });
19
+ await execAsync(`which ${cmd}`);
9
20
  return true;
10
21
  }
11
22
  catch {
12
23
  return false;
13
24
  }
14
25
  }
15
- function getClients() {
26
+ function isJsonClientConfigured(configPath) {
27
+ const config = readJsonConfig(configPath);
28
+ const mcpServers = config.mcpServers;
29
+ return mcpServers?.['figma-console'] !== undefined;
30
+ }
31
+ async function isClaudeCodeConfigured() {
32
+ try {
33
+ const output = await execAsync('claude mcp list');
34
+ return output.includes('figma-console');
35
+ }
36
+ catch {
37
+ return false;
38
+ }
39
+ }
40
+ export async function getClients() {
16
41
  const platform = getPlatform();
17
42
  const appData = getAppDataPath();
18
43
  const claudeDesktopPath = platform === 'windows'
19
44
  ? `${appData}\\Claude\\claude_desktop_config.json`
20
45
  : `${appData}/Claude/claude_desktop_config.json`;
46
+ const cursorPath = resolveConfigPath('.cursor', 'mcp.json');
47
+ const windsurfPath = resolveConfigPath('.codeium', 'windsurf', 'mcp_config.json');
48
+ const claudeCodeDetected = await isCommandAvailable('claude');
21
49
  return [
22
50
  {
23
51
  name: 'Claude Code',
24
52
  id: 'claude-code',
25
53
  configPath: null,
26
- detected: isCommandAvailable('claude'),
54
+ detected: claudeCodeDetected,
55
+ configured: claudeCodeDetected && (await isClaudeCodeConfigured()),
27
56
  },
28
57
  {
29
58
  name: 'Claude Desktop',
30
59
  id: 'claude-desktop',
31
60
  configPath: claudeDesktopPath,
32
61
  detected: fs.existsSync(claudeDesktopPath),
62
+ configured: fs.existsSync(claudeDesktopPath) &&
63
+ isJsonClientConfigured(claudeDesktopPath),
33
64
  },
34
65
  {
35
66
  name: 'Cursor',
36
67
  id: 'cursor',
37
- configPath: resolveConfigPath('.cursor', 'mcp.json'),
38
- detected: fs.existsSync(resolveConfigPath('.cursor', 'mcp.json')),
68
+ configPath: cursorPath,
69
+ detected: fs.existsSync(cursorPath),
70
+ configured: fs.existsSync(cursorPath) && isJsonClientConfigured(cursorPath),
39
71
  },
40
72
  {
41
73
  name: 'Windsurf',
42
74
  id: 'windsurf',
43
- configPath: resolveConfigPath('.codeium', 'windsurf', 'mcp_config.json'),
44
- detected: fs.existsSync(resolveConfigPath('.codeium', 'windsurf', 'mcp_config.json')),
75
+ configPath: windsurfPath,
76
+ detected: fs.existsSync(windsurfPath),
77
+ configured: fs.existsSync(windsurfPath) && isJsonClientConfigured(windsurfPath),
45
78
  },
46
79
  ];
47
80
  }
48
81
  export async function detectAndSelectClients() {
49
82
  console.log(chalk.bold('\n🔎 Client Detection\n'));
50
- const clients = getClients();
83
+ const SPINNER = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
84
+ const msg = 'Scanning for AI clients…';
85
+ let frame = 0;
86
+ const spinner = setInterval(() => {
87
+ const f = SPINNER[frame % SPINNER.length];
88
+ process.stdout.write(`\r ${chalk.cyan(f)} ${msg}`);
89
+ frame++;
90
+ }, 80);
91
+ const clients = await getClients();
92
+ clearInterval(spinner);
93
+ process.stdout.write(`\r${' '.repeat(msg.length + 6)}\r`);
51
94
  const detected = clients.filter((c) => c.detected);
52
95
  const notDetected = clients.filter((c) => !c.detected);
53
96
  for (const c of detected) {
54
- console.log(chalk.green(` ✓ ${c.name} detected`));
97
+ const tag = c.configured ? chalk.cyan(' (already configured)') : '';
98
+ console.log(chalk.green(` ✓ ${c.name} detected`) + tag);
55
99
  }
56
100
  for (const c of notDetected) {
57
101
  console.log(chalk.dim(` · ${c.name} not found`));
@@ -60,6 +104,12 @@ export async function detectAndSelectClients() {
60
104
  console.log(chalk.yellow('\n No supported clients detected.'));
61
105
  return [];
62
106
  }
107
+ const hasConfigured = detected.some((c) => c.configured);
108
+ if (hasConfigured) {
109
+ console.log(chalk.dim('\n Tip: To update your Figma token or remove the integration from configured'));
110
+ console.log(chalk.dim(' clients, quit and run: ') +
111
+ chalk.cyan('npx figma-console-mcp-cli doctor'));
112
+ }
63
113
  console.log('');
64
114
  const selected = await checkbox({
65
115
  message: 'Select clients to configure:',
@@ -1 +1 @@
1
- {"version":3,"file":"clientDetect.js","sourceRoot":"","sources":["../../src/steps/clientDetect.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"clientDetect.js","sourceRoot":"","sources":["../../src/steps/clientDetect.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,6 @@
1
1
  import type { Client } from './clientDetect.js';
2
- export declare function configureClients(clients: Client[], token: string): Promise<Client[]>;
2
+ import type { InstallMethod } from './installMethod.js';
3
+ export declare function configureClients(clients: Client[], token: string, method?: InstallMethod): Promise<Client[]>;
4
+ export declare function isFigmaConsoleConfigured(): boolean;
5
+ export declare function configureClaudeCode(token: string, method?: InstallMethod): Promise<boolean>;
6
+ export declare function configureJsonClient(client: Client, token: string, method?: InstallMethod): void;
@@ -1,22 +1,22 @@
1
1
  import { execSync } from 'node:child_process';
2
2
  import chalk from 'chalk';
3
3
  import { select } from '@inquirer/prompts';
4
- import { readJsonConfig, writeJsonConfig, mergeServerConfig } from '../utils/config.js';
4
+ import { readJsonConfig, writeJsonConfig, mergeServerConfig, } from '../utils/config.js';
5
5
  import { getPlatform } from '../utils/platform.js';
6
- export async function configureClients(clients, token) {
6
+ export async function configureClients(clients, token, method = { type: 'npx' }) {
7
7
  console.log(chalk.bold('\n⚙️ Configuring MCP Server\n'));
8
8
  const configured = [];
9
9
  for (const client of clients) {
10
10
  try {
11
11
  if (client.id === 'claude-code') {
12
- const ok = await configureClaudeCode(token);
12
+ const ok = await configureClaudeCode(token, method);
13
13
  if (!ok) {
14
14
  console.log(chalk.yellow(` ⊘ ${client.name} skipped`));
15
15
  continue;
16
16
  }
17
17
  }
18
18
  else if (client.configPath) {
19
- configureJsonClient(client, token);
19
+ configureJsonClient(client, token, method);
20
20
  }
21
21
  configured.push(client);
22
22
  console.log(chalk.green(` ✓ ${client.name} configured`));
@@ -33,7 +33,10 @@ function isClaudeRunning() {
33
33
  const cmd = getPlatform() === 'windows'
34
34
  ? 'tasklist /FI "IMAGENAME eq claude.exe" /NH'
35
35
  : 'pgrep -x claude';
36
- const output = execSync(cmd, { encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'] });
36
+ const output = execSync(cmd, {
37
+ encoding: 'utf-8',
38
+ stdio: ['ignore', 'pipe', 'ignore'],
39
+ });
37
40
  if (getPlatform() === 'windows') {
38
41
  return output.includes('claude.exe');
39
42
  }
@@ -43,7 +46,7 @@ function isClaudeRunning() {
43
46
  return false; // pgrep exits 1 if no match
44
47
  }
45
48
  }
46
- function isFigmaConsoleConfigured() {
49
+ export function isFigmaConsoleConfigured() {
47
50
  try {
48
51
  const output = execSync('claude mcp list', {
49
52
  encoding: 'utf-8',
@@ -55,7 +58,14 @@ function isFigmaConsoleConfigured() {
55
58
  return false;
56
59
  }
57
60
  }
58
- async function configureClaudeCode(token) {
61
+ function buildClaudeCodeCommand(method) {
62
+ if (method.type === 'local') {
63
+ return `node ${method.path}`;
64
+ }
65
+ return 'npx -y figma-console-mcp@latest';
66
+ }
67
+ export async function configureClaudeCode(token, method = { type: 'npx' }) {
68
+ const serverCommand = buildClaudeCodeCommand(method);
59
69
  while (isClaudeRunning()) {
60
70
  console.log(chalk.yellow('\n ⚠ Claude Code appears to be running.'));
61
71
  console.log(chalk.yellow(' It holds a lock that prevents `claude mcp add` from succeeding.'));
@@ -63,13 +73,13 @@ async function configureClaudeCode(token) {
63
73
  const action = await select({
64
74
  message: 'What would you like to do?',
65
75
  choices: [
66
- { name: 'I\'ve closed Claude Code — retry', value: 'retry' },
76
+ { name: "I've closed Claude Code — retry", value: 'retry' },
67
77
  { name: 'Skip Claude Code setup', value: 'skip' },
68
78
  ],
69
79
  });
70
80
  if (action === 'skip') {
71
81
  console.log(chalk.dim(' Skipped. You can configure manually later:'));
72
- console.log(chalk.dim(` claude mcp add figma-console -s user -e FIGMA_ACCESS_TOKEN=<token> -e ENABLE_MCP_APPS=true -- npx -y figma-console-mcp@latest`));
82
+ console.log(chalk.dim(` claude mcp add figma-console -s user -e FIGMA_ACCESS_TOKEN=<token> -e ENABLE_MCP_APPS=true -- ${serverCommand}`));
73
83
  return false;
74
84
  }
75
85
  // action === 'retry' → loop continues, re-checks isClaudeRunning()
@@ -77,13 +87,13 @@ async function configureClaudeCode(token) {
77
87
  if (isFigmaConsoleConfigured()) {
78
88
  execSync('claude mcp remove figma-console -s user', { stdio: 'ignore' });
79
89
  }
80
- execSync(`claude mcp add figma-console -s user -e FIGMA_ACCESS_TOKEN=${token} -e ENABLE_MCP_APPS=true -- npx -y figma-console-mcp@latest`, { stdio: 'ignore' });
90
+ execSync(`claude mcp add figma-console -s user -e FIGMA_ACCESS_TOKEN=${token} -e ENABLE_MCP_APPS=true -- ${serverCommand}`, { stdio: 'ignore' });
81
91
  return true;
82
92
  }
83
- function configureJsonClient(client, token) {
93
+ export function configureJsonClient(client, token, method = { type: 'npx' }) {
84
94
  const configPath = client.configPath;
85
95
  const existing = readJsonConfig(configPath);
86
- const merged = mergeServerConfig(existing, token);
96
+ const merged = mergeServerConfig(existing, token, method);
87
97
  writeJsonConfig(configPath, merged);
88
98
  }
89
99
  //# sourceMappingURL=configure.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"configure.js","sourceRoot":"","sources":["../../src/steps/configure.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"configure.js","sourceRoot":"","sources":["../../src/steps/configure.ts"],"names":[],"mappings":"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"}
@@ -1 +1,2 @@
1
- export declare function setupConnection(): Promise<"bridge" | "cdp">;
1
+ import type { InstallMethod } from './installMethod.js';
2
+ export declare function setupConnection(installMethod: InstallMethod): Promise<void>;
@@ -1,140 +1,48 @@
1
- import { spawnSync } from "node:child_process";
2
- import { existsSync } from "node:fs";
3
- import { join } from "node:path";
4
- import { input, select } from "@inquirer/prompts";
5
- import chalk from "chalk";
6
- import { getHomedir, getPlatform } from "../utils/platform.js";
7
- const REPO_URL = "https://github.com/southleft/figma-console-mcp.git";
8
- const DEFAULT_CLONE_DIR_NAME = "figma-console-mcp";
9
- export async function setupConnection() {
10
- console.log(chalk.bold("\n🔌 Figma Connection Method\n"));
11
- const method = await select({
12
- message: "How do you want to connect to Figma?",
13
- choices: [
14
- {
15
- name: "Desktop Bridge Plugin (Recommended)",
16
- value: "bridge",
17
- description: "Install a Figma plugin — no restart needed",
18
- },
19
- {
20
- name: "CDP Debug Mode",
21
- value: "cdp",
22
- description: "Relaunch Figma with remote debugging enabled",
23
- },
24
- ],
25
- });
26
- if (method === "bridge") {
27
- await setupBridge();
1
+ import { spawnSync } from 'node:child_process';
2
+ import { dirname, join } from 'node:path';
3
+ import { existsSync } from 'node:fs';
4
+ import chalk from 'chalk';
5
+ import { MANIFEST_PATH_SUFFIX } from '../utils/constants.js';
6
+ export async function setupConnection(installMethod) {
7
+ console.log(chalk.bold('\n🔌 Figma Connection Method\n'));
8
+ const repoDir = installMethod.type === 'local'
9
+ ? dirname(dirname(installMethod.path))
10
+ : undefined;
11
+ await setupBridge(repoDir);
12
+ }
13
+ async function setupBridge(existingRepoDir) {
14
+ console.log(chalk.bold('\n Desktop Bridge Setup:\n'));
15
+ let manifestPath;
16
+ if (existingRepoDir) {
17
+ manifestPath = join(existingRepoDir, MANIFEST_PATH_SUFFIX);
18
+ if (!existsSync(manifestPath)) {
19
+ console.log(chalk.red(`\n Error: Bridge manifest not found at: ${manifestPath}`));
20
+ return;
21
+ }
28
22
  }
29
23
  else {
30
- setupCDP();
31
- }
32
- return method;
33
- }
34
- function isGitInstalled() {
35
- try {
36
- const result = spawnSync("git", ["--version"], {
37
- encoding: "utf-8",
38
- timeout: 5_000,
39
- stdio: ["ignore", "pipe", "ignore"],
24
+ console.log(chalk.dim(' Locating plugin path…'));
25
+ const result = spawnSync('npx', ['figma-console-mcp@latest', '--print-path'], {
26
+ encoding: 'utf-8',
27
+ timeout: 60_000,
28
+ stdio: ['ignore', 'pipe', 'pipe'],
29
+ shell: true,
40
30
  });
41
- return result.status === 0;
42
- }
43
- catch {
44
- return false;
45
- }
46
- }
47
- function isExistingClone(dir) {
48
- return (existsSync(join(dir, ".git")) &&
49
- existsSync(join(dir, "figma-desktop-bridge", "manifest.json")));
50
- }
51
- function cloneOrUpdateRepo(targetDir) {
52
- const manifestPath = join(targetDir, "figma-desktop-bridge", "manifest.json");
53
- if (isExistingClone(targetDir)) {
54
- console.log(chalk.dim(" Existing clone detected — pulling latest…"));
55
- try {
56
- spawnSync("git", ["-C", targetDir, "pull"], {
57
- encoding: "utf-8",
58
- timeout: 30_000,
59
- stdio: ["ignore", "pipe", "pipe"],
60
- });
61
- }
62
- catch {
63
- // non-fatal — existing clone is still usable
31
+ if (result.status !== 0) {
32
+ console.log(chalk.red(`\n Error: Failed to run npx figma-console-mcp@latest --print-path`));
33
+ if (result.stderr) {
34
+ console.log(chalk.red(` ${result.stderr.trim()}`));
35
+ }
36
+ return;
64
37
  }
65
- return manifestPath;
66
- }
67
- if (existsSync(targetDir)) {
68
- throw new Error(`Directory already exists but is not the figma-console-mcp repo: ${targetDir}`);
69
- }
70
- console.log(chalk.dim(" Cloning figma-console-mcp…"));
71
- const result = spawnSync("git", ["clone", REPO_URL, targetDir], {
72
- encoding: "utf-8",
73
- timeout: 60_000,
74
- stdio: ["ignore", "pipe", "pipe"],
75
- });
76
- if (result.status !== 0) {
77
- const stderr = result.stderr?.trim() ?? "unknown error";
78
- throw new Error(`git clone failed: ${stderr}`);
79
- }
80
- if (!existsSync(manifestPath)) {
81
- throw new Error(`Clone succeeded but manifest not found at: ${manifestPath}`);
82
- }
83
- return manifestPath;
84
- }
85
- function showManualFallback() {
86
- console.log(chalk.yellow("\n Automatic setup unavailable. Manual steps:\n"));
87
- console.log(` 1. Clone the repo manually:\n`);
88
- console.log(chalk.cyan(` git clone ${REPO_URL}\n`));
89
- console.log(" 2. Open Figma Desktop");
90
- console.log(" 3. Go to Plugins → Development → Import plugin from manifest…");
91
- console.log(" 4. Select: <clone-dir>/figma-desktop-bridge/manifest.json\n");
92
- console.log(" 5. Run the plugin: Plugins → Development → Figma Console Bridge\n");
93
- }
94
- async function setupBridge() {
95
- console.log(chalk.bold("\n Desktop Bridge Setup:\n"));
96
- if (!isGitInstalled()) {
97
- console.log(chalk.yellow(" git is not installed or not on PATH."));
98
- showManualFallback();
99
- return;
100
- }
101
- const defaultDir = join(getHomedir(), DEFAULT_CLONE_DIR_NAME);
102
- const targetDir = await input({
103
- message: "Where should we clone figma-console-mcp?",
104
- default: defaultDir,
105
- });
106
- let manifestPath;
107
- try {
108
- manifestPath = cloneOrUpdateRepo(targetDir.trim());
109
- }
110
- catch (err) {
111
- const msg = err instanceof Error ? err.message : String(err);
112
- console.log(chalk.red(`\n Error: ${msg}`));
113
- showManualFallback();
38
+ console.log(result.stdout);
114
39
  return;
115
40
  }
116
- console.log(chalk.bold("\n Next steps:\n"));
117
- console.log(" 1. Open Figma Desktop");
118
- console.log(" 2. Go to Plugins → Development → Import plugin from manifest…");
119
- console.log(" 3. Select this file:\n");
41
+ console.log(chalk.bold('\n Next steps:\n'));
42
+ console.log(' 1. Open Figma Desktop');
43
+ console.log(' 2. Go to Plugins → Development → Import plugin from manifest…');
44
+ console.log(' 3. Select this file:\n');
120
45
  console.log(chalk.cyan(` ${manifestPath}\n`));
121
- console.log(" 4. Run the plugin: Plugins → Development → Figma Console Bridge\n");
122
- }
123
- function setupCDP() {
124
- const platform = getPlatform();
125
- console.log(chalk.bold("\n CDP Debug Mode Setup:\n"));
126
- if (platform === "macos") {
127
- console.log(" Close Figma if running, then launch with:\n");
128
- console.log(chalk.cyan(" open -a Figma --args --remote-debugging-port=9222\n"));
129
- }
130
- else if (platform === "windows") {
131
- console.log(" Close Figma if running, then launch with:\n");
132
- console.log(chalk.cyan(' "%LOCALAPPDATA%\\Figma\\Figma.exe" --remote-debugging-port=9222\n'));
133
- }
134
- else {
135
- console.log(" Close Figma if running, then relaunch with the flag:\n");
136
- console.log(chalk.cyan(" figma --remote-debugging-port=9222\n"));
137
- }
138
- console.log(" Figma must be restarted with this flag each time you want CDP access.");
46
+ console.log(' 4. Run the plugin: Plugins → Development → Figma Console Bridge\n');
139
47
  }
140
48
  //# sourceMappingURL=connection.js.map