figma-coder-mcp 0.2.0 → 0.2.2

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 (3) hide show
  1. package/README.md +152 -112
  2. package/dist/bin.js +57 -53
  3. package/package.json +3 -5
package/README.md CHANGED
@@ -1,112 +1,152 @@
1
- # figma-coder-mcp
2
-
3
- MCP server **and** CLI that exposes the Figma HTML/Tailwind converter to AI
4
- coding agents (Claude Code, Cursor, …).
5
-
6
- ```bash
7
- npm i -g figma-coder-mcp # or: npx figma-coder-mcp
8
- figma-coder-mcp set-token figd_xxx
9
- ```
10
-
11
- It runs in two modes and picks automatically:
12
-
13
- - **local** (default when a PAT is present): converts using the bundled
14
- [`@figma-to-code/core`](../packages/figma-core) directly. **No backend needed** —
15
- works even if the API server is down. Just provide a Figma PAT.
16
- - **remote**: delegates to a running `figma-to-html-api` over HTTP (`FIGMA_MCP_API`).
17
- Authenticate with **OAuth** (`figma-coder-mcp login`) so no personal access
18
- token lives in your config — the backend holds the OAuth secret.
19
-
20
- Both modes share the **exact same conversion code** (the core package), so output
21
- is identical.
22
-
23
- ## Two ways to authenticate
24
-
25
- | | Option A — Remote + OAuth | Option B — Local + PAT |
26
- |---|---|---|
27
- | Setup | `set-api <url>` then `login` (browser) | `set-token figd_xxx` (or `FIGMA_PAT`) |
28
- | Needs the backend? | Yes | No fully local |
29
- | Survives backend outage? | No | **Yes** |
30
- | Token in your config? | No | Yes (PAT) |
31
-
32
- ```bash
33
- # Option A — OAuth via the backend (no PAT in your config)
34
- figma-coder-mcp set-api http://localhost:4403
35
- figma-coder-mcp login # opens the browser; token is stored for you
36
-
37
- # Option B — fully local with a PAT
38
- figma-coder-mcp set-token figd_xxx
39
- ```
40
-
41
- `login` opens `…/auth/figma/login` in your browser, captures the token the backend
42
- hands back over a one-shot **loopback** server, and stores it in
43
- `~/.figma-mcp/credentials.json`. The access token is **refreshed silently** (using
44
- the stored refresh token) when it expires — re-run `login` only if the refresh
45
- token itself is revoked. Set `FIGMA_MCP_NO_BROWSER=1` on headless/SSH hosts to
46
- print the URL instead of launching a browser.
47
-
48
- ## Tools
49
-
50
- | Tool | What it does |
51
- |------|--------------|
52
- | `get_figma_data` | Returns the deterministic **Style IR** (exact CSS per node) so the agent can generate code itself. Large trees are written to a JSON file and summarised. |
53
- | `convert_figma_to_html` | Produces finished, self-contained **HTML + Tailwind** (assets inlined, optional LLM restructure). The HTML is written to a file; a compact summary + path is returned to keep the agent's context small. |
54
-
55
- ## Setup
56
-
57
- ```bash
58
- # Build the workspace from the repo root
59
- npm install
60
- npm run build
61
-
62
- # Store a Figma personal access token (local mode, no backend)
63
- node figma-mcp/dist/bin.js set-token figd_xxx
64
- # …or set it per-process: FIGMA_PAT=figd_xxx
65
-
66
- # …or use OAuth via a backend instead (no PAT in your config)
67
- node figma-mcp/dist/bin.js set-api http://localhost:4403
68
- node figma-mcp/dist/bin.js login
69
-
70
- # Check how requests will be served (no secrets printed)
71
- node figma-mcp/dist/bin.js status
72
- ```
73
-
74
- ## Register with an agent
75
-
76
- `.mcp.json` (Claude Code) / Cursor MCP config — once installed (`npm i -g`) or via npx:
77
-
78
- ```json
79
- {
80
- "mcpServers": {
81
- "figma": {
82
- "command": "npx",
83
- "args": ["-y", "figma-coder-mcp"],
84
- "env": { "FIGMA_PAT": "figd_xxx" }
85
- }
86
- }
87
- }
88
- ```
89
-
90
- (From a local clone instead, point `command: "node"`, `args: [".../figma-mcp/dist/bin.js"]`.)
91
-
92
- ## One-off CLI (no agent)
93
-
94
- ```bash
95
- figma-coder-mcp convert "https://www.figma.com/design/<key>/Title?node-id=1-23"
96
- figma-coder-mcp convert <fileKey> --node 1:23 --no-assets --out page.html
97
- figma-coder-mcp data <fileKey> --node 1:23
98
- ```
99
-
100
- ## Configuration
101
-
102
- | Var | Meaning |
103
- |-----|---------|
104
- | `FIGMA_PAT` / `FIGMA_TOKEN` | Figma personal access token (local mode). |
105
- | `FIGMA_MCP_API` | Backend converter base URL (remote mode). |
106
- | `FIGMA_MCP_TOKEN` | OAuth/bearer token for the backend (remote mode). Usually set for you by `login`; an explicit value here is used verbatim and never auto-refreshed. |
107
- | `FIGMA_MCP_MODE` | `auto` (default) · `local` · `remote`. Auto prefers local. |
108
- | `FIGMA_MCP_OUT_DIR` | Where HTML/JSON outputs are written. Default `<cwd>/figma-output`. |
109
- | `FIGMA_MCP_NO_BROWSER` | If set, `login` prints the URL instead of opening a browser (headless/SSH). |
110
- | `OLLAMA_CLOUD_URL` / `OLLAMA_API_KEY` / `OLLAMA_CLOUD_MODELS` | Enable the `--llm` restructure pass. |
111
-
112
- Priority for every setting: **flags > env > stored credentials** (`~/.figma-mcp/credentials.json`).
1
+ # figma-coder-mcp
2
+
3
+ > **Figma Coder** is an MCP server and CLI that turns any Figma frame into
4
+ > pixel-faithful, self-contained HTML, right inside your AI coding agent. No
5
+ > screenshots, no rebuilding by hand. Works with any Figma account: no paid
6
+ > plan, completely free.
7
+
8
+ Homepage: **https://figmacoder.sitenow.cloud**
9
+
10
+ `figma-coder-mcp` is one program that is two things at once: an MCP server your
11
+ AI agent talks to, and a command-line tool you can run in a terminal. It runs in
12
+ two modes and picks one automatically: with a Figma token it converts locally on
13
+ your machine; without one it uses the hosted backend. Both modes produce
14
+ identical output.
15
+
16
+ ```bash
17
+ npm i -g figma-coder-mcp # or run on demand with: npx figma-coder-mcp
18
+ ```
19
+
20
+ ## Setup
21
+
22
+ Setup is two steps. Step 1 (required): add the server to your project's
23
+ `.mcp.json`. Step 2: give it access to Figma using either a personal access token
24
+ (local mode) or by signing in with Figma (remote mode).
25
+
26
+ ### Local mode — personal access token
27
+
28
+ Create a personal access token (`figd_…`) in your Figma account settings
29
+ (Settings Security Personal access tokens:
30
+ https://www.figma.com/settings). Add the server to `.mcp.json` with the token in
31
+ the inline `env`:
32
+
33
+ ```json
34
+ {
35
+ "mcpServers": {
36
+ "figma": {
37
+ "command": "npx",
38
+ "args": ["-y", "figma-coder-mcp"],
39
+ "env": { "FIGMA_PAT": "figd_xxx" }
40
+ }
41
+ }
42
+ }
43
+ ```
44
+
45
+ Prefer not to keep the token in the project file? Run
46
+ `npx figma-coder-mcp set-token figd_xxx` to store it once in the global settings
47
+ file instead, and leave the `env` out.
48
+
49
+ ### Remote mode — sign in with Figma (OAuth)
50
+
51
+ Add the server to `.mcp.json` with no token, then run
52
+ `npx figma-coder-mcp login` once to authorize via the hosted backend. The login
53
+ is stored globally; no token lives in your project.
54
+
55
+ ```json
56
+ {
57
+ "mcpServers": {
58
+ "figma": {
59
+ "command": "npx",
60
+ "args": ["-y", "figma-coder-mcp"]
61
+ }
62
+ }
63
+ }
64
+ ```
65
+
66
+ `login` opens the authorize page in your browser, captures the token the backend
67
+ hands back over a one-shot loopback server, and stores it in
68
+ `~/.figma-mcp/settings.json`. The access token is refreshed silently when it
69
+ expires; re-run `login` only if the refresh token itself is revoked. Set
70
+ `FIGMA_MCP_NO_BROWSER=1` on headless/SSH hosts to print the URL instead of
71
+ launching a browser.
72
+
73
+ Then ask your agent: **"Convert this Figma frame to HTML."**
74
+
75
+ ## Tools
76
+
77
+ Once the server is registered, your agent can call these two tools. There is
78
+ nothing to configure: just ask in plain language and the agent picks the right
79
+ one.
80
+
81
+ | Tool | What it does |
82
+ |------|--------------|
83
+ | `get_figma_data` | Returns the deterministic **Style IR** (the exact CSS for each node) so the agent can reason about the design and generate code itself. Small trees come back inline; large trees are written to a JSON file and summarised. |
84
+ | `convert_figma_to_html` | Produces finished, self-contained **HTML + Tailwind** (assets inlined, optional LLM restructure). The HTML is written to a file, and a compact summary plus path is returned to keep the agent's context small. Args: `mode`, `assets`, `assetScale`, `llm`, `outFile`. |
85
+
86
+ ## Configuration
87
+
88
+ A setting can come from three places. When the same setting appears in more than
89
+ one, the higher one wins: **command flags > environment variables > stored
90
+ `settings.json`**.
91
+
92
+ Settings live in two places:
93
+
94
+ - **`.mcp.json`** (project scope): how your agent launches the server, plus an
95
+ optional inline `env` (such as `FIGMA_PAT`). Only applies to this project.
96
+ - **`~/.figma-mcp/settings.json`** (global scope): your stored Figma token or
97
+ OAuth login, written by `set-token` / `login`. Shared by every project. You
98
+ only have this file if you run `set-token` or `login`.
99
+
100
+ The global file mirrors the `env` block of a `.mcp.json` — user-facing values sit
101
+ under `env`, keyed by the same names as the environment variables, so you can
102
+ edit it by hand:
103
+
104
+ ```json
105
+ {
106
+ "env": {
107
+ "FIGMA_PAT": "figd_xxx",
108
+ "FIGMA_MCP_API": "https://figmacoder-api.sitenow.cloud",
109
+ "FIGMA_MCP_TOKEN": "<oauth access token>"
110
+ },
111
+ "refreshToken": "<oauth refresh token>",
112
+ "apiTokenExpiresAt": 1735689600000
113
+ }
114
+ ```
115
+
116
+ Environment variables:
117
+
118
+ | Var | Meaning |
119
+ |-----|---------|
120
+ | `FIGMA_PAT` / `FIGMA_TOKEN` | Figma personal access token (local mode). |
121
+ | `FIGMA_MCP_API` | Backend converter base URL. Defaults to `https://figmacoder-api.sitenow.cloud`. |
122
+ | `FIGMA_MCP_TOKEN` | OAuth/bearer token for the backend. Usually set for you by `login`; an explicit value is used verbatim and never auto-refreshed. |
123
+ | `FIGMA_MCP_MODE` | `auto` (default) · `local` · `remote`. Auto prefers local. |
124
+ | `FIGMA_MCP_OUT_DIR` | Where HTML/JSON outputs are written. Default `<cwd>/figma-output`. |
125
+ | `FIGMA_MCP_NO_BROWSER` | If set, `login` prints the URL instead of opening a browser (headless/SSH). |
126
+ | `OLLAMA_CLOUD_URL` / `OLLAMA_API_KEY` / `OLLAMA_CLOUD_MODELS` | Optional, advanced. Only needed for the `--llm` restructure pass. |
127
+
128
+ ## CLI
129
+
130
+ The same program also works on its own, without an agent. Flags for
131
+ convert/data: `--node <id>`, `--mode tailwind|inline`, `--no-assets`, `--llm`,
132
+ `--out <file>`.
133
+
134
+ | Command | What it does |
135
+ |---------|--------------|
136
+ | `figma-coder-mcp` | Start the MCP server over stdio (the default command). |
137
+ | `convert <url\|key>` | One-off convert to a self-contained HTML file. |
138
+ | `data <url\|key>` | Print or save the deterministic Style IR. |
139
+ | `set-token <PAT>` | Store a Figma personal access token globally (local mode). |
140
+ | `login` | Sign in with Figma via OAuth, stored globally (remote mode). |
141
+ | `status` | Show how requests will be served. No secrets printed. |
142
+ | `logout` | Remove the global stored credentials. |
143
+
144
+ ```bash
145
+ figma-coder-mcp convert "https://www.figma.com/design/<key>/Title?node-id=1-23"
146
+ figma-coder-mcp convert <fileKey> --node 1:23 --no-assets --out page.html
147
+ figma-coder-mcp data <fileKey> --node 1:23
148
+ ```
149
+
150
+ ## License
151
+
152
+ MIT
package/dist/bin.js CHANGED
@@ -1805,31 +1805,37 @@ var import_core = __toESM(require_dist(), 1);
1805
1805
  import { promises as fs2 } from "fs";
1806
1806
  import * as path2 from "path";
1807
1807
 
1808
- // src/credentials.ts
1808
+ // src/settings.ts
1809
1809
  import { promises as fs } from "fs";
1810
1810
  import * as os from "os";
1811
1811
  import * as path from "path";
1812
1812
  var DIR = path.join(os.homedir(), ".figma-mcp");
1813
- var FILE = path.join(DIR, "credentials.json");
1814
- function credentialsPath() {
1813
+ var FILE = path.join(DIR, "settings.json");
1814
+ function settingsPath() {
1815
1815
  return FILE;
1816
1816
  }
1817
- async function loadCredentials() {
1817
+ async function loadSettings() {
1818
1818
  try {
1819
1819
  const raw = await fs.readFile(FILE, "utf8");
1820
- return JSON.parse(raw);
1820
+ const parsed = JSON.parse(raw);
1821
+ if (!parsed.env || typeof parsed.env !== "object") parsed.env = {};
1822
+ return parsed;
1821
1823
  } catch {
1822
- return {};
1824
+ return { env: {} };
1823
1825
  }
1824
1826
  }
1825
- async function saveCredentials(patch) {
1826
- const current = await loadCredentials();
1827
- const next = { ...current, ...patch };
1827
+ async function saveSettings(patch) {
1828
+ const current = await loadSettings();
1829
+ const next = {
1830
+ ...current,
1831
+ ...patch,
1832
+ env: { ...current.env ?? {}, ...patch.env ?? {} }
1833
+ };
1828
1834
  await fs.mkdir(DIR, { recursive: true });
1829
1835
  await fs.writeFile(FILE, JSON.stringify(next, null, 2), { mode: 384 });
1830
1836
  return next;
1831
1837
  }
1832
- async function clearCredentials() {
1838
+ async function clearSettings() {
1833
1839
  try {
1834
1840
  await fs.unlink(FILE);
1835
1841
  } catch {
@@ -1839,24 +1845,25 @@ async function clearCredentials() {
1839
1845
  // src/refresh.ts
1840
1846
  var SKEW_MS = 6e4;
1841
1847
  async function ensureFreshApiToken(apiUrl, force = false) {
1842
- const creds = await loadCredentials();
1843
- if (!creds.apiToken || !creds.refreshToken) return;
1848
+ const settings = await loadSettings();
1849
+ const apiToken = settings.env?.FIGMA_MCP_TOKEN;
1850
+ if (!apiToken || !settings.refreshToken) return;
1844
1851
  if (!force) {
1845
- if (!creds.apiTokenExpiresAt) return;
1846
- if (Date.now() < creds.apiTokenExpiresAt - SKEW_MS) return;
1852
+ if (!settings.apiTokenExpiresAt) return;
1853
+ if (Date.now() < settings.apiTokenExpiresAt - SKEW_MS) return;
1847
1854
  }
1848
1855
  const base = apiUrl.replace(/\/+$/, "");
1849
1856
  try {
1850
1857
  const res = await fetch(`${base}/auth/figma/cli-refresh`, {
1851
1858
  method: "POST",
1852
1859
  headers: { "Content-Type": "application/json" },
1853
- body: JSON.stringify({ refresh_token: creds.refreshToken })
1860
+ body: JSON.stringify({ refresh_token: settings.refreshToken })
1854
1861
  });
1855
1862
  if (!res.ok) return;
1856
1863
  const t = await res.json();
1857
- await saveCredentials({
1858
- apiToken: t.access_token,
1859
- refreshToken: t.refresh_token ?? creds.refreshToken,
1864
+ await saveSettings({
1865
+ env: { FIGMA_MCP_TOKEN: t.access_token },
1866
+ refreshToken: t.refresh_token ?? settings.refreshToken,
1860
1867
  apiTokenExpiresAt: t.expires_in ? Date.now() + t.expires_in * 1e3 : void 0
1861
1868
  });
1862
1869
  } catch {
@@ -1864,13 +1871,15 @@ async function ensureFreshApiToken(apiUrl, force = false) {
1864
1871
  }
1865
1872
 
1866
1873
  // src/config.ts
1874
+ var DEFAULT_API_URL = "https://figmacoder-api.sitenow.cloud";
1867
1875
  async function resolveConfig(overrides = {}) {
1868
- let creds = await loadCredentials();
1869
- const mode = overrides.mode ?? process.env.FIGMA_MCP_MODE ?? "auto";
1870
- const pat = overrides.pat ?? process.env.FIGMA_PAT ?? process.env.FIGMA_TOKEN ?? creds.pat;
1871
- const apiUrl = overrides.apiUrl ?? process.env.FIGMA_MCP_API ?? creds.apiUrl;
1876
+ let settings = await loadSettings();
1877
+ let env = settings.env ?? {};
1878
+ const mode = overrides.mode ?? process.env.FIGMA_MCP_MODE ?? env.FIGMA_MCP_MODE ?? "auto";
1879
+ const pat = overrides.pat ?? process.env.FIGMA_PAT ?? process.env.FIGMA_TOKEN ?? env.FIGMA_PAT ?? env.FIGMA_TOKEN;
1880
+ const apiUrl = overrides.apiUrl ?? process.env.FIGMA_MCP_API ?? env.FIGMA_MCP_API ?? DEFAULT_API_URL;
1872
1881
  const apiTokenOverride = overrides.apiToken ?? process.env.FIGMA_MCP_TOKEN;
1873
- const outDir = overrides.outDir ?? process.env.FIGMA_MCP_OUT_DIR ?? `${process.cwd()}/figma-output`;
1882
+ const outDir = overrides.outDir ?? process.env.FIGMA_MCP_OUT_DIR ?? env.FIGMA_MCP_OUT_DIR ?? `${process.cwd()}/figma-output`;
1874
1883
  let effectiveMode;
1875
1884
  if (mode === "local") {
1876
1885
  effectiveMode = "local";
@@ -1881,9 +1890,10 @@ async function resolveConfig(overrides = {}) {
1881
1890
  }
1882
1891
  if (effectiveMode === "remote" && apiUrl && !apiTokenOverride) {
1883
1892
  await ensureFreshApiToken(apiUrl);
1884
- creds = await loadCredentials();
1893
+ settings = await loadSettings();
1894
+ env = settings.env ?? {};
1885
1895
  }
1886
- const apiToken = apiTokenOverride ?? creds.apiToken;
1896
+ const apiToken = apiTokenOverride ?? env.FIGMA_MCP_TOKEN;
1887
1897
  return { mode, effectiveMode, pat, apiUrl, apiToken, outDir };
1888
1898
  }
1889
1899
  function describeConfig(cfg) {
@@ -1907,7 +1917,7 @@ async function post(cfg, route, body) {
1907
1917
  let res = await fetch(url, { method: "POST", headers: authHeaders(cfg), body: payload });
1908
1918
  if (res.status === 401 && cfg.apiToken) {
1909
1919
  await ensureFreshApiToken(cfg.apiUrl, true);
1910
- const refreshed = (await loadCredentials()).apiToken;
1920
+ const refreshed = (await loadSettings()).env?.FIGMA_MCP_TOKEN;
1911
1921
  if (refreshed && refreshed !== cfg.apiToken) {
1912
1922
  res = await fetch(url, { method: "POST", headers: authHeaders(cfg, refreshed), body: payload });
1913
1923
  }
@@ -2058,12 +2068,12 @@ function buildServer() {
2058
2068
  "convert_figma_to_html",
2059
2069
  {
2060
2070
  title: "Convert Figma to HTML + Tailwind",
2061
- description: "Convert a Figma file/node into finished, self-contained HTML + Tailwind (deterministic Style IR, assets inlined, optional LLM restructure). The HTML is written to a file; a compact summary + path is returned to keep context small.",
2071
+ description: "Convert a Figma file/node into finished, self-contained HTML + Tailwind (deterministic Style IR, optional LLM restructure). Asset inlining is off by default (placeholders shown for images/vectors); pass assets:true to render & inline them. The HTML is written to a file; a compact summary + path is returned to keep context small.",
2062
2072
  inputSchema: {
2063
2073
  ...targetShape,
2064
2074
  mode: z.enum(["tailwind", "inline"]).optional().describe("Output mode. Default 'tailwind'."),
2065
2075
  document: z.boolean().optional().describe("Emit a full HTML document (default true) vs a fragment."),
2066
- assets: z.boolean().optional().describe("Export & inline vectors/images as data URIs. Default true."),
2076
+ assets: z.boolean().optional().describe("Export & inline vectors/images as data URIs. Default false (placeholders shown instead)."),
2067
2077
  assetScale: z.number().min(1).max(4).optional().describe("Raster export scale (1-4). Default 2."),
2068
2078
  llm: z.boolean().optional().describe("Run the LLM restructure pass (needs OLLAMA_* config). Default false."),
2069
2079
  outFile: z.string().optional().describe("Override the output file name (within the output dir).")
@@ -2100,9 +2110,7 @@ var page = (title, body) => `<!doctype html><meta charset="utf-8"><title>figma-c
2100
2110
  async function login(opts = {}) {
2101
2111
  const cfg = await resolveConfig({ apiUrl: opts.apiUrl });
2102
2112
  if (!cfg.apiUrl) {
2103
- throw new Error(
2104
- "OAuth login needs the backend URL. Set it with `figma-coder-mcp set-api <URL>` or FIGMA_MCP_API."
2105
- );
2113
+ throw new Error("OAuth login needs the backend URL. Set FIGMA_MCP_API or pass --api <URL>.");
2106
2114
  }
2107
2115
  const base = cfg.apiUrl.replace(/\/+$/, "");
2108
2116
  const tokens = await new Promise((resolve2, reject) => {
@@ -2155,13 +2163,15 @@ If it doesn't open automatically, visit:
2155
2163
  openBrowser(authorizeUrl);
2156
2164
  });
2157
2165
  });
2158
- await saveCredentials({
2159
- apiUrl: base,
2160
- apiToken: tokens.access_token,
2166
+ await saveSettings({
2167
+ env: {
2168
+ FIGMA_MCP_API: base,
2169
+ FIGMA_MCP_TOKEN: tokens.access_token
2170
+ },
2161
2171
  refreshToken: tokens.refresh_token,
2162
2172
  apiTokenExpiresAt: tokens.expires_in ? Date.now() + tokens.expires_in * 1e3 : void 0
2163
2173
  });
2164
- console.error(`\u2713 Saved Figma OAuth session to ${credentialsPath()}`);
2174
+ console.error(`\u2713 Saved Figma OAuth session to ${settingsPath()}`);
2165
2175
  console.error("Run the MCP in remote mode (set FIGMA_MCP_MODE=remote) to use it.");
2166
2176
  }
2167
2177
 
@@ -2192,29 +2202,30 @@ function targetFrom(value, flags) {
2192
2202
  if (/figma\.com\//.test(value)) return { figmaUrl: value, nodeId };
2193
2203
  return { fileKey: value, nodeId };
2194
2204
  }
2195
- var HELP = `figma-coder-mcp \u2014 Figma -> HTML/Tailwind for AI agents (MCP server + CLI)
2205
+ var HELP = `figma-coder-mcp: Figma -> HTML/Tailwind for AI agents (MCP server + CLI)
2196
2206
 
2197
2207
  Usage:
2198
2208
  figma-coder-mcp [serve] Start the MCP server over stdio (default)
2199
2209
  figma-coder-mcp convert <url|key> [..] One-off convert to HTML (writes a file)
2200
2210
  figma-coder-mcp data <url|key> [..] One-off: print/save the Style IR
2201
2211
  figma-coder-mcp set-token <PAT> Store a Figma personal access token (local mode)
2202
- figma-coder-mcp set-api <URL> Store the backend converter URL (remote mode)
2203
2212
  figma-coder-mcp login [--api <URL>] Log in with Figma via OAuth (remote mode)
2204
2213
  figma-coder-mcp status Show how requests will be served (no secrets)
2205
- figma-coder-mcp logout Remove stored credentials
2214
+ figma-coder-mcp logout Remove stored settings
2206
2215
  figma-coder-mcp help Show this help
2207
2216
 
2208
2217
  Common flags (convert/data):
2209
2218
  --node <id> Node id ("1-23" or "1:23")
2210
2219
  --mode <m> tailwind | inline (convert)
2211
- --no-assets Skip asset inlining (convert)
2220
+ --assets Render & inline assets (convert; off by default, placeholders shown)
2212
2221
  --llm Run LLM restructure (convert; needs OLLAMA_* env)
2213
2222
  --out <file> Output file name (convert)
2214
2223
 
2215
2224
  Config (env or stored): FIGMA_PAT, FIGMA_MCP_API, FIGMA_MCP_TOKEN, FIGMA_MCP_MODE,
2216
2225
  FIGMA_MCP_OUT_DIR, FIGMA_MCP_NO_BROWSER (skip auto-opening the browser on login).
2217
- Auto mode prefers local (PAT) so it works even if the backend is down.`;
2226
+ Auto mode prefers local (PAT) so it works even if the backend is down; with no PAT
2227
+ it uses the hosted backend by default (override the URL with FIGMA_MCP_API).
2228
+ Stored settings live in ~/.figma-mcp/settings.json under "env" (edit it directly if you like).`;
2218
2229
  async function main() {
2219
2230
  const [positionals, flags] = parseArgs(process.argv.slice(2));
2220
2231
  const cmd = positionals[0] ?? "serve";
@@ -2227,7 +2238,7 @@ async function main() {
2227
2238
  const text = await convertFigmaToHtml({
2228
2239
  ...targetFrom(positionals[1], flags),
2229
2240
  mode: flags.mode === "inline" ? "inline" : flags.mode === "tailwind" ? "tailwind" : void 0,
2230
- assets: flags["no-assets"] ? false : void 0,
2241
+ assets: flags.assets ? true : flags["no-assets"] ? false : void 0,
2231
2242
  llm: flags.llm === true,
2232
2243
  outFile: typeof flags.out === "string" ? flags.out : void 0
2233
2244
  });
@@ -2242,15 +2253,8 @@ async function main() {
2242
2253
  case "set-token": {
2243
2254
  const pat = positionals[1];
2244
2255
  if (!pat) throw new Error("Usage: figma-coder-mcp set-token <PAT>");
2245
- await saveCredentials({ pat });
2246
- console.log(`Stored Figma PAT in ${credentialsPath()}`);
2247
- return;
2248
- }
2249
- case "set-api": {
2250
- const url = positionals[1];
2251
- if (!url) throw new Error("Usage: figma-coder-mcp set-api <URL>");
2252
- await saveCredentials({ apiUrl: url });
2253
- console.log(`Stored backend URL (${url}) in ${credentialsPath()}`);
2256
+ await saveSettings({ env: { FIGMA_PAT: pat } });
2257
+ console.log(`Stored FIGMA_PAT in ${settingsPath()}`);
2254
2258
  return;
2255
2259
  }
2256
2260
  case "login": {
@@ -2260,12 +2264,12 @@ async function main() {
2260
2264
  case "status": {
2261
2265
  const cfg = await resolveConfig();
2262
2266
  console.log(describeConfig(cfg));
2263
- console.log(`credentials: ${credentialsPath()}`);
2267
+ console.log(`settings: ${settingsPath()}`);
2264
2268
  return;
2265
2269
  }
2266
2270
  case "logout":
2267
- await clearCredentials();
2268
- console.log("Cleared stored credentials.");
2271
+ await clearSettings();
2272
+ console.log("Cleared stored settings.");
2269
2273
  return;
2270
2274
  case "help":
2271
2275
  case "--help":
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "figma-coder-mcp",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "MCP server + CLI that converts Figma designs into HTML + Tailwind for AI coding agents. Runs locally with a Figma PAT (no backend) or delegates to a figma-to-html-api backend.",
5
5
  "license": "MIT",
6
6
  "author": "GoldynLabs",
@@ -29,10 +29,8 @@
29
29
  "claude",
30
30
  "cursor"
31
31
  ],
32
- "repository": {
33
- "type": "git",
34
- "url": "git+https://github.com/goldynlabs/figma-coder-mcp.git"
35
- },
32
+ "repository": "",
33
+ "homepage": "https://figmacoder.sitenow.cloud",
36
34
  "scripts": {
37
35
  "build": "tsup",
38
36
  "typecheck": "tsc -p tsconfig.json --noEmit",