figma-console-mcp 1.41.5 β†’ 1.42.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
@@ -8,7 +8,7 @@
8
8
 
9
9
  > **Your design system as an API.** A design-system-focused Model Context Protocol server for Figma. It works in both directions (Figma ⇄ code), **writes to Figma**, and runs **deterministic checks** for design-code parity, accessibility, and design-system health. It hands the AI exact tokens, variants, bindings, and states as structured data rather than prescribing a framework or house style, so generated code follows your team's own stack and conventions.
10
10
 
11
- > **πŸ†• Security & data-safety fixes (latest v1.41.5):** Cloud Mode sign-in is hardened: each session uses only its own Figma token, authorization codes are single-use and bound to the client that asked for them, and the accessibility scanner no longer runs scripts from the HTML it checks. Two data-loss fixes: `figma_import_tokens` refuses an import that read no token files (it used to plan deleting every variable) and `replace` only deletes inside the collections you import; arranging a component set no longer deletes the other arranged sets on the page. Token export and import read variables live, so renames show up immediately. Abandoned servers exit on Windows, batch-created variables accept aliases, and the Slots tools take `fileKey`. v1.41.1–v1.41.5 make component-set analysis report real variant differences, including changes inside nested layers (an icon swap, a token on a nested vector), the variant's own background and opacity, auto-layout, gradients, corner radius, typography and swapped tokens, stop component loading from timing out on large files, and fix variable paging. Re-import the plugin for the component fixes. [See what's new β†’](CHANGELOG.md#1415---2026-10-27)
11
+ > **πŸ†• Comment threads, plus reliability, security & data-safety fixes (latest v1.42.1):** commands fail fast instead of piling up behind a plugin stuck on a timed-out script, and a new server no longer shuts down one a thread is using (v1.42.1). `figma_get_comments` returns compact comment threads with node, thread and date filters and paging, so a busy file no longer floods the conversation (v1.42.0). Cloud Mode sign-in is hardened: each session uses only its own Figma token, authorization codes are single-use and bound to the client that asked for them, and the accessibility scanner no longer runs scripts from the HTML it checks. Two data-loss fixes: `figma_import_tokens` refuses an import that read no token files (it used to plan deleting every variable) and `replace` only deletes inside the collections you import; arranging a component set no longer deletes the other arranged sets on the page. Token export and import read variables live, so renames show up immediately. Abandoned servers exit on Windows, batch-created variables accept aliases, and the Slots tools take `fileKey`. v1.41.1–v1.41.5 make component-set analysis report real variant differences, including changes inside nested layers (an icon swap, a token on a nested vector), the variant's own background and opacity, auto-layout, gradients, corner radius, typography and swapped tokens, stop component loading from timing out on large files, and fix variable paging. Re-import the plugin for the component fixes. [See what's new β†’](CHANGELOG.md#1421---2026-10-27)
12
12
 
13
13
  ## What is this?
14
14
 
@@ -874,9 +874,11 @@ The two servers are complementary, and both can run in the same MCP client.
874
874
 
875
875
  ## πŸ›€οΈ Roadmap
876
876
 
877
- **Current Status:** v1.41.5 (Stable) - Production-ready. Latest: component-set analysis reports gradient/image/paint-opacity, corner radius, typography and label text, swapped spacing tokens, nested layer geometry and vector shape changes (re-import the plugin). On top of v1.41.4's variant background/stroke and auto-layout changes. On top of v1.41.3's component-set analysis reporting changes inside nested layers (instance swaps, nested token changes, opacity on the variant itself) and no longer reports a layer hidden in every variant as a change (re-import the plugin). On top of v1.41.2's design-system summary and `figma_get_token_values` report the file's tokens (they always reported 0) (server-only). On top of v1.41.1's component-set analysis reports real variant differences (Figma's default variant, size and layer changes), component loading no longer times out on large files (throttled plugin timers), relevance-ranked component search, and `figma_get_variables` paging that works with `format: "full"` (re-import the plugin for the component fixes). On top of v1.41.0's Cloud Mode sign-in hardening (per-session tokens on `/sse`, single-use authorization codes bound to client, redirect URI and PKCE, a consent page for unrecognized destinations), a script-execution fix in the accessibility scanner, `figma_import_tokens` refusing empty imports and scoping `replace` deletes to imported collections, `figma_arrange_component_set` no longer deleting other arranged sets, live variable reads for token export/import, Windows orphan-server exit (PR #140), and `fileKey` for the Slots tools (PR #112) (server-only, no plugin re-import). On top of v1.40.9's composed colors (a color variable set to another color at an opacity, "grey/900 at 50%") export and import with the link to the primitive intact β€” `color-mix()` in CSS/Tailwind v4, `rgba()` in SCSS, an alpha modifier in Tokens Studio, the resolved color plus the composition in DTCG β€” where the export previously failed or wrote `[object Object]` (server-only, no plugin re-import). On top of v1.40.8's min/max width and height survive every way of extracting a component as JSON β€” the design system kit, the reconstruction format and `figma_get_file_data` now carry them, design-code parity compares them, and the reconstruction format returns real geometry again instead of 50Γ—50 placeholders when the plugin is connected (server-only, no plugin re-import). On top of v1.40.7's clearer Color Tokens table in generated docs β€” layers revealed by a boolean property are printed once under that property, and stroke/fill rows name the nested instance they belong to (server-only, no plugin re-import). On top of v1.40.6's overrides in extended variable collections are visible (previously reported as nonexistent), and a third round of generated-doc fidelity fixes β€” radius tokens read per corner, boolean props compared in Design-Code Parity, source links pinned to a commit, hidden layers linked to the property that shows them (server-only, no plugin re-import). On top of v1.40.5's clean dependency audit for the npm package β€” Worker-only dependencies (`@cloudflare/puppeteer`, which pulled in a high-severity `extract-zip` advisory with no upstream fix, and `agents`) no longer install for npm users, so `npm install figma-console-mcp` audits at 0 vulnerabilities and is 64 MB instead of 173 MB; the server also reports its real version to MCP clients instead of `0.1.0` (server-only, no plugin re-import). On top of v1.40.4's fixes found by live-testing v1.40.3 on hard production components β€” tools given a `fileUrl` now read variables, descriptions and annotations from THAT file rather than whichever file is active (previously every token name could vanish, or on an id collision come from the wrong file; `figma_get_component` could return a different component), a tool result over 16 MB no longer disconnects the server, anatomy labels sizing by the layout's real axes, and the icon/typography/anatomy output stays readable on large components (server-only, no plugin re-import). On top of v1.40.3's fidelity fixes for generated component docs on harder components β€” hidden layers are labeled instead of documented as rendered, one-sided borders report the weight that actually renders, typography and layer structure are compared across every variant instead of read from the first, gradients/shadows/opacity are no longer silently dropped, truncated trees say so, and `SLOT` properties are listed (server-only, no plugin re-import). On top of v1.40.2's data-loss fix for `figma_export_tokens` β€” with a different file active in Figma than intended, an export could replace a real token file with an empty one (or with another file's tokens) and report success; exports now refuse to write when a requested collection is missing, when the export is empty, when the target was generated from a different Figma file, or when overwriting would destroy tokens the export doesn't manage, and `strategy: "merge"` β€” documented as preserving code-only tokens but never implemented β€” is now a genuinely safe default (server-only, no plugin re-import). On top of v1.40.1's accuracy fixes for generated component docs across variants β€” a descendant's fill (typically an icon's) could be documented as a variant's Background, Color Token headings kept only a property literally named `Variant`, spacing was read from the first variant alone, and icons were only detected by layer name β€” plus `figma_export_tokens` accepting a file path as `outputPath` instead of failing with a raw `EEXIST` or silently creating a directory (server-only, no plugin re-import). On top of v1.40.0's design system extraction from production codebases β€” seven Local-Mode `figma_ds_*` tools that scan one or more apps (framework/styling/vendor detection, usage-ranked component inventory classified vendored/wrapped/pure-vendor/bespoke, variant inference from real call sites, duplicate detection, and an architecture pass separating UI-kit specializations from the missing generic primitives), mine the de-facto styling into DTCG tokens with per-token provenance (multi-mode CSS custom properties, SCSS, Tailwind config, shadcn HSL triples, utility-class frequency mining valued from the app's own theme), scaffold the design-system package with showcase docs pages, wire a fresh Storybook workshop to the app's real theme layers and fonts, deep-extract components for porting with CSF3 story scaffolds, verify with deterministic fidelity evals, and persist porting progress across sessions β€” the extracted tokens import straight into Figma variables via `figma_import_tokens`. On top of v1.39.1's fix for a plugin-update banner that could never be cleared β€” an older server instance nagging a newer plugin to re-import, which only ever installs the same or a newer plugin. On top of v1.39.0's multi-file execution β€” `figma_execute_across_files` runs one script against several Desktop Bridge-connected files concurrently (four files x 2s of work in ~3s, not ~8s), and `figma_execute` takes an optional `fileKey` to target a single file without moving the active file or releasing target lock; targeting must be explicit (`fileKeys` or `allFiles: true`), so nothing fans out to files you did not name. From community PR #107 by @Wolfr. Ships with a relay fix: `handleResult()` in the plugin's ui.html rebuilt each response field by field and silently dropped `resultAnalysis` and `fileContext`, so the `resultAnalysis.warning` check that `figma_execute`'s own description tells callers to perform has never been possible (re-import `manifest.json` for those two fields; everything else works without it). On top of v1.38.2's connection-stability fix β€” the server's own orphan reaper was terminating healthy MCP servers because its liveness probe used an IPv4 literal while the server binds the IPv6 loopback, which turned every kill-safety gate into a rubber stamp; this was the cause of recurring "Server disconnected" errors across all MCP clients. Alongside v1.38.1's fix for the shared-library variable tools, which had silently reported zero collections since v1.29.0 and reported failed imports as successes. On top of v1.38.0's ongoing component changelogs in generated docs β€” `figma_generate_component_doc` takes an opt-in `history` parameter that pulls per-component **design history** from Figma version history (each version diffed and scoped to that component, so renames, added properties, and token bindings show up as rows) alongside **code history** from `git log` on the component's source files, rendered as a `## History` section with design, code, and release-note tables. Prefers labeled versions, falls back to auto-saves when a file has none, and is off by default so existing calls are unchanged (server-only, no plugin re-import). On top of v1.37.x's design-system health audit for every client β€” `figma_audit_design_system_report` runs the dashboard's deterministic six-category scoring engine and returns the report as data with per-finding remediation, live-first fileKey-verified data (source disclosed), chunked per-category drill-down, and a 5-minute cache (server-only, no plugin re-import). On top of v1.36.0's target lock for multi-file parallel work β€” β€” `figma_navigate` takes a `lock: true` flag that pins the active file so an AI agent can work in one file while you work in another without commands routing to the wrong file. On top of v1.35.0's Figma Slots write support β€” create, inspect, populate, and reset Slots (GA at Config 2026) via 5 new tools (`figma_create_slot`, `figma_get_slots`, `figma_append_to_slot`, `figma_reset_slot`, `figma_add_slot_property`), live-validated against the GA Plugin API and based on community PR #77. On top of v1.34.0's Bidirectional Token Sync v2 + DTCG 2025.10 β€” `figma_import_tokens` applies the complete diff plan (creates missing collections/variables, applies renames, writes real `VARIABLE_ALIAS` references, and deletes only under explicit `replace`), `figma_export_tokens` speaks the DTCG 2025.10 dialect on request (legacy default byte-identical), variable scopes/codeSyntax round-trip via `$extensions`, `figma_setup_design_tokens` accepts alias values via DTCG brace references, and `figma_create_component_set` builds a full variant set from an axes matrix in one call. On top of the v1.33.x line: version-handshake fix (re-import banner only fires when plugin files actually changed), security dependency sweep, and the v1.33.0 connection UX overhaul (honest status pill derived from live connection state, `/health` auto-discovery with self-healing reconnect) + a 33-fix full-codebase audit (lossless DTCG multi-mode round-trips, cross-collection alias resolution, branch-URL correctness across REST tools, cache-poisoning and CSWSH fixes, bridge-first screenshots). Built on WCAG-accurate accessibility auditing (line height below 1.5Γ— is no longer mis-flagged as a failure; readability hints decoupled from conformance checks and scoped to multi-line text; code-side WCAG 1.4.12 check), a self-healing Desktop Bridge connection (zombie-process reaper + auto-reconnect watchdog β€” fixes the recurring "not connected until restart" bug), native variable binding on fills/strokes + typography control in the write tools, shared-library inspection (key-based component resolution + library variable read/import without Enterprise plan), 10-format token export pipeline (DTCG, CSS, Tailwind v4, Tailwind v3, SCSS, TS module, JSON flat/nested, Style Dictionary v3, Tokens Studio), bidirectional Figma↔code token sync, version history & time-series awareness, FigJam + Slides support, Cloud Write Relay, Design System Kit, WebSocket-only connectivity, smart multi-file tracking, **121 tools** (Local) / **96 tools** (Cloud) / read-only subset (Remote), Comments API, cross-MCP identity disambiguation, and MCP Apps.
877
+ **Current Status:** v1.42.1 (Stable) - Production-ready. Latest: commands to a plugin stuck on a timed-out script fail fast with a busy message instead of queuing behind it, port-exhaustion eviction ends the least recently used server instead of the oldest, and `figma_execute` accepts up to a 300 s timeout (server-only). On top of v1.42.0's `figma_get_comments` returning compact threads (root + replies, newest activity first) with `node_id`, `thread_id` and `since` filters and `limit`/`offset` paging, 30 threads by default; summary counts are per thread (server-only, PR #139). On top of v1.41.5's component-set analysis reporting gradient/image/paint-opacity, corner radius, typography and label text, swapped spacing tokens, nested layer geometry and vector shape changes (re-import the plugin). On top of v1.41.4's variant background/stroke and auto-layout changes. On top of v1.41.3's component-set analysis reporting changes inside nested layers (instance swaps, nested token changes, opacity on the variant itself) and no longer reports a layer hidden in every variant as a change (re-import the plugin). On top of v1.41.2's design-system summary and `figma_get_token_values` report the file's tokens (they always reported 0) (server-only). On top of v1.41.1's component-set analysis reports real variant differences (Figma's default variant, size and layer changes), component loading no longer times out on large files (throttled plugin timers), relevance-ranked component search, and `figma_get_variables` paging that works with `format: "full"` (re-import the plugin for the component fixes). On top of v1.41.0's Cloud Mode sign-in hardening (per-session tokens on `/sse`, single-use authorization codes bound to client, redirect URI and PKCE, a consent page for unrecognized destinations), a script-execution fix in the accessibility scanner, `figma_import_tokens` refusing empty imports and scoping `replace` deletes to imported collections, `figma_arrange_component_set` no longer deleting other arranged sets, live variable reads for token export/import, Windows orphan-server exit (PR #140), and `fileKey` for the Slots tools (PR #112) (server-only, no plugin re-import). On top of v1.40.9's composed colors (a color variable set to another color at an opacity, "grey/900 at 50%") export and import with the link to the primitive intact β€” `color-mix()` in CSS/Tailwind v4, `rgba()` in SCSS, an alpha modifier in Tokens Studio, the resolved color plus the composition in DTCG β€” where the export previously failed or wrote `[object Object]` (server-only, no plugin re-import). On top of v1.40.8's min/max width and height survive every way of extracting a component as JSON β€” the design system kit, the reconstruction format and `figma_get_file_data` now carry them, design-code parity compares them, and the reconstruction format returns real geometry again instead of 50Γ—50 placeholders when the plugin is connected (server-only, no plugin re-import). On top of v1.40.7's clearer Color Tokens table in generated docs β€” layers revealed by a boolean property are printed once under that property, and stroke/fill rows name the nested instance they belong to (server-only, no plugin re-import). On top of v1.40.6's overrides in extended variable collections are visible (previously reported as nonexistent), and a third round of generated-doc fidelity fixes β€” radius tokens read per corner, boolean props compared in Design-Code Parity, source links pinned to a commit, hidden layers linked to the property that shows them (server-only, no plugin re-import). On top of v1.40.5's clean dependency audit for the npm package β€” Worker-only dependencies (`@cloudflare/puppeteer`, which pulled in a high-severity `extract-zip` advisory with no upstream fix, and `agents`) no longer install for npm users, so `npm install figma-console-mcp` audits at 0 vulnerabilities and is 64 MB instead of 173 MB; the server also reports its real version to MCP clients instead of `0.1.0` (server-only, no plugin re-import). On top of v1.40.4's fixes found by live-testing v1.40.3 on hard production components β€” tools given a `fileUrl` now read variables, descriptions and annotations from THAT file rather than whichever file is active (previously every token name could vanish, or on an id collision come from the wrong file; `figma_get_component` could return a different component), a tool result over 16 MB no longer disconnects the server, anatomy labels sizing by the layout's real axes, and the icon/typography/anatomy output stays readable on large components (server-only, no plugin re-import). On top of v1.40.3's fidelity fixes for generated component docs on harder components β€” hidden layers are labeled instead of documented as rendered, one-sided borders report the weight that actually renders, typography and layer structure are compared across every variant instead of read from the first, gradients/shadows/opacity are no longer silently dropped, truncated trees say so, and `SLOT` properties are listed (server-only, no plugin re-import). On top of v1.40.2's data-loss fix for `figma_export_tokens` β€” with a different file active in Figma than intended, an export could replace a real token file with an empty one (or with another file's tokens) and report success; exports now refuse to write when a requested collection is missing, when the export is empty, when the target was generated from a different Figma file, or when overwriting would destroy tokens the export doesn't manage, and `strategy: "merge"` β€” documented as preserving code-only tokens but never implemented β€” is now a genuinely safe default (server-only, no plugin re-import). On top of v1.40.1's accuracy fixes for generated component docs across variants β€” a descendant's fill (typically an icon's) could be documented as a variant's Background, Color Token headings kept only a property literally named `Variant`, spacing was read from the first variant alone, and icons were only detected by layer name β€” plus `figma_export_tokens` accepting a file path as `outputPath` instead of failing with a raw `EEXIST` or silently creating a directory (server-only, no plugin re-import). On top of v1.40.0's design system extraction from production codebases β€” seven Local-Mode `figma_ds_*` tools that scan one or more apps (framework/styling/vendor detection, usage-ranked component inventory classified vendored/wrapped/pure-vendor/bespoke, variant inference from real call sites, duplicate detection, and an architecture pass separating UI-kit specializations from the missing generic primitives), mine the de-facto styling into DTCG tokens with per-token provenance (multi-mode CSS custom properties, SCSS, Tailwind config, shadcn HSL triples, utility-class frequency mining valued from the app's own theme), scaffold the design-system package with showcase docs pages, wire a fresh Storybook workshop to the app's real theme layers and fonts, deep-extract components for porting with CSF3 story scaffolds, verify with deterministic fidelity evals, and persist porting progress across sessions β€” the extracted tokens import straight into Figma variables via `figma_import_tokens`. On top of v1.39.1's fix for a plugin-update banner that could never be cleared β€” an older server instance nagging a newer plugin to re-import, which only ever installs the same or a newer plugin. On top of v1.39.0's multi-file execution β€” `figma_execute_across_files` runs one script against several Desktop Bridge-connected files concurrently (four files x 2s of work in ~3s, not ~8s), and `figma_execute` takes an optional `fileKey` to target a single file without moving the active file or releasing target lock; targeting must be explicit (`fileKeys` or `allFiles: true`), so nothing fans out to files you did not name. From community PR #107 by @Wolfr. Ships with a relay fix: `handleResult()` in the plugin's ui.html rebuilt each response field by field and silently dropped `resultAnalysis` and `fileContext`, so the `resultAnalysis.warning` check that `figma_execute`'s own description tells callers to perform has never been possible (re-import `manifest.json` for those two fields; everything else works without it). On top of v1.38.2's connection-stability fix β€” the server's own orphan reaper was terminating healthy MCP servers because its liveness probe used an IPv4 literal while the server binds the IPv6 loopback, which turned every kill-safety gate into a rubber stamp; this was the cause of recurring "Server disconnected" errors across all MCP clients. Alongside v1.38.1's fix for the shared-library variable tools, which had silently reported zero collections since v1.29.0 and reported failed imports as successes. On top of v1.38.0's ongoing component changelogs in generated docs β€” `figma_generate_component_doc` takes an opt-in `history` parameter that pulls per-component **design history** from Figma version history (each version diffed and scoped to that component, so renames, added properties, and token bindings show up as rows) alongside **code history** from `git log` on the component's source files, rendered as a `## History` section with design, code, and release-note tables. Prefers labeled versions, falls back to auto-saves when a file has none, and is off by default so existing calls are unchanged (server-only, no plugin re-import). On top of v1.37.x's design-system health audit for every client β€” `figma_audit_design_system_report` runs the dashboard's deterministic six-category scoring engine and returns the report as data with per-finding remediation, live-first fileKey-verified data (source disclosed), chunked per-category drill-down, and a 5-minute cache (server-only, no plugin re-import). On top of v1.36.0's target lock for multi-file parallel work β€” β€” `figma_navigate` takes a `lock: true` flag that pins the active file so an AI agent can work in one file while you work in another without commands routing to the wrong file. On top of v1.35.0's Figma Slots write support β€” create, inspect, populate, and reset Slots (GA at Config 2026) via 5 new tools (`figma_create_slot`, `figma_get_slots`, `figma_append_to_slot`, `figma_reset_slot`, `figma_add_slot_property`), live-validated against the GA Plugin API and based on community PR #77. On top of v1.34.0's Bidirectional Token Sync v2 + DTCG 2025.10 β€” `figma_import_tokens` applies the complete diff plan (creates missing collections/variables, applies renames, writes real `VARIABLE_ALIAS` references, and deletes only under explicit `replace`), `figma_export_tokens` speaks the DTCG 2025.10 dialect on request (legacy default byte-identical), variable scopes/codeSyntax round-trip via `$extensions`, `figma_setup_design_tokens` accepts alias values via DTCG brace references, and `figma_create_component_set` builds a full variant set from an axes matrix in one call. On top of the v1.33.x line: version-handshake fix (re-import banner only fires when plugin files actually changed), security dependency sweep, and the v1.33.0 connection UX overhaul (honest status pill derived from live connection state, `/health` auto-discovery with self-healing reconnect) + a 33-fix full-codebase audit (lossless DTCG multi-mode round-trips, cross-collection alias resolution, branch-URL correctness across REST tools, cache-poisoning and CSWSH fixes, bridge-first screenshots). Built on WCAG-accurate accessibility auditing (line height below 1.5Γ— is no longer mis-flagged as a failure; readability hints decoupled from conformance checks and scoped to multi-line text; code-side WCAG 1.4.12 check), a self-healing Desktop Bridge connection (zombie-process reaper + auto-reconnect watchdog β€” fixes the recurring "not connected until restart" bug), native variable binding on fills/strokes + typography control in the write tools, shared-library inspection (key-based component resolution + library variable read/import without Enterprise plan), 10-format token export pipeline (DTCG, CSS, Tailwind v4, Tailwind v3, SCSS, TS module, JSON flat/nested, Style Dictionary v3, Tokens Studio), bidirectional Figma↔code token sync, version history & time-series awareness, FigJam + Slides support, Cloud Write Relay, Design System Kit, WebSocket-only connectivity, smart multi-file tracking, **121 tools** (Local) / **96 tools** (Cloud) / read-only subset (Remote), Comments API, cross-MCP identity disambiguation, and MCP Apps.
878
878
 
879
879
  **Recent Releases:**
880
+ - [x] **v1.42.1** - Fail fast while the plugin is stuck on a timed-out script (#94); evict the least recently used server, never one in use (#69); `figma_execute` timeout up to 300 s. Server-only.
881
+ - [x] **v1.42.0** - `figma_get_comments` compact threads with node/thread/date filters and paging, 30 threads by default (PR #139 by @OAPrilepa). Server-only.
880
882
  - [x] **v1.41.5** - Component-set analysis diffs paints (gradients, images, opacity), corner radius, typography and label text, swapped tokens (`tokens`), nested size/position/rotation and vector shapes. Plugin re-import.
881
883
  - [x] **v1.41.4** - Component-set analysis diffs the variant's own fill/stroke (button backgrounds) and auto-layout (`layout`). Plugin re-import.
882
884
  - [x] **v1.41.3** - Component-set analysis diffs nested layers by path (instance swaps, nested fill/stroke tokens), variant-level opacity, and visibility in both directions; a layer hidden in every variant is no longer reported as a change. Plugin re-import.
@@ -5,7 +5,15 @@
5
5
  */
6
6
  import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
7
7
  import type { FigmaAPI } from "./figma-api.js";
8
+ interface CommentThread {
9
+ root: any;
10
+ replies: any[];
11
+ lastActivity: number;
12
+ }
13
+ /** Groups the flat REST list into threads, newest activity first. */
14
+ export declare function buildThreads(comments: any[]): CommentThread[];
8
15
  export declare function registerCommentTools(server: McpServer, getFigmaAPI: () => Promise<FigmaAPI>, getCurrentUrl: () => string | null, options?: {
9
16
  isRemoteMode?: boolean;
10
17
  }): void;
18
+ export {};
11
19
  //# sourceMappingURL=comment-tools.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"comment-tools.d.ts","sourceRoot":"","sources":["../../src/core/comment-tools.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAU/C,wBAAgB,oBAAoB,CACnC,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,MAAM,OAAO,CAAC,QAAQ,CAAC,EACpC,aAAa,EAAE,MAAM,MAAM,GAAG,IAAI,EAClC,OAAO,CAAC,EAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE,GAClC,IAAI,CAgUN"}
1
+ {"version":3,"file":"comment-tools.d.ts","sourceRoot":"","sources":["../../src/core/comment-tools.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAU/C,UAAU,aAAa;IACtB,IAAI,EAAE,GAAG,CAAC;IACV,OAAO,EAAE,GAAG,EAAE,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;CACrB;AAOD,qEAAqE;AACrE,wBAAgB,YAAY,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,aAAa,EAAE,CAwB7D;AA4CD,wBAAgB,oBAAoB,CACnC,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,MAAM,OAAO,CAAC,QAAQ,CAAC,EACpC,aAAa,EAAE,MAAM,MAAM,GAAG,IAAI,EAClC,OAAO,CAAC,EAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE,GAClC,IAAI,CA+bN"}
@@ -4,9 +4,81 @@
4
4
  * Works in both local and Cloudflare Workers modes β€” no Plugin API dependency.
5
5
  */
6
6
  import { z } from "zod";
7
- import { extractFileKey } from "./figma-api.js";
7
+ import { extractFileKey, normalizeNodeId } from "./figma-api.js";
8
8
  import { createChildLogger } from "./logger.js";
9
9
  const logger = createChildLogger({ component: "comment-tools" });
10
+ function timeOf(comment) {
11
+ const t = Date.parse(comment?.created_at ?? "");
12
+ return Number.isNaN(t) ? 0 : t;
13
+ }
14
+ /** Groups the flat REST list into threads, newest activity first. */
15
+ export function buildThreads(comments) {
16
+ const byRoot = new Map();
17
+ for (const c of comments) {
18
+ if (!c.parent_id) {
19
+ byRoot.set(c.id, { root: c, replies: [], lastActivity: timeOf(c) });
20
+ }
21
+ }
22
+ for (const c of comments) {
23
+ if (!c.parent_id)
24
+ continue;
25
+ const thread = byRoot.get(c.parent_id);
26
+ // A reply whose root is missing is still shown, as its own thread.
27
+ if (!thread) {
28
+ byRoot.set(c.id, { root: c, replies: [], lastActivity: timeOf(c) });
29
+ continue;
30
+ }
31
+ thread.replies.push(c);
32
+ thread.lastActivity = Math.max(thread.lastActivity, timeOf(c));
33
+ }
34
+ const threads = [...byRoot.values()];
35
+ for (const t of threads) {
36
+ t.replies.sort((a, b) => timeOf(a) - timeOf(b));
37
+ }
38
+ threads.sort((a, b) => b.lastActivity - a.lastActivity);
39
+ return threads;
40
+ }
41
+ function collectNodeIds(node, ids) {
42
+ if (!node)
43
+ return;
44
+ if (node.id)
45
+ ids.add(node.id);
46
+ for (const child of node.children ?? []) {
47
+ collectNodeIds(child, ids);
48
+ }
49
+ }
50
+ function reactionCounts(reactions) {
51
+ if (!reactions?.length)
52
+ return undefined;
53
+ const counts = {};
54
+ for (const r of reactions) {
55
+ counts[r.emoji] = (counts[r.emoji] ?? 0) + 1;
56
+ }
57
+ return counts;
58
+ }
59
+ function compactComment(c) {
60
+ const out = {
61
+ id: c.id,
62
+ author: c.user?.handle,
63
+ created_at: c.created_at,
64
+ message: c.message,
65
+ };
66
+ const reactions = reactionCounts(c.reactions);
67
+ if (reactions)
68
+ out.reactions = reactions;
69
+ return out;
70
+ }
71
+ function compactThread(t) {
72
+ const out = compactComment(t.root);
73
+ const meta = t.root.client_meta;
74
+ if (meta?.node_id)
75
+ out.node_id = meta.node_id;
76
+ if (t.root.resolved_at)
77
+ out.resolved_at = t.root.resolved_at;
78
+ if (t.replies.length)
79
+ out.replies = t.replies.map(compactComment);
80
+ return out;
81
+ }
10
82
  // ============================================================================
11
83
  // Tool Registration
12
84
  // ============================================================================
@@ -14,12 +86,12 @@ export function registerCommentTools(server, getFigmaAPI, getCurrentUrl, options
14
86
  // -----------------------------------------------------------------------
15
87
  // Tool: figma_get_comments
16
88
  // -----------------------------------------------------------------------
17
- server.tool("figma_get_comments", "Get comments on a Figma file. Returns comment threads with author, message, timestamps, and pinned node locations. Use include_resolved to also see resolved comments.", {
89
+ server.tool("figma_get_comments", "Get comment threads on a Figma file. Returns threads (root comment + replies) sorted by latest activity, in a compact format by default (author handle, message, timestamps, pinned node, reaction counts). Narrow the result with an explicit node_id (includes comments pinned to nested nodes), thread_id or since, and page with limit/offset β€” files often have hundreds of comments. Use include_resolved to also see resolved threads and format='full' for raw Figma API objects.", {
18
90
  fileUrl: z
19
91
  .string()
20
92
  .url()
21
93
  .optional()
22
- .describe("Figma file URL. Uses current URL if omitted."),
94
+ .describe("Figma file URL. Uses current URL if omitted. A node-id in the URL does not filter comments; use node_id explicitly."),
23
95
  as_md: z
24
96
  .boolean()
25
97
  .optional()
@@ -29,8 +101,45 @@ export function registerCommentTools(server, getFigmaAPI, getCurrentUrl, options
29
101
  .boolean()
30
102
  .optional()
31
103
  .default(false)
32
- .describe("Include resolved (completed) comment threads. Default: false (only active comments)"),
33
- }, async ({ fileUrl, as_md = false, include_resolved = false }) => {
104
+ .describe("Include resolved (completed) comment threads. Default: false (only active threads unless thread_id is given)"),
105
+ node_id: z
106
+ .string()
107
+ .optional()
108
+ .describe("Only threads pinned to this node (e.g. '695:313' or '695-313') or, with include_nested, to any node inside it. Omit or pass an empty string to return threads across the file."),
109
+ include_nested: z
110
+ .boolean()
111
+ .optional()
112
+ .default(true)
113
+ .describe("With node_id: also match threads pinned to descendants of the node (one extra REST call). Default: true"),
114
+ thread_id: z
115
+ .string()
116
+ .optional()
117
+ .describe("Return only the thread containing this comment ID (root or reply), including resolved threads."),
118
+ since: z
119
+ .string()
120
+ .optional()
121
+ .describe("ISO date/time: only threads with a comment or reply created at or after it."),
122
+ limit: z
123
+ .number()
124
+ .int()
125
+ .min(1)
126
+ .max(200)
127
+ .optional()
128
+ .default(30)
129
+ .describe("Maximum threads to return. Default: 30"),
130
+ offset: z
131
+ .number()
132
+ .int()
133
+ .min(0)
134
+ .optional()
135
+ .default(0)
136
+ .describe("Threads to skip, for paging. Default: 0"),
137
+ format: z
138
+ .enum(["compact", "full"])
139
+ .optional()
140
+ .default("compact")
141
+ .describe("'compact' (default) β€” trimmed fields; 'full' β€” raw Figma API comment objects."),
142
+ }, async ({ fileUrl, as_md = false, include_resolved = false, node_id, include_nested = true, thread_id, since, limit = 30, offset = 0, format = "compact", }) => {
34
143
  try {
35
144
  const url = fileUrl || getCurrentUrl();
36
145
  if (!url) {
@@ -62,21 +171,89 @@ export function registerCommentTools(server, getFigmaAPI, getCurrentUrl, options
62
171
  isError: true,
63
172
  };
64
173
  }
65
- logger.info({ fileKey, as_md, include_resolved }, "Fetching comments");
174
+ let sinceTime;
175
+ if (since) {
176
+ sinceTime = Date.parse(since);
177
+ if (Number.isNaN(sinceTime)) {
178
+ return {
179
+ content: [
180
+ {
181
+ type: "text",
182
+ text: JSON.stringify({
183
+ error: "invalid_since",
184
+ message: `Invalid since date: ${since}`,
185
+ }),
186
+ },
187
+ ],
188
+ isError: true,
189
+ };
190
+ }
191
+ }
192
+ const targetNode = node_id || undefined;
193
+ logger.info({ fileKey, as_md, include_resolved, targetNode, thread_id, since, limit, offset, format }, "Fetching comments");
66
194
  const api = await getFigmaAPI();
67
195
  const response = await api.getComments(fileKey, { as_md });
68
196
  const allComments = response.comments || [];
69
- // Filter out resolved comments unless explicitly requested
70
- const comments = include_resolved
71
- ? allComments
72
- : allComments.filter((c) => !c.resolved_at);
197
+ const threads = buildThreads(allComments);
198
+ let selected = include_resolved || thread_id
199
+ ? threads
200
+ : threads.filter((t) => !t.root.resolved_at);
201
+ let nodeIds;
202
+ if (targetNode) {
203
+ const normalized = normalizeNodeId(targetNode);
204
+ nodeIds = new Set([normalized]);
205
+ if (include_nested) {
206
+ const nodes = await api.getNodes(fileKey, [normalized]);
207
+ const document = nodes?.nodes?.[normalized]?.document;
208
+ if (!document) {
209
+ return {
210
+ content: [
211
+ {
212
+ type: "text",
213
+ text: JSON.stringify({
214
+ error: "node_not_found",
215
+ message: `Node ${normalized} not found in file ${fileKey}`,
216
+ }),
217
+ },
218
+ ],
219
+ isError: true,
220
+ };
221
+ }
222
+ collectNodeIds(document, nodeIds);
223
+ }
224
+ const ids = nodeIds;
225
+ selected = selected.filter((t) => {
226
+ const pinned = t.root.client_meta?.node_id;
227
+ return pinned !== undefined && ids.has(pinned);
228
+ });
229
+ }
230
+ if (thread_id) {
231
+ const byId = allComments.find((c) => c.id === thread_id);
232
+ const rootId = byId ? byId.parent_id || byId.id : thread_id;
233
+ selected = selected.filter((t) => t.root.id === rootId);
234
+ }
235
+ if (sinceTime !== undefined) {
236
+ const from = sinceTime;
237
+ selected = selected.filter((t) => t.lastActivity >= from);
238
+ }
239
+ const page = selected.slice(offset, offset + limit);
240
+ const comments = page.map((t) => format === "full"
241
+ ? { ...t.root, replies: t.replies }
242
+ : compactThread(t));
73
243
  const result = {
74
244
  comments,
75
245
  summary: {
76
- total: allComments.length,
77
- active: allComments.filter((c) => !c.resolved_at).length,
78
- resolved: allComments.filter((c) => c.resolved_at).length,
246
+ total: threads.length,
247
+ active: threads.filter((t) => !t.root.resolved_at).length,
248
+ resolved: threads.filter((t) => t.root.resolved_at).length,
249
+ comments_total: allComments.length,
250
+ matched: selected.length,
79
251
  returned: comments.length,
252
+ offset,
253
+ has_more: offset + comments.length < selected.length,
254
+ ...(targetNode
255
+ ? { node_id: normalizeNodeId(targetNode), nested_nodes: nodeIds?.size }
256
+ : {}),
80
257
  },
81
258
  };
82
259
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"comment-tools.js","sourceRoot":"","sources":["../../src/core/comment-tools.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"comment-tools.js","sourceRoot":"","sources":["../../src/core/comment-tools.ts"],"names":[],"mappings":"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"}
@@ -53,5 +53,7 @@ export declare function capToolResponse(result: unknown, maxBytes?: number): unk
53
53
  * Adds attribution coverage to every response path uniformly β€” see
54
54
  * project_lauren_cross_mcp_confusion for why this matters.
55
55
  */
56
- export declare function wrapServerForIdentity(server: McpServer): void;
56
+ export declare function wrapServerForIdentity(server: McpServer, options?: {
57
+ onToolCall?: () => void;
58
+ }): void;
57
59
  //# sourceMappingURL=identity.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/core/identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,eAAO,MAAM,QAAQ,sBAAsB,CAAC;AAE5C,eAAO,MAAM,YAAY,wBAAkB,CAAC;AAE5C;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,CAEtD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7D,IAAI,EAAE,CAAC,GACL,CAAC,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAEtB;AA0CD;;;;;;;;;GASG;AACH,eAAO,MAAM,uBAAuB,QAAkB,CAAC;AAEvD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,GAAE,MAAgC,GAAG,OAAO,CA+BpG;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA6B7D"}
1
+ {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/core/identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,eAAO,MAAM,QAAQ,sBAAsB,CAAC;AAE5C,eAAO,MAAM,YAAY,wBAAkB,CAAC;AAE5C;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,CAEtD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7D,IAAI,EAAE,CAAC,GACL,CAAC,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAEtB;AA0CD;;;;;;;;;GASG;AACH,eAAO,MAAM,uBAAuB,QAAkB,CAAC;AAEvD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,GAAE,MAAgC,GAAG,OAAO,CA+BpG;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CACpC,MAAM,EAAE,SAAS,EACjB,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,IAAI,CAAA;CAAO,GACvC,IAAI,CA8BN"}
@@ -118,7 +118,7 @@ export function capToolResponse(result, maxBytes = MAX_TOOL_RESPONSE_BYTES) {
118
118
  * Adds attribution coverage to every response path uniformly β€” see
119
119
  * project_lauren_cross_mcp_confusion for why this matters.
120
120
  */
121
- export function wrapServerForIdentity(server) {
121
+ export function wrapServerForIdentity(server, options = {}) {
122
122
  const target = server;
123
123
  const originalTool = target.tool.bind(target);
124
124
  target.tool = function (...args) {
@@ -127,6 +127,7 @@ export function wrapServerForIdentity(server) {
127
127
  }
128
128
  const handler = args[args.length - 1];
129
129
  const wrappedHandler = async (...handlerArgs) => {
130
+ options.onToolCall?.();
130
131
  try {
131
132
  const result = await handler(...handlerArgs);
132
133
  return capToolResponse(tagToolResponse(result));
@@ -1 +1 @@
1
- {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/core/identity.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/core/identity.ts"],"names":[],"mappings":"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"}
@@ -59,7 +59,15 @@ export interface PortFileData {
59
59
  startedAt: string;
60
60
  /** Updated by heartbeat every 30s. Missing in port files from pre-v1.12 instances. */
61
61
  lastSeen?: string;
62
+ /** Last time this server handled a tool call. Missing until the first call, and in pre-v1.42.1 files. */
63
+ lastToolCall?: string;
62
64
  }
65
+ /**
66
+ * Record that this server just handled a tool call (see evictOldestInstance).
67
+ * Written to the port file right away (throttled), so a server in use never
68
+ * looks idle to a sibling deciding whom to evict.
69
+ */
70
+ export declare function noteToolCall(): void;
63
71
  /**
64
72
  * Try to bind a WebSocket server to ports in a range, starting from the preferred port.
65
73
  * Returns the first port that binds successfully.
@@ -164,7 +172,11 @@ export declare function cleanupOrphanedProcessesAsync(preferredPort?: number, op
164
172
  minAgeMs?: number;
165
173
  }): Promise<number>;
166
174
  /**
167
- * Last-resort eviction: terminate the oldest MCP server instance to free a port.
175
+ * Last-resort eviction: terminate the least recently used MCP server instance to free a port.
176
+ *
177
+ * "Least recently used" is the last tool call, falling back to start time for
178
+ * a server that has never handled one. So a server started for a thread that
179
+ * never touched Figma goes before an older one a thread is still working with.
168
180
  *
169
181
  * Called ONLY when all ports in the range are exhausted after both cleanup phases
170
182
  * (cleanupStalePortFiles + cleanupOrphanedProcesses) have already run. This handles
@@ -1 +1 @@
1
- {"version":3,"file":"port-discovery.d.ts","sourceRoot":"","sources":["../../src/core/port-discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAaH,uCAAuC;AACvC,eAAO,MAAM,eAAe,OAAO,CAAC;AAEpC,mEAAmE;AACnE,eAAO,MAAM,eAAe,KAAK,CAAC;AAQlC,qFAAqF;AACrF,eAAO,MAAM,oBAAoB,QAAqB,CAAC;AAEvD,yFAAyF;AACzF,eAAO,MAAM,kBAAkB,QAAgB,CAAC;AAEhD,mEAAmE;AACnE,eAAO,MAAM,kBAAkB,MAAM,CAAC;AAEtC;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,QAAY,CAAC;AAE3C,uDAAuD;AACvD,eAAO,MAAM,gBAAgB,QAAgB,CAAC;AAE9C,+EAA+E;AAC/E,eAAO,MAAM,mBAAmB,QAAgB,CAAC;AAEjD,wDAAwD;AACxD,eAAO,MAAM,qBAAqB,QAAY,CAAC;AAE/C,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,sFAAsF;IACtF,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,aAAa,GAAE,MAAwB,GAAG,MAAM,EAAE,CAM9E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,MAAoB,GAAG,IAAI,CAkB5E;AA0BD;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAsB3D;AAaD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAalD;AAcD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAY3D;AAED;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,QAA4B,CAAC;AAwOtE;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAoB9D;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,aAAa,GAAE,MAAwB,GAAG,YAAY,EAAE,CAW/F;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CA+D9C;AAED;;;;;;;;GAQG;AACH,wBAAsB,0BAA0B,IAAI,OAAO,CAAC,MAAM,CAAC,CA+DlE;AAED;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CACtC,aAAa,GAAE,MAAwB,EACvC,OAAO,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAClC,MAAM,CA4FR;AAiDD;;;;;;;;GAQG;AACH,wBAAsB,6BAA6B,CACjD,aAAa,GAAE,MAAwB,EACvC,OAAO,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAClC,OAAO,CAAC,MAAM,CAAC,CA0EjB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,mBAAmB,CAAC,aAAa,GAAE,MAAwB,GAAG,OAAO,CA0EpF;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAStD;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,mBAAmB,CAAC,aAAa,GAAE,MAAwB,GAAG,MAAM,IAAI,CAgCvF"}
1
+ {"version":3,"file":"port-discovery.d.ts","sourceRoot":"","sources":["../../src/core/port-discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAaH,uCAAuC;AACvC,eAAO,MAAM,eAAe,OAAO,CAAC;AAEpC,mEAAmE;AACnE,eAAO,MAAM,eAAe,KAAK,CAAC;AAQlC,qFAAqF;AACrF,eAAO,MAAM,oBAAoB,QAAqB,CAAC;AAEvD,yFAAyF;AACzF,eAAO,MAAM,kBAAkB,QAAgB,CAAC;AAEhD,mEAAmE;AACnE,eAAO,MAAM,kBAAkB,MAAM,CAAC;AAEtC;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,QAAY,CAAC;AAE3C,uDAAuD;AACvD,eAAO,MAAM,gBAAgB,QAAgB,CAAC;AAE9C,+EAA+E;AAC/E,eAAO,MAAM,mBAAmB,QAAgB,CAAC;AAEjD,wDAAwD;AACxD,eAAO,MAAM,qBAAqB,QAAY,CAAC;AAE/C,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,sFAAsF;IACtF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yGAAyG;IACzG,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AASD;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,IAAI,CAMnC;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,aAAa,GAAE,MAAwB,GAAG,MAAM,EAAE,CAM9E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,MAAoB,GAAG,IAAI,CAkB5E;AA0BD;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAuB3D;AAaD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAalD;AAcD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAY3D;AAED;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,QAA4B,CAAC;AAwOtE;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAoB9D;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,aAAa,GAAE,MAAwB,GAAG,YAAY,EAAE,CAW/F;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CA+D9C;AAED;;;;;;;;GAQG;AACH,wBAAsB,0BAA0B,IAAI,OAAO,CAAC,MAAM,CAAC,CA+DlE;AAED;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CACtC,aAAa,GAAE,MAAwB,EACvC,OAAO,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAClC,MAAM,CA4FR;AAiDD;;;;;;;;GAQG;AACH,wBAAsB,6BAA6B,CACjD,aAAa,GAAE,MAAwB,EACvC,OAAO,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAClC,OAAO,CAAC,MAAM,CAAC,CA0EjB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,mBAAmB,CAAC,aAAa,GAAE,MAAwB,GAAG,OAAO,CAmFpF;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAStD;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,mBAAmB,CAAC,aAAa,GAAE,MAAwB,GAAG,MAAM,IAAI,CAgCvF"}
@@ -64,6 +64,25 @@ export const REAP_INTERVAL_MS = 5 * 60 * 1000;
64
64
  export const EVICTION_MIN_AGE_MS = 2 * 60 * 1000;
65
65
  /** Interval between heartbeat refreshes (30 seconds) */
66
66
  export const HEARTBEAT_INTERVAL_MS = 30 * 1000;
67
+ /** When this process last handled a tool call; written to its port file by the heartbeat. */
68
+ let lastToolCallAt;
69
+ let lastToolCallWrite = 0;
70
+ /** Write-through at most this often; the 30s heartbeat covers the rest. */
71
+ const TOOL_CALL_WRITE_INTERVAL_MS = 10_000;
72
+ /**
73
+ * Record that this server just handled a tool call (see evictOldestInstance).
74
+ * Written to the port file right away (throttled), so a server in use never
75
+ * looks idle to a sibling deciding whom to evict.
76
+ */
77
+ export function noteToolCall() {
78
+ lastToolCallAt = new Date().toISOString();
79
+ const now = Date.now();
80
+ if (now - lastToolCallWrite < TOOL_CALL_WRITE_INTERVAL_MS)
81
+ return;
82
+ lastToolCallWrite = now;
83
+ for (const port of advertisedPorts)
84
+ refreshPortAdvertisement(port);
85
+ }
67
86
  /**
68
87
  * Try to bind a WebSocket server to ports in a range, starting from the preferred port.
69
88
  * Returns the first port that binds successfully.
@@ -161,6 +180,8 @@ export function refreshPortAdvertisement(port) {
161
180
  if (data.pid !== process.pid)
162
181
  return;
163
182
  data.lastSeen = new Date().toISOString();
183
+ if (lastToolCallAt)
184
+ data.lastToolCall = lastToolCallAt;
164
185
  writePortFileAtomic(filePath, data);
165
186
  }
166
187
  catch {
@@ -861,7 +882,11 @@ export async function cleanupOrphanedProcessesAsync(preferredPort = DEFAULT_WS_P
861
882
  return cleaned;
862
883
  }
863
884
  /**
864
- * Last-resort eviction: terminate the oldest MCP server instance to free a port.
885
+ * Last-resort eviction: terminate the least recently used MCP server instance to free a port.
886
+ *
887
+ * "Least recently used" is the last tool call, falling back to start time for
888
+ * a server that has never handled one. So a server started for a thread that
889
+ * never touched Figma goes before an older one a thread is still working with.
865
890
  *
866
891
  * Called ONLY when all ports in the range are exhausted after both cleanup phases
867
892
  * (cleanupStalePortFiles + cleanupOrphanedProcesses) have already run. This handles
@@ -910,15 +935,22 @@ export function evictOldestInstance(preferredPort = DEFAULT_WS_PORT) {
910
935
  logger.debug('No eviction candidates β€” ports may be held by non-MCP processes');
911
936
  return false;
912
937
  }
913
- // Sort by startedAt ascending β€” oldest first
914
- candidates.sort((a, b) => new Date(a.startedAt).getTime() - new Date(b.startedAt).getTime());
915
- const oldest = candidates[0];
916
- const ageMs = Date.now() - new Date(oldest.startedAt).getTime();
917
- // Safety: don't evict instances that started recently (prevents cascade)
918
- if (ageMs < EVICTION_MIN_AGE_MS) {
919
- logger.info({ port: oldest.port, pid: oldest.pid, ageSeconds: Math.round(ageMs / 1000) }, 'Oldest instance is too recent to evict β€” skipping');
938
+ // Least recently used first: last tool call, else start time. A server that
939
+ // has never handled a tool call sorts by when it started, ahead of any
940
+ // server used since then. Servers started or used in the last
941
+ // EVICTION_MIN_AGE_MS are never evicted (prevents cascades, and never cuts
942
+ // off a thread mid-task).
943
+ const lastUsed = (c) => new Date(c.lastToolCall ?? c.startedAt).getTime();
944
+ const now = Date.now();
945
+ const eligible = candidates
946
+ .filter((c) => now - new Date(c.startedAt).getTime() >= EVICTION_MIN_AGE_MS && now - lastUsed(c) >= EVICTION_MIN_AGE_MS)
947
+ .sort((a, b) => lastUsed(a) - lastUsed(b));
948
+ if (eligible.length === 0) {
949
+ logger.info({ candidates: candidates.length }, 'Every other instance started or handled a tool call recently β€” skipping eviction');
920
950
  return false;
921
951
  }
952
+ const oldest = eligible[0];
953
+ const ageMs = now - new Date(oldest.startedAt).getTime();
922
954
  // Re-read the port file to avoid TOCTOU race
923
955
  try {
924
956
  const raw = readFileSync(oldest.filePath, 'utf-8');
@@ -927,12 +959,16 @@ export function evictOldestInstance(preferredPort = DEFAULT_WS_PORT) {
927
959
  // PID changed between reads β€” another process took over, skip
928
960
  return false;
929
961
  }
962
+ if (Date.now() - lastUsed(freshData) < EVICTION_MIN_AGE_MS) {
963
+ // It handled a tool call since we first read it β€” it's in use, skip
964
+ return false;
965
+ }
930
966
  }
931
967
  catch {
932
968
  // File disappeared β€” port may already be free
933
969
  return true;
934
970
  }
935
- logger.info({ port: oldest.port, pid: oldest.pid, startedAt: oldest.startedAt, ageHours: Math.round(ageMs / 3600000 * 10) / 10 }, 'Evicting oldest MCP server instance to free port (all ports exhausted)');
971
+ logger.info({ port: oldest.port, pid: oldest.pid, startedAt: oldest.startedAt, lastToolCall: oldest.lastToolCall ?? null, ageHours: Math.round(ageMs / 3600000 * 10) / 10 }, 'Evicting least recently used MCP server instance to free port (all ports exhausted)');
936
972
  terminateProcess(oldest.pid);
937
973
  try {
938
974
  unlinkSync(oldest.filePath);