Repository navigation
Releases
v0.5.5 — loopback-only HTTP endpoint, MCP SDK 1.32, fileContext, clean package
Restart the server, then re-import the Desktop Bridge plugin. The HTTP guard and the SDK upgrade take effect when the server restarts.
fileContext/resultAnalysiscome from a change tofigma-desktop-bridge/ui.html, and this fork never shows Figma's update banner, so re-importmanifest.jsonby hand. If you launch with plainnpx @muloka/figma-console-mcp, npx may keep running a cached older version. Run it once asnpx @muloka/figma-console-mcp@latest.
This release covers 0.5.4 and 0.5.5. 0.5.4 had no release notes of its own; 0.5.5 is the same code, packaged correctly.
Security (0.5.4)
- The HTTP endpoint only answers loopback clients. With
MCP_HTTP_PORTset, every request must name a loopbackHoston that port (localhost,127.0.0.1or[::1]) and carry either noOriginor a loopback one. Anything else gets a 403 before it reaches MCP, on/mcpand on the/status route. The endpoint already bound127.0.0.1, but a web page could still reach it through DNS rebinding and call any tool. Non-browser MCP clients send noOriginand are unaffected. - MCP SDK 1.26 → 1.32.2. Fixes advisories that reach the HTTP endpoint, including a single oversized request exhausting server memory during validation. Still on zod 3. The tool list served to clients is unchanged: all 112 definitions are identical.
figma_scan_code_accessibilityno longer runs scripts from the HTML it scans.<script>tags and inline handlers in the scanned HTML used to execute inside the server's Node process. Cherry-picked from upstream (fe3af0b6, the Local Mode part only), authorship preserved.
Added (0.5.4)
figma_executeresults carryfileContextandresultAnalysis.fileContextis{ fileName, fileKey }of the file the code actually ran in, so a caller using 0.5.1'sfileKeycan confirm the call landed where it asked.resultAnalysisflags empty and null results, as the tool's description has always promised. The plugin computed both, but its UI relay dropped them before they reached the server. Cherry-picked from upstream (63745813), authorship preserved.
Packaging (0.5.5)
- The package now contains exactly the build it needs.
dist/is rebuilt from empty before every publish. Stale Cloud Mode compiler output (dist/cloudflare/, which nothing in the package uses) is gone, and both MCP App bundles (token browser, design-system dashboard) are included. They were missing from 0.5.1 and 0.5.2, so reading those app resources failed there.
Notes
- Versions below 0.5.4 are deprecated on npm. They lack the HTTP guard and the accessibility-scan fix.
- 0.5.3 was never released.
- A missing
fileContextmeans unverified, not failed. It arrives only once the plugin has been re-imported from 0.5.4 or later. Clients that rely on it should treat its absence as "targeting not confirmed". npm auditstill lists the SDK advisories against the copy nested underagents, which only Cloud Mode loads. Local mode never imports it.- Suite: 1467 tests across 55 suites. The HTTP guard is tested with real requests and was checked live: allowed clients complete the handshake and tool calls, while a rebinding
Hostor a cross-siteOrigingets a 403.
npm: npx @muloka/figma-console-mcp@0.5.5
v0.5.2 — the HTTP port survives a re-created port file
No plugin re-import needed. Only the server changed. Restart the server on 0.5.2 to pick up the fix; if you launch with plain
npx @muloka/figma-console-mcp, run it once asnpx @muloka/figma-console-mcp@latestso npx doesn't reuse a cached copy.
Fixes
- The HTTP port stays discoverable after the port file is re-created. A server started with
MCP_HTTP_PORTpublishes it asmcpHttpPortin its port-discovery file (<tmpdir>/figma-console-mcp-<port>.json). If that file was deleted, the 30s heartbeat re-created it withoutmcpHttpPortand with a newstartedAt, so clients that find the server through the file reported its HTTP transport as disabled until a restart. The server now keeps the record it advertised and rewrites it whole: a re-created file keepsmcpHttpPortand the originalstartedAt, and a file that lost the field gets it back on the next beat. The file's fields are unchanged. - The test suite no longer touches real port files.
tests/port-discovery.test.tsdeleted the default port files (9223–9232) in the real tmpdir after each test, which removed the file of any server running on the same machine; the stale-instance cleanup tests also scanned real servers' files. Each jest run now gets a privateTMPDIR, removed at the end.
Notes
- Patch bump per this fork's versioning rule: fixes only; no tool or behavior change for callers.
- Suite: 1449 tests across 52 suites; both fixes landed test-first. Checked end to end: a server whose port file was deleted re-created it about 24s later with
mcpHttpPortandstartedAtintact.
npm: npx @muloka/figma-console-mcp@0.5.2
v0.5.1 — per-call file targeting
No plugin re-import needed. Only the server changed;
figma-desktop-bridge/is untouched, so updating the npm package is enough. If you launch with plainnpx @muloka/figma-console-mcp, npx may keep running a cached 0.5.0. Run it once asnpx @muloka/figma-console-mcp@latest.
Added
- Per-call file targeting.
figma_execute,figma_setup_design_tokens,figma_batch_create_variables,figma_batch_update_variables,figma_delete_variable,figma_rename_variableandfigma_rename_nodetake an optionalfileKey. With it, the call runs only in that file's Desktop Bridge plugin, whichever file is active, and even when another client has pinned the target withfigma_navigate({ lock: true }). Several clients sharing one server can each work in their own file without the active file moving under them. LeavefileKeyout and nothing changes. - A refusal instead of a wrong-file write. If the named file's plugin isn't connected, the call is refused and nothing is sent:
File <key> is not connected to the Desktop Bridge, so nothing was sent. Connected files: "<name>" (<key>), …. It never falls back to the active file. Calls without afileKeykeep the old error text. - Local mode only. The cloud relay pairs with a single file, so it refuses a
fileKeyrather than run the call in the paired file.
figma_get_variables already read a specific file through fileUrl; that's unchanged. Details: Targeting a file.
Notes
- Patch bump per this fork's versioning rule: one optional argument added, and existing calls behave exactly as before.
- Check the server version before relying on
fileKey. A 0.5.0 server silently drops the unknown argument and runs the call in the active file. Clients that depend on targeting should requireserverInfo.version≥ 0.5.1. - Suite: 1447 tests across 52 suites, including real-socket tests with two connected files and concurrent calls to both. Also checked live against two open Figma files.
npm: npx @muloka/figma-console-mcp@0.5.1
v0.5.0 — no more orphans, real timeouts, plan-aware mode limits
⚠️ Plugin re-import required for the plugin-side fixes.code.jsandui.htmlboth changed (orphan cleanup, dispatch budgets), butPLUGIN_VERSIONcorrectly stays on the vendored 1.35.0 lineage — so no update banner will prompt you. Re-importfigma-desktop-bridge/manifest.jsonmanually. Server-side fixes arrive with the npm update alone.
Fixes
- Mode-limit failures roll back instead of orphaning (#7, #8).
figma_setup_design_tokensandfigma_create_variable_collectionremove the just-created collection whenaddModehits your plan's ceiling, and the setup tool returns the file's real limit:{error, planModeLimit, requested, rolledBack: true}— parsed from Figma's ownLimited to N modes onlyerror. The schema's stale 4-mode cap (Figma's pre-raise Professional limit) is now a 40 sanity bound; current plans allow 10/20/unlimited and the runtime governs. - Batch-create rows report partial effects honestly (#10). A failure row whose
createVariablesucceeded before the throw now carriescreated: true, id, valueSet: false— infigma_batch_create_variablesand the setup create pass — so callers can clean up or complete instead of retrying into duplicates. - No more orphaned nodes on failure (#11, reduced cut).
figma_create_connectorvalidates endpoints before creating (a stale nodeId can no longer strand an endpoint-less connector — previously guaranteed); create-child, add-text-to-slide, and create-table remove their partially-created node on error, suffixing(partially-created node was removed); batch stickies report the id of any sticky a failed row left behind.figma_create_childalso gains POLYGON/STAR/VECTOR. - Long-running commands get their real timeouts (#9). The server's per-command budget rides in each WS frame and the plugin dispatcher honors it (+5s margin, 310s cap) instead of cutting everything off at a fixed 30s: variable refresh and component scans get 300s, lint/audit 120s, large component sets their scaled budget — on both local and cloud transports. Absent/invalid field falls back to the old 30s, so mixed server/plugin versions behave exactly as before.
- Plugin-loader guard. A comment pattern (
…importat end of line above another comment) tripped Figma's import-expression scanner and bricked plugin load withpossible import expression rejected around line 1. Fixed, and Figma's exact scanner regex (extracted from their bundle) now runs in the test suite so the class can't recur.
Notes
- Minor bump per this fork's versioning rule: failure-path envelopes changed (rollback errors, partial-effect row fields) and plugin files changed.
- Suite: 1414 tests across 52 suites; every fix landed test-first with the failing case verified before the change.
npm: npx @muloka/figma-console-mcp@0.5.0
v0.4.0 — honest errors, stable servers, truthful update banner
Fixes
- Honest error reporting in the eight single-op variable/collection/mode write tools (#6). The Desktop Bridge resolves plugin failures as
{success:false, error}objects; these tools never checked, so failures surfaced as false successes (figma_create_variable,figma_update_variable,figma_create_variable_collection,figma_rename_mode) or as a masking TypeError (figma_delete_variable,figma_delete_variable_collection,figma_rename_variable,figma_add_mode— e.g. a mode-limit failure reported "Cannot read properties of undefined (reading 'name')" instead of Figma'sin addMode: Limited to 10 modes only). Every handler now guards the result envelope and propagates the plugin's error text verbatim;figma_update_variablealso notes when the value had applied before a failed description step. 11 new regression tests. - Orphan reaper no longer kills healthy MCP servers — cherry-pick of upstream v1.38.2 (
fbb1cb80, original authorship preserved). Fixes the "Server disconnected across every MCP client" failure: IPv6-blind health probe, non-atomic port-file writes, and corrupt-file cleanup racing healthy servers. - An older server no longer nags a newer plugin to re-import — cherry-pick of upstream v1.39.1 (
e5e2df87). The update banner now compares versions directionally (compareSemver), so stale server processes left over from before an upgrade stop showing an un-clearable re-import banner.
Features
- Plugin + server build versions surfaced in the Desktop Bridge UI and diagnostics.
Notes
- Minor bump per this fork's versioning rule: the error-reporting guards change observable tool behavior (plugin failures now report as errors instead of successes).
- Plugin re-import is optional for this release:
PLUGIN_VERSIONstays at the vendored 1.35.0 lineage, so no update banner will appear — but the version-surfacing improvements in the Desktop Bridge UI only arrive if you manually re-import the plugin from the updated package. - This fork is now frozen at the upstream v1.36.0 base with selective cherry-picks — see the README's "Relationship to upstream" section. Bugs go to this repo's tracker, not upstream.
npm: npx @muloka/figma-console-mcp@0.4.0
v0.3.0
Synced to upstream v1.36.0.
Added
Target lock for multi-file parallel work. figma_navigate accepts lock: true, pinning the active file so new connections, reconnects, and your own selection or page changes in other files can't move the target.
Use it when an agent works in one file while you work in another — without it, commands can silently route to whichever file most recently reported activity. Switching to another file or passing lock: false releases the pin, and it releases automatically if the pinned file disconnects.
figma_get_status and figma_navigate now report targetLocked.
Notes
No plugin re-import required. figma-desktop-bridge/ is unchanged from v1.35.0 — upstream's own v1.36.0 ships the same plugin files, so PLUGIN_VERSION stays at 1.35.0.
Requires Node >= 22 (unchanged since v0.2.0).
v0.2.0
First release with CI. Fork of southleft/figma-console-mcp, tracking upstream v1.35.0.
Breaking
engines.noderaised to>=22. Node 18 reached EOL 2025-04 and Node 20 left maintenance 2026-04, so the previous>=18certified runtimes nobody should be on. Published as0.2.0rather than0.1.3so npm's^0.1.xranges correctly withhold it.
Fixed
figma_get_variablesnow honorspage/pageSizeunderformat='full'(upstream #98). They were accepted, silently ignored, and omitted from the response, so callers had no way to detect paging had not happened. On a 689-variable fileformat='full'auto-summarizes into nothing usable and paging could not rescue it — the exact case the parameter documents. Both the cached and Desktop Bridge paths were affected.- Desktop Bridge no longer drops pagination metadata. It computed
paginationInfoand never returned it, so cache-miss requests received silently truncated data with nohasNextPagesignal. page/pageSizeare now documented accurately: hard limit 100, a soft ~25K-token ceiling above which a page is auto-summarized rather than returned, and out-of-range pages clamp to the last page instead of erroring — so paging loops must be driven offhasNextPage.
Added
- Setup guidance in the MCP handshake. A connected agent hitting a disconnected bridge is now told to read
pluginPathfromfigma_get_status, and that Figma's import dialog hides the plugin's dot-directory on macOS (press Cmd+Shift+G and paste the path). That last fact appears in no other surface — see upstream #100 and #101. - GitHub Actions CI — Node 22/24 test matrix plus a per-file typecheck ratchet that baselines known upstream type errors and fails on new ones.
No plugin re-import required — figma-desktop-bridge/ is unchanged from upstream v1.35.0.