figma-relai 0.2.1 → 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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/server.ts","../../shared/src/types/commands.ts","../../shared/src/pitfalls.ts","../../shared/src/utils/color.ts","../../shared/src/utils/schemas.ts","../../shared/src/relay-core.ts","../src/tools/index.ts","../src/tools/core/create.ts","../src/tools/core/helpers.ts","../src/tools/core/properties.ts","../src/tools/core/structure.ts","../src/tools/core/text.ts","../src/tools/core/components.ts","../src/tools/core/variables.ts","../src/tools/core/styles.ts","../src/tools/core/pages.ts","../src/tools/core/navigate.ts","../src/tools/core/assets.ts","../src/tools/core/library.ts","../src/tools/core/annotate.ts","../src/tools/core/read.ts","../src/tools/core/execute.ts","../src/tools/core/comments.ts","../src/tools/core/design-system.ts","../src/tools/batch.ts","../src/tools/v2/context.ts","../src/semantic/response.ts","../src/semantic/errors.ts","../src/semantic/normalize.ts","../src/tools/v2/analysis.ts","../src/semantic/health.ts","../src/tools/v2/verification.ts","../../../docs/skills/figma-plugin-api.md","../../../docs/skills/design-tokens-strategy.md","../../../docs/skills/component-architecture-strategy.md","../../../docs/skills/design-audit-strategy.md","../../../docs/skills/token-audit.md","../../../docs/skills/component-spec.md","../../../docs/skills/comment-driven-tasks.md","../../../docs/skills/design-system-first.md","../../../docs/skills/janitorial-cleanup.md","../src/prompts.ts"],"sourcesContent":["import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\n\n// Create and configure the MCP server instance\nexport function createServer(): McpServer {\n return new McpServer(\n {\n name: \"Relai\",\n version: \"0.2.2\",\n },\n {\n instructions: `\nYou control Figma through ~30 consolidated tools. Pairing with the Figma plugin is automatic — just call any tool; join_room is only needed if an error reports multiple plugins.\n\n📖 UNDERSTAND (start here):\n get_document_overview — structure, page/component/style/variable counts\n get_selection_context — full context for what the designer selected\n get_node_details — deep single-node inspection (CSS, token bindings)\n search_nodes — find nodes by name/type · get_node_data — raw data/tree/css\n get_design_tokens — variable collections, modes, styles\n screenshot — see the canvas (use this to verify your work visually)\n\n🔍 DIAGNOSE:\n analyze_design — aspect: color/layout/components/accessibility, or\n \"overall\" for a weighted 0-100 health score across all four\n diff_nodes — compare two nodes, or checkpoint save/compare to audit\n what changed on a node over an editing session\n\n✏️ EDIT:\n create_node — any node type (rectangle/frame/text/svg/image/…)\n set_properties — one call for geometry, fills, strokes, effects, text,\n auto-layout, constraints, style/variable bindings, on one or many nodes\n set_text — single, bulk, or character-range text edits\n edit_structure — group/reparent/reorder/clone/flatten/boolean/delete\n navigate — focus/select/viewport/switch_page · manage_pages\n\n🧱 DESIGN SYSTEM:\n manage_components — create/variants/instantiate/overrides/props/detach\n manage_variables — collections, modes, tokens, bind/unbind\n manage_styles — paint/text/effect/grid styles\n import_from_library — bring in library components/styles/variables\n\n📦 ASSETS: export_asset (PNG/JPG/SVG/PDF) · add_image (URL or fill)\n📝 ANNOTATIONS: annotate (Dev Mode annotations)\n💬 COMMENTS: manage_comments — read/apply/reply to file comments\n (needs FIGMA_TOKEN env; the tool explains setup when missing)\n\n✅ VERIFY: verify_changes · validate_design_rules\n\n⚡ ADVANCED:\n batch_execute — run many plugin-level commands in one round-trip\n execute_figma — run JavaScript against the Figma Plugin API directly\n (the escape hatch when no tool fits; small incremental scripts,\n screenshot between steps; the designer can disable it)\n\nOPERATING PRINCIPLES:\n- Inspect context BEFORE changing things; don't assume selection state\n- After visual edits, verify: screenshot or verify_changes\n- Colors are RGBA in 0-1 range (Figma format), not 0-255\n- layoutSizing FILL requires the node's PARENT to have auto-layout;\n set layoutMode on a frame before padding/alignment/spacing\n- Responses include recommended_next tools — follow them\n- Errors name the node, its type, and the fix — read them, don't retry blindly\n`,\n }\n );\n}\n","// All Figma commands supported by the MCP server and plugin\n\nexport const FIGMA_COMMANDS = [\n // Document & Selection\n \"get_document_info\",\n \"get_file_info\",\n \"get_selection\",\n \"read_my_design\",\n \"get_node_info\",\n \"get_node_tree\",\n \"get_nodes_info\",\n \"scan_nodes_by_types\",\n \"get_css\",\n \"find_nodes\",\n \"get_bound_variables\",\n // Creation\n \"create_rectangle\",\n \"create_frame\",\n \"create_text\",\n \"create_ellipse\",\n \"create_polygon\",\n \"create_star\",\n \"create_line\",\n \"create_component_instance\",\n \"create_section\",\n \"create_node_from_svg\",\n \"create_connector\",\n \"create_table\",\n \"create_sticky\",\n \"create_code_block\",\n \"create_slice\",\n // Modification\n \"move_node\",\n \"resize_node\",\n \"clone_node\",\n \"delete_node\",\n \"delete_multiple_nodes\",\n \"rename_node\",\n \"set_opacity\",\n \"reorder_node\",\n \"set_visible\",\n \"set_locked\",\n \"reparent_node\",\n \"set_rotation\",\n \"set_relaunch_data\",\n \"get_relaunch_data\",\n // Styling\n \"set_fill_color\",\n \"set_fills\",\n \"set_stroke_color\",\n \"set_corner_radius\",\n \"set_blend_mode\",\n \"set_gradient_fill\",\n \"set_clips_content\",\n \"set_layout_grids\",\n \"set_aspect_ratio\",\n // Effects\n \"add_drop_shadow\",\n \"add_inner_shadow\",\n \"add_blur\",\n \"add_background_blur\",\n \"remove_effects\",\n // Text\n \"scan_text_nodes\",\n \"set_text_content\",\n \"set_multiple_text_contents\",\n \"set_text_style_range\",\n // Layout\n \"set_layout_mode\",\n \"set_padding\",\n \"set_axis_align\",\n \"set_layout_sizing\",\n \"set_item_spacing\",\n // Design system\n \"get_design_system\",\n \"scan_token_drift\",\n \"get_conventions\",\n \"set_conventions\",\n // Components\n \"get_local_components\",\n \"get_instance_overrides\",\n \"set_instance_overrides\",\n \"create_component\",\n \"create_component_set\",\n \"get_component_properties\",\n \"set_component_properties\",\n \"detach_instance\",\n \"reset_instance\",\n \"audit_colors\",\n \"find_orphan_instances\",\n // Variables\n \"get_variable_collections\",\n \"get_variables\",\n \"create_variable_collection\",\n \"create_variable\",\n \"update_variable\",\n \"delete_variable\",\n \"delete_variable_collection\",\n \"update_variable_collection\",\n \"add_mode\",\n \"remove_mode\",\n \"rename_mode\",\n \"set_variable_scopes\",\n \"set_variable_code_syntax\",\n \"remove_variable_code_syntax\",\n \"create_variable_alias\",\n \"bind_variable\",\n \"unbind_variable\",\n \"set_node_variable_mode\",\n \"get_resolved_variable_modes\",\n // Styles\n \"get_styles\",\n \"create_paint_style\",\n \"create_text_style\",\n \"create_effect_style\",\n \"create_grid_style\",\n \"update_style\",\n \"delete_style\",\n \"apply_style\",\n \"reorder_style\",\n // Export\n \"export_node_as_image\",\n \"get_screenshot\",\n \"create_image_from_url\",\n // Page\n \"get_pages\",\n \"create_page\",\n \"rename_page\",\n \"delete_page\",\n \"switch_page\",\n \"set_page_background\",\n \"get_flow_starting_points\",\n // Structure\n \"group_nodes\",\n \"ungroup_nodes\",\n \"flatten_node\",\n \"boolean_operation\",\n \"create_component_from_node\",\n // Library\n \"import_component_by_key\",\n \"import_style_by_key\",\n \"import_variable_by_key\",\n // Document extras\n \"get_selection_colors\",\n \"set_file_thumbnail\",\n \"figma_notify\",\n // Constraints\n \"set_constraints\",\n \"set_min_max_size\",\n // Annotations\n \"get_annotations\",\n \"set_annotation\",\n \"set_multiple_annotations\",\n // Prototype\n \"get_reactions\",\n \"set_default_connector\",\n \"create_connections\",\n // Viewport\n \"set_focus\",\n \"set_selections\",\n \"get_viewport\",\n \"set_viewport\",\n // Plugin data\n \"set_plugin_data\",\n \"get_plugin_data\",\n // Image fill\n \"set_image_fill\",\n // Batch\n \"batch_execute\",\n \"execute_code\",\n // Room\n \"join\",\n] as const;\n\nexport type FigmaCommand = (typeof FIGMA_COMMANDS)[number];\n\n// Color type used across the system (0-1 range)\nexport interface RGBAColor {\n r: number;\n g: number;\n b: number;\n a?: number;\n}\n\n// Gradient stop for gradient fills\nexport interface GradientStop {\n position: number;\n color: RGBAColor;\n}\n","// Single source of truth for Figma Plugin API pitfalls.\n//\n// Consumed in two places so the knowledge can never drift:\n// 1. Runtime — the plugin's execute_code handler matches raw Figma errors\n// against `pattern` and appends `hint`, so the AI self-corrects in one\n// round-trip.\n// 2. Build time — scripts/inject-pitfalls.ts renders `doc` bullets into the\n// figma-plugin-api cheat sheet, which ships as an MCP prompt.\n//\n// Adding a lesson learned = adding one entry here.\n\nexport interface Pitfall {\n /** RegExp source, matched case-insensitively against the raw error message. null = doc-only (silent pitfalls that never throw). */\n pattern: string | null;\n /** One-liner appended to the runtime error as \"Hint: …\". Empty for doc-only entries. */\n hint: string;\n /** Markdown bullet for the cheat sheet. */\n doc: string;\n}\n\nexport const PITFALLS: Pitfall[] = [\n {\n pattern: \"unloaded font\",\n hint: \"await figma.loadFontAsync(node.fontName) before editing text — new TextNodes default to Inter Regular; for mixed ranges load every font from getRangeAllFontNames().\",\n doc: \"**Editing text without loading its font throws** (`unloaded font`). `await figma.loadFontAsync(textNode.fontName)` first; new TextNodes default to Inter Regular; when `fontName === figma.mixed`, load every font from `getRangeAllFontNames()`.\",\n },\n {\n pattern: \"getNodeById\",\n hint: \"This plugin runs in dynamic-page mode — use await figma.getNodeByIdAsync(id) instead of getNodeById.\",\n doc: \"**`getNodeById` throws in dynamic-page mode** — always `await figma.getNodeByIdAsync(id)`.\",\n },\n {\n pattern: \"explicitly loaded\",\n hint: \"Non-current pages must be loaded before traversal: await page.loadAsync() before reading page.children or calling findAll.\",\n doc: \"**Traversing a non-current page throws until you `await page.loadAsync()`** — `figma.currentPage` is always loaded, other pages are not.\",\n },\n {\n pattern: \"layoutSizing\",\n hint: \"layoutSizing FILL/HUG needs auto-layout — on the parent for FILL, on the node itself for HUG. Set layoutMode on the frame first.\",\n doc: \"**`layoutSizingHorizontal/Vertical` throw without auto-layout** — FILL requires the parent to have a `layoutMode`, HUG requires it on the node itself.\",\n },\n {\n pattern: \"Starter plan\",\n hint: \"This file hit the free-plan page limit — reuse an existing page (find it via figma.root.children) instead of figma.createPage().\",\n doc: \"**`createPage()` throws on the free plan once a file has 3 pages** — reuse an existing page instead.\",\n },\n {\n pattern: \"read.?only property '(width|height)'\",\n hint: \"width/height are read-only — use node.resize(w, h) (and note resize on an auto-layout frame pins that axis to FIXED).\",\n doc: \"**`width`/`height` are read-only** — use `node.resize(w, h)`.\",\n },\n {\n pattern: \"symbol\",\n hint: \"You probably hit figma.mixed (a Symbol) — properties like fontSize/cornerRadius/fills return it when values differ across ranges or children. Compare with === figma.mixed before using the value.\",\n doc: \"**`figma.mixed` is a Symbol** returned by `fontSize`, `cornerRadius`, `fills` etc. when values differ across ranges/children — check `=== figma.mixed` before use; never JSON-serialize it.\",\n },\n {\n pattern: \"of undefined\",\n hint: \"A lookup returned undefined — if you searched pages or nodes by exact name, names may have been changed by the designer. Locate by type/content (e.g. c.type === \\\"COMPONENT_SET\\\") instead.\",\n doc: \"**Exact-name lookups are fragile** — designers rename pages and layers freely; locate nodes by type/content instead of `name ===`.\",\n },\n {\n pattern: \"does not exist\",\n hint: \"The node id is stale — the node was likely deleted or lives on another page. Re-read the document to get current ids.\",\n doc: \"**Stale node ids throw `does not exist`** — nodes get deleted while you work; re-read before editing and check `node.removed`.\",\n },\n {\n pattern: \"not extensible\",\n hint: \"Figma nodes can't hold custom properties (they're non-extensible). Stash data with node.setPluginData(key, value), or return it from the script.\",\n doc: \"**Nodes are non-extensible** — `node.myCustomProp = x` throws `object is not extensible`; use `setPluginData` or return the data instead.\",\n },\n // ── silent pitfalls: nothing throws, results are just wrong ──\n {\n pattern: null,\n hint: \"\",\n doc: \"**Shadow `spread` renders only on shapes or frames with `clipsContent: true`** — a focus ring built from spread shadows is invisible on a non-clipping frame/component.\",\n },\n {\n pattern: null,\n hint: \"\",\n doc: \"**`resize()` on an auto-layout frame silently pins that axis to FIXED**, overriding `primaryAxisSizingMode: \\\"AUTO\\\"`. Append children first, then set `layoutSizingHorizontal = \\\"HUG\\\"`; use `resize` only for the fixed cross-axis.\",\n },\n {\n pattern: null,\n hint: \"\",\n doc: \"**Per-corner radius** (`topLeftRadius` …) only exists on RectangleCornerMixin nodes (rectangles, frames, components) — polygons, stars and lines throw.\",\n },\n {\n pattern: null,\n hint: \"\",\n doc: \"**Instance children can't be added or removed** — detach first, or edit the main component.\",\n },\n {\n pattern: null,\n hint: \"\",\n doc: \"**Figma's slot feature (Convert to slot, ⇧⌘S) has no Plugin API** — no createSlot/convertToSlot exists (verified against typings 1.123 and at runtime, 2026-07). Scaffold a frame named \\\"Slot\\\", select it for the designer (navigate select), and let them press the shortcut.\",\n },\n {\n pattern: null,\n hint: \"\",\n doc: \"**A converted SLOT node stops hugging** — after the designer converts a frame to a slot it carries its own fixed size. Re-assert `layoutSizingVertical = \\\"HUG\\\"` (and the intended horizontal mode) on the SLOT node afterwards; the API can still edit its layout props.\",\n },\n {\n pattern: null,\n hint: \"\",\n doc: \"**Variantizing can silently pin the hug axis to FIXED** — observed after clone → counterAxisSizingMode/width-variable changes → combineAsVariants: the variants' `primaryAxisSizingMode` ended up FIXED though the source hugged. Always verify sizing modes on every variant after combineAsVariants and re-assert `\\\"AUTO\\\"`.\",\n },\n];\n\n// First matching pitfall's hint, or null. Doc-only entries never match.\nexport function pitfallHint(message: string): string | null {\n for (const p of PITFALLS) {\n if (p.pattern && new RegExp(p.pattern, \"i\").test(message)) return p.hint;\n }\n return null;\n}\n","import type { RGBAColor } from \"../types/commands.js\";\n\n// Convert RGBA (0-1 range) to hex string\nexport function rgbaToHex(color: RGBAColor): string {\n const r = Math.round(color.r * 255);\n const g = Math.round(color.g * 255);\n const b = Math.round(color.b * 255);\n const hex = `#${r.toString(16).padStart(2, \"0\")}${g.toString(16).padStart(2, \"0\")}${b.toString(16).padStart(2, \"0\")}`;\n if (color.a !== undefined && color.a < 1) {\n const a = Math.round(color.a * 255);\n return hex + a.toString(16).padStart(2, \"0\");\n }\n return hex;\n}\n\n// Convert hex string to RGBA (0-1 range)\nexport function hexToRgba(hex: string): RGBAColor {\n const clean = hex.replace(\"#\", \"\");\n const r = parseInt(clean.substring(0, 2), 16) / 255;\n const g = parseInt(clean.substring(2, 4), 16) / 255;\n const b = parseInt(clean.substring(4, 6), 16) / 255;\n const a = clean.length === 8 ? parseInt(clean.substring(6, 8), 16) / 255 : 1;\n return { r, g, b, a };\n}\n\n// ---- Perceptual color distance (OKLab, Björn Ottosson's matrices) ----\n// Used by the token-drift scan to decide whether a hardcoded color \"is\" an\n// existing variable. Distances are in OKLab units: identical ≈ 0, and\n// ~0.02 is at the edge of what most people can tell apart side by side.\n\nexport interface Oklab {\n L: number;\n a: number;\n b: number;\n}\n\nfunction srgbToLinear(c: number): number {\n return c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;\n}\n\nexport function rgbToOklab(color: { r: number; g: number; b: number }): Oklab {\n const lr = srgbToLinear(color.r);\n const lg = srgbToLinear(color.g);\n const lb = srgbToLinear(color.b);\n const l = Math.cbrt(0.4122214708 * lr + 0.5363325363 * lg + 0.0514459929 * lb);\n const m = Math.cbrt(0.2119034982 * lr + 0.6806995451 * lg + 0.1073969566 * lb);\n const s = Math.cbrt(0.0883024619 * lr + 0.2817188376 * lg + 0.6299787005 * lb);\n return {\n L: 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s,\n a: 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s,\n b: 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s,\n };\n}\n\nexport function deltaEOk(\n c1: { r: number; g: number; b: number },\n c2: { r: number; g: number; b: number }\n): number {\n const a = rgbToOklab(c1);\n const b = rgbToOklab(c2);\n return Math.hypot(a.L - b.L, a.a - b.a, a.b - b.b);\n}\n\nexport interface ColorCandidate {\n /** Variable (or style) identifier the caller wants back on a match */\n id: string;\n name: string;\n color: { r: number; g: number; b: number };\n}\n\n/** Closest candidate within tolerance, or null. Ties break toward the first. */\nexport function nearestColorMatch(\n target: { r: number; g: number; b: number },\n candidates: ColorCandidate[],\n tolerance: number\n): { candidate: ColorCandidate; deltaE: number } | null {\n let best: { candidate: ColorCandidate; deltaE: number } | null = null;\n for (const candidate of candidates) {\n const d = deltaEOk(target, candidate.color);\n if (d <= tolerance && (best === null || d < best.deltaE)) {\n best = { candidate, deltaE: d };\n }\n }\n return best;\n}\n","import { z } from \"zod\";\n\n// Shared Zod schemas used by MCP server tools\n\nexport const colorSchema = z.object({\n r: z.number().min(0).max(1).describe(\"Red channel (0-1)\"),\n g: z.number().min(0).max(1).describe(\"Green channel (0-1)\"),\n b: z.number().min(0).max(1).describe(\"Blue channel (0-1)\"),\n a: z.number().min(0).max(1).optional().describe(\"Alpha channel (0-1)\"),\n});\n\n// Node dimensions — Figma's resize() throws on zero or negative values\nexport const dimensionSchema = z.number().positive();\n\nexport const layoutModeSchema = z.enum([\"NONE\", \"HORIZONTAL\", \"VERTICAL\"]);\n\nexport const layoutWrapSchema = z.enum([\"NO_WRAP\", \"WRAP\"]);\n\nexport const primaryAxisAlignSchema = z.enum([\n \"MIN\",\n \"MAX\",\n \"CENTER\",\n \"SPACE_BETWEEN\",\n]);\n\nexport const counterAxisAlignSchema = z.enum([\n \"MIN\",\n \"MAX\",\n \"CENTER\",\n \"BASELINE\",\n]);\n\nexport const sizingModeSchema = z.enum([\"FIXED\", \"HUG\", \"FILL\"]);\n\nexport const exportFormatSchema = z.enum([\"PNG\", \"JPG\", \"SVG\", \"PDF\"]);\n\nexport const blendModeSchema = z.enum([\n \"PASS_THROUGH\",\n \"NORMAL\",\n \"DARKEN\",\n \"MULTIPLY\",\n \"LINEAR_BURN\",\n \"COLOR_BURN\",\n \"LIGHTEN\",\n \"SCREEN\",\n \"LINEAR_DODGE\",\n \"COLOR_DODGE\",\n \"OVERLAY\",\n \"SOFT_LIGHT\",\n \"HARD_LIGHT\",\n \"DIFFERENCE\",\n \"EXCLUSION\",\n \"HUE\",\n \"SATURATION\",\n \"COLOR\",\n \"LUMINOSITY\",\n]);\n\nexport const gradientTypeSchema = z.enum([\n \"GRADIENT_LINEAR\",\n \"GRADIENT_RADIAL\",\n \"GRADIENT_ANGULAR\",\n \"GRADIENT_DIAMOND\",\n]);\n\nexport const gradientStopSchema = z.object({\n position: z.number().min(0).max(1).describe(\"Stop position (0-1)\"),\n color: colorSchema,\n});\n\nexport const booleanOperationSchema = z.enum([\n \"UNION\",\n \"SUBTRACT\",\n \"INTERSECT\",\n \"EXCLUDE\",\n]);\n\nexport const constraintTypeSchema = z.enum([\n \"MIN\",\n \"CENTER\",\n \"MAX\",\n \"STRETCH\",\n \"SCALE\",\n]);\n\nexport const reorderDirectionSchema = z.enum([\n \"FRONT\",\n \"BACK\",\n \"FORWARD\",\n \"BACKWARD\",\n]);\n","// Transport-agnostic relay logic shared by the standalone Bun relay and the\n// relay embedded in the MCP server (Node/ws). The transport layer only needs\n// to call handleOpen/handleMessage/handleClose with a socket that can send().\n\nexport interface RelaySocket {\n send(data: string): void;\n close(): void;\n}\n\nexport type PeerRole = \"plugin\" | \"agent\" | \"unknown\";\n\nexport interface PeerInfo {\n role: PeerRole;\n meta?: Record<string, unknown>;\n}\n\nexport interface RoomSummary {\n room: string;\n hasPlugin: boolean;\n agentCount: number;\n /** File name reported by the plugin peer, when known */\n fileName?: string;\n}\n\nexport interface RelayCoreOptions {\n version?: string;\n log?: (message: string) => void;\n}\n\nexport class RelayCore<S extends RelaySocket = RelaySocket> {\n private rooms = new Map<string, Map<S, PeerInfo>>();\n private lastActivity = new Map<S, number>();\n private staleTimer: ReturnType<typeof setInterval> | null = null;\n private version: string;\n private log: (message: string) => void;\n\n constructor(options: RelayCoreOptions = {}) {\n this.version = options.version ?? \"unknown\";\n this.log = options.log ?? (() => {});\n }\n\n handleOpen(ws: S): void {\n this.lastActivity.set(ws, Date.now());\n this.send(ws, { type: \"system\", message: \"Please join a room to start\" });\n }\n\n handleMessage(ws: S, raw: string): void {\n this.lastActivity.set(ws, Date.now());\n\n let data: {\n type?: string;\n id?: string;\n room?: string;\n role?: string;\n meta?: Record<string, unknown>;\n message?: unknown;\n };\n try {\n data = JSON.parse(raw);\n } catch {\n this.send(ws, { type: \"error\", message: \"Invalid JSON\" });\n return;\n }\n\n switch (data.type) {\n case \"hello\":\n // Identity probe so clients can verify they reached a Relai relay\n this.send(ws, { type: \"hello\", server: \"figma-relai\", version: this.version });\n return;\n\n case \"join\": {\n const room = data.room;\n if (!room || typeof room !== \"string\") {\n this.send(ws, { type: \"error\", message: \"Room name required\" });\n return;\n }\n\n const role: PeerRole =\n data.role === \"plugin\" || data.role === \"agent\" ? data.role : \"unknown\";\n const peers = this.roomPeers(room);\n peers.set(ws, { role, meta: data.meta });\n this.log(`Client joined \"${room}\" as ${role} (${peers.size} clients)`);\n\n this.send(ws, { type: \"system\", message: `Joined room: ${room}`, room });\n // Response with the request id so the MCP server resolves its promise\n this.send(ws, {\n type: \"system\",\n message: { id: data.id, result: `Connected to room: ${room}` },\n room,\n });\n\n this.broadcastPresence(room);\n return;\n }\n\n case \"list_rooms\": {\n const rooms: RoomSummary[] = [];\n for (const [room, peers] of this.rooms) {\n if (peers.size === 0) continue;\n const pluginPeer = [...peers.values()].find((p) => p.role === \"plugin\");\n const fileName =\n typeof pluginPeer?.meta?.fileName === \"string\" ? pluginPeer.meta.fileName : undefined;\n rooms.push({\n room,\n hasPlugin: pluginPeer !== undefined,\n agentCount: [...peers.values()].filter((p) => p.role === \"agent\").length,\n ...(fileName ? { fileName } : {}),\n });\n }\n this.send(ws, { type: \"list_rooms_result\", id: data.id, rooms });\n return;\n }\n\n case \"message\": {\n const room = data.room;\n if (!room || typeof room !== \"string\") {\n this.send(ws, { type: \"error\", message: \"Room name required\" });\n return;\n }\n if (!this.rooms.get(room)?.has(ws)) {\n this.send(ws, { type: \"error\", message: \"Must join room first\" });\n return;\n }\n\n const payload = JSON.stringify({\n type: \"broadcast\",\n message: data.message,\n sender: \"peer\",\n room,\n });\n const count = this.broadcast(ws, room, payload);\n if (count === 0) this.log(`No peers in \"${room}\" to receive message`);\n return;\n }\n\n case \"progress_update\": {\n const room = data.room;\n if (room && typeof room === \"string\" && this.rooms.get(room)?.has(ws)) {\n this.broadcast(ws, room, raw);\n }\n return;\n }\n }\n }\n\n handleClose(ws: S): void {\n this.lastActivity.delete(ws);\n const affected: string[] = [];\n for (const [room, peers] of this.rooms) {\n if (peers.delete(ws)) affected.push(room);\n if (peers.size === 0) this.rooms.delete(room);\n }\n for (const room of affected) this.broadcastPresence(room);\n }\n\n // Periodically close connections with no activity (heartbeat)\n startStaleCleanup(staleTimeoutMs = 120000, checkIntervalMs = 30000): void {\n this.staleTimer = setInterval(() => {\n const now = Date.now();\n for (const [ws, lastTime] of this.lastActivity) {\n if (now - lastTime > staleTimeoutMs) {\n this.log(\"Closing stale connection\");\n try {\n ws.close();\n } catch {\n // Already closed\n }\n this.handleClose(ws);\n }\n }\n }, checkIntervalMs);\n }\n\n stop(): void {\n if (this.staleTimer) {\n clearInterval(this.staleTimer);\n this.staleTimer = null;\n }\n }\n\n private roomPeers(room: string): Map<S, PeerInfo> {\n let peers = this.rooms.get(room);\n if (!peers) {\n peers = new Map();\n this.rooms.set(room, peers);\n }\n return peers;\n }\n\n // Presence goes to every member (including the newcomer) so both the plugin\n // UI and the MCP server always know who is in the room\n private broadcastPresence(room: string): void {\n const peers = this.rooms.get(room);\n if (!peers) return;\n const payload = JSON.stringify({\n type: \"presence\",\n room,\n peers: [...peers.values()].map((p) => ({ role: p.role, meta: p.meta })),\n });\n for (const ws of peers.keys()) {\n try {\n ws.send(payload);\n } catch {\n // Ignore send failures; close handler will clean up\n }\n }\n }\n\n private broadcast(sender: S, room: string, payload: string): number {\n const peers = this.rooms.get(room);\n if (!peers) return 0;\n let count = 0;\n for (const ws of peers.keys()) {\n if (ws === sender) continue;\n try {\n ws.send(payload);\n count++;\n } catch {\n // Ignore send failures; close handler will clean up\n }\n }\n return count;\n }\n\n private send(ws: S, data: unknown): void {\n try {\n ws.send(JSON.stringify(data));\n } catch {\n // Ignore send failures\n }\n }\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { SendCommandFn } from \"../tool-registry.js\";\nimport { z } from \"zod\";\n\n// Consolidated core tools (~30). Each maps declarative input onto the plugin's\n// granular command vocabulary — the plugin side is unchanged, so the\n// precondition checks and structured errors keep working underneath.\nimport * as create from \"./core/create.js\";\nimport * as properties from \"./core/properties.js\";\nimport * as structure from \"./core/structure.js\";\nimport * as text from \"./core/text.js\";\nimport * as components from \"./core/components.js\";\nimport * as variables from \"./core/variables.js\";\nimport * as styles from \"./core/styles.js\";\nimport * as pages from \"./core/pages.js\";\nimport * as navigate from \"./core/navigate.js\";\nimport * as assets from \"./core/assets.js\";\nimport * as library from \"./core/library.js\";\nimport * as annotate from \"./core/annotate.js\";\nimport * as read from \"./core/read.js\";\nimport * as execute from \"./core/execute.js\";\nimport * as comments from \"./core/comments.js\";\nimport * as designSystem from \"./core/design-system.js\";\nimport * as batch from \"./batch.js\";\n\n// v2 semantic layer: context, analysis, verification\nimport * as v2Context from \"./v2/context.js\";\nimport * as v2Analysis from \"./v2/analysis.js\";\nimport * as v2Verification from \"./v2/verification.js\";\n\nconst moduleCategories: [ToolModuleLike, string][] = [\n [v2Context, \"context\"],\n [v2Analysis, \"analysis\"],\n [v2Verification, \"verification\"],\n [read, \"read\"],\n [create, \"create\"],\n [properties, \"edit\"],\n [structure, \"edit\"],\n [text, \"edit\"],\n [components, \"components\"],\n [variables, \"design-system\"],\n [styles, \"design-system\"],\n [library, \"design-system\"],\n [designSystem, \"design-system\"],\n [pages, \"document\"],\n [navigate, \"document\"],\n [assets, \"assets\"],\n [annotate, \"annotations\"],\n [comments, \"comments\"],\n [batch, \"advanced\"],\n [execute, \"advanced\"],\n];\n\ninterface ToolModuleLike {\n register(server: McpServer, sendCommand: SendCommandFn): void;\n}\n\n// Register the join_room tool separately since it uses joinRoom directly.\n// Pairing is automatic when exactly one plugin is connected; this tool exists\n// for disambiguation when several Figma files run the plugin at once.\nexport function registerRoomTool(\n server: McpServer,\n joinRoom: (room: string) => Promise<void>\n): void {\n server.tool(\n \"join_room\",\n \"Connect to a specific Figma plugin instance by room name. Usually unnecessary — pairing is automatic when one plugin is connected. Use only when an error reports multiple plugins/rooms; the room name is shown in each plugin's UI.\",\n {\n room: z.string().describe(\"Room name shown in the Figma plugin\"),\n },\n async ({ room }) => {\n try {\n if (!room) {\n return {\n content: [{ type: \"text\" as const, text: \"Please provide a room name.\" }],\n };\n }\n await joinRoom(room);\n return {\n content: [\n { type: \"text\" as const, text: `Successfully joined room: ${room}` },\n ],\n };\n } catch (error) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: `Error joining room: ${error instanceof Error ? error.message : String(error)}`,\n },\n ],\n };\n }\n }\n );\n}\n\n// Designer-activity polling tool; events also piggyback on command results\n// as a designer_events field. scope:\"agent\" returns this session's own\n// command log — an audit trail of what the AI actually did.\nexport function registerEventsTool(\n server: McpServer,\n consumeEvents: () => unknown[],\n getSessionLog: () => unknown[]\n): void {\n server.tool(\n \"get_events\",\n \"Activity since the last check. scope 'designer' (default): the designer's selection/node/page changes (also piggybacked as designer_events on command results). scope 'agent': this session's own command log — every plugin command sent, with success/duration — useful for summarizing what was changed. 'all': both.\",\n {\n scope: z.enum([\"designer\", \"agent\", \"all\"]).optional(),\n },\n { readOnlyHint: true },\n async ({ scope = \"designer\" }) => {\n const parts: Record<string, unknown> = {};\n if (scope === \"designer\" || scope === \"all\") {\n parts.designer_events = consumeEvents();\n }\n if (scope === \"agent\" || scope === \"all\") {\n parts.session_log = getSessionLog();\n }\n const empty = Object.values(parts).every((v) => Array.isArray(v) && v.length === 0);\n return {\n content: [\n {\n type: \"text\" as const,\n text: empty\n ? \"No activity recorded.\"\n : JSON.stringify(parts, null, 2),\n },\n ],\n };\n }\n );\n}\n\n// Register all tool modules\nexport function registerAllTools(\n server: McpServer,\n sendCommand: SendCommandFn\n): void {\n for (const [mod] of moduleCategories) {\n mod.register(server, sendCommand);\n }\n}\n\n// Build-time tool inventory for the plugin UI (node dist/index.js --list-tools)\nexport function listToolCatalog(): Array<{ name: string; category: string }> {\n const catalog: Array<{ name: string; category: string }> = [\n { name: \"join_room\", category: \"advanced\" },\n { name: \"get_events\", category: \"context\" },\n ];\n for (const [mod, category] of moduleCategories) {\n const collector = {\n tool: (name: string) => {\n catalog.push({ name, category });\n },\n } as unknown as McpServer;\n // Handlers never run; registration only records names\n mod.register(collector, async () => undefined);\n }\n return catalog;\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { SendCommandFn } from \"../../tool-registry.js\";\nimport { colorSchema, dimensionSchema, type FigmaCommand } from \"@figma-relai/shared\";\nimport { jsonResult, errorResult } from \"./helpers.js\";\n\nconst NODE_KINDS = [\n \"rectangle\",\n \"frame\",\n \"text\",\n \"ellipse\",\n \"polygon\",\n \"star\",\n \"line\",\n \"section\",\n \"slice\",\n \"svg\",\n \"image\",\n \"connector\",\n \"table\",\n \"sticky\",\n \"code_block\",\n] as const;\n\n// kind → plugin command\nconst KIND_COMMAND: Record<(typeof NODE_KINDS)[number], FigmaCommand> = {\n rectangle: \"create_rectangle\",\n frame: \"create_frame\",\n text: \"create_text\",\n ellipse: \"create_ellipse\",\n polygon: \"create_polygon\",\n star: \"create_star\",\n line: \"create_line\",\n section: \"create_section\",\n slice: \"create_slice\",\n svg: \"create_node_from_svg\",\n image: \"create_image_from_url\",\n connector: \"create_connector\",\n table: \"create_table\",\n sticky: \"create_sticky\",\n code_block: \"create_code_block\",\n};\n\nexport function register(server: McpServer, sendCommand: SendCommandFn): void {\n server.tool(\n \"create_node\",\n \"Create a node in Figma: rectangle, frame, text, ellipse, polygon, star, line, section, slice, svg (from markup), image (from URL), or FigJam connector/table/sticky/code_block. Returns the new node's id — style it further with set_properties. For component instances use manage_components.\",\n {\n type: z.enum(NODE_KINDS).describe(\"What to create\"),\n x: z.number().optional().describe(\"X position (default 0)\"),\n y: z.number().optional().describe(\"Y position (default 0)\"),\n width: dimensionSchema.optional(),\n height: dimensionSchema.optional(),\n name: z.string().optional(),\n parentId: z.string().optional().describe(\"Parent node id (default: current page)\"),\n text: z.string().optional().describe(\"Text content (text/sticky)\"),\n fontSize: z.number().positive().optional().describe(\"text only\"),\n fontWeight: z.number().optional().describe(\"text only (e.g. 400, 700)\"),\n fontColor: colorSchema.optional().describe(\"text only\"),\n fillColor: colorSchema.optional().describe(\"frame/rectangle fill\"),\n pointCount: z.number().int().min(3).optional().describe(\"polygon/star points\"),\n innerRadius: z.number().min(0).max(1).optional().describe(\"star inner radius ratio\"),\n length: z.number().positive().optional().describe(\"line length\"),\n rotation: z.number().optional().describe(\"line rotation in degrees\"),\n strokeWeight: z.number().min(0).optional().describe(\"line stroke weight\"),\n svg: z.string().optional().describe(\"SVG markup (type=svg)\"),\n url: z.string().optional().describe(\"Image URL (type=image)\"),\n scaleMode: z.enum([\"FILL\", \"FIT\", \"CROP\", \"TILE\"]).optional().describe(\"image only\"),\n rows: z.number().int().positive().optional().describe(\"table only\"),\n cols: z.number().int().positive().optional().describe(\"table only\"),\n startNodeId: z.string().optional().describe(\"connector only\"),\n endNodeId: z.string().optional().describe(\"connector only\"),\n lineType: z.enum([\"ELBOWED\", \"STRAIGHT\"]).optional().describe(\"connector only\"),\n },\n async ({ type, ...params }) => {\n try {\n const clean = Object.fromEntries(\n Object.entries(params).filter(([, v]) => v !== undefined)\n );\n const result = await sendCommand(KIND_COMMAND[type], clean);\n return jsonResult(result);\n } catch (error) {\n return errorResult(error);\n }\n }\n );\n}\n","// Shared helpers for the consolidated core tools\n\nexport function textResult(text: string) {\n return { content: [{ type: \"text\" as const, text }] };\n}\n\nexport function jsonResult(value: unknown) {\n return textResult(typeof value === \"string\" ? value : JSON.stringify(value, null, 2));\n}\n\nexport function errorResult(error: unknown) {\n return textResult(`Error: ${error instanceof Error ? error.message : String(error)}`);\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { SendCommandFn } from \"../../tool-registry.js\";\nimport {\n colorSchema,\n dimensionSchema,\n layoutModeSchema,\n layoutWrapSchema,\n primaryAxisAlignSchema,\n counterAxisAlignSchema,\n sizingModeSchema,\n blendModeSchema,\n gradientTypeSchema,\n gradientStopSchema,\n constraintTypeSchema,\n} from \"@figma-relai/shared\";\nimport type { FigmaCommand } from \"@figma-relai/shared\";\nimport { jsonResult, errorResult, textResult } from \"./helpers.js\";\n\n// One declarative properties object covering the write surface that used to\n// be ~55 granular set_*/add_* tools. Each field group maps to one plugin\n// command; multiple groups (or multiple nodes) fan out via batch_execute.\n\nconst effectSchema = z.object({\n type: z.enum([\"DROP_SHADOW\", \"INNER_SHADOW\", \"LAYER_BLUR\", \"BACKGROUND_BLUR\"]),\n color: colorSchema.optional().describe(\"Shadow color (shadows only)\"),\n offsetX: z.number().optional(),\n offsetY: z.number().optional(),\n radius: z.number().min(0).optional().describe(\"Blur radius\"),\n spread: z.number().optional(),\n});\n\nexport const propertiesSchema = z\n .object({\n // Geometry\n x: z.number().optional(),\n y: z.number().optional(),\n width: dimensionSchema.optional(),\n height: dimensionSchema.optional(),\n rotation: z.number().optional().describe(\"Degrees\"),\n // Identity / visibility\n name: z.string().optional(),\n visible: z.boolean().optional(),\n locked: z.boolean().optional(),\n opacity: z.number().min(0).max(1).optional(),\n blendMode: blendModeSchema.optional(),\n // Paint\n fillColor: colorSchema.optional(),\n fills: z\n .array(z.record(z.unknown()))\n .optional()\n .describe(\"Raw Paint[] — replaces the whole fill list; [] clears all fills\"),\n strokes: z\n .array(z.record(z.unknown()))\n .optional()\n .describe(\"Raw Paint[] — replaces the whole stroke list; [] clears all strokes\"),\n strokeColor: colorSchema.optional(),\n strokeWeight: z.number().min(0).optional(),\n cornerRadius: z.number().min(0).optional(),\n corners: z\n .array(z.boolean())\n .length(4)\n .optional()\n .describe(\"With cornerRadius: apply per corner [TL, TR, BR, BL]\"),\n gradient: z\n .object({ gradientType: gradientTypeSchema, stops: z.array(gradientStopSchema).min(2) })\n .optional(),\n // Effects (replaces existing effects list entry of same type)\n effects: z.array(effectSchema).optional(),\n removeEffects: z.boolean().optional(),\n // Text\n text: z.string().optional().describe(\"Text content (TEXT nodes)\"),\n // Auto-layout (frame itself)\n layoutMode: layoutModeSchema.optional(),\n layoutWrap: layoutWrapSchema.optional().describe(\"WRAP requires layoutMode HORIZONTAL\"),\n paddingTop: z.number().min(0).optional(),\n paddingRight: z.number().min(0).optional(),\n paddingBottom: z.number().min(0).optional(),\n paddingLeft: z.number().min(0).optional(),\n primaryAxisAlignItems: primaryAxisAlignSchema.optional(),\n counterAxisAlignItems: counterAxisAlignSchema.optional(),\n itemSpacing: z.number().optional(),\n counterAxisSpacing: z.number().optional(),\n // Auto-layout (as a child; FILL requires the PARENT to have auto-layout)\n layoutSizingHorizontal: sizingModeSchema.optional(),\n layoutSizingVertical: sizingModeSchema.optional(),\n // Constraints & sizing limits\n constraintsHorizontal: constraintTypeSchema.optional(),\n constraintsVertical: constraintTypeSchema.optional(),\n minWidth: z.number().min(0).optional(),\n maxWidth: z.number().min(0).optional(),\n minHeight: z.number().min(0).optional(),\n maxHeight: z.number().min(0).optional(),\n aspectRatioLocked: z.boolean().optional(),\n clipsContent: z.boolean().optional(),\n // Design-system bindings\n styleId: z.string().optional().describe(\"Apply a paint/text/effect/grid style by id\"),\n styleType: z.enum([\"PAINT\", \"TEXT\", \"EFFECT\", \"GRID\"]).optional(),\n boundVariables: z\n .record(z.string())\n .optional()\n .describe('Bind variables: {\"fills\": \"VariableID:...\", \"width\": \"...\"}'),\n })\n .strict();\n\nexport type NodeProperties = z.infer<typeof propertiesSchema>;\n\ninterface PluginCall {\n command: string;\n params: Record<string, unknown>;\n}\n\nfunction defined(obj: Record<string, unknown>): Record<string, unknown> {\n return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== undefined));\n}\n\n// Pure mapper: declarative properties → ordered plugin commands for one node.\n// Order matters: layoutMode must precede padding/align/sizing on fresh frames.\nexport function mapPropertiesToCommands(nodeId: string, p: NodeProperties): PluginCall[] {\n const calls: PluginCall[] = [];\n const add = (command: string, params: Record<string, unknown>) =>\n calls.push({ command, params: { nodeId, ...defined(params) } });\n\n if (p.name !== undefined) add(\"rename_node\", { name: p.name });\n if (p.visible !== undefined) add(\"set_visible\", { visible: p.visible });\n if (p.locked !== undefined) add(\"set_locked\", { locked: p.locked });\n\n if (p.x !== undefined || p.y !== undefined) add(\"move_node\", { x: p.x, y: p.y });\n if (p.width !== undefined || p.height !== undefined)\n add(\"resize_node\", { width: p.width, height: p.height });\n if (p.rotation !== undefined) add(\"set_rotation\", { rotation: p.rotation });\n\n if (p.layoutMode !== undefined)\n add(\"set_layout_mode\", { layoutMode: p.layoutMode, layoutWrap: p.layoutWrap });\n if (\n p.paddingTop !== undefined ||\n p.paddingRight !== undefined ||\n p.paddingBottom !== undefined ||\n p.paddingLeft !== undefined\n )\n add(\"set_padding\", {\n paddingTop: p.paddingTop,\n paddingRight: p.paddingRight,\n paddingBottom: p.paddingBottom,\n paddingLeft: p.paddingLeft,\n });\n if (p.primaryAxisAlignItems !== undefined || p.counterAxisAlignItems !== undefined)\n add(\"set_axis_align\", {\n primaryAxisAlignItems: p.primaryAxisAlignItems,\n counterAxisAlignItems: p.counterAxisAlignItems,\n });\n if (p.itemSpacing !== undefined || p.counterAxisSpacing !== undefined)\n add(\"set_item_spacing\", {\n itemSpacing: p.itemSpacing,\n counterAxisSpacing: p.counterAxisSpacing,\n });\n if (p.layoutSizingHorizontal !== undefined || p.layoutSizingVertical !== undefined)\n add(\"set_layout_sizing\", {\n layoutSizingHorizontal: p.layoutSizingHorizontal,\n layoutSizingVertical: p.layoutSizingVertical,\n });\n\n if (p.fills !== undefined || p.strokes !== undefined)\n add(\"set_fills\", {\n ...(p.fills !== undefined ? { fills: p.fills } : {}),\n ...(p.strokes !== undefined ? { strokes: p.strokes } : {}),\n });\n if (p.fillColor !== undefined) add(\"set_fill_color\", { color: p.fillColor });\n if (p.strokeColor !== undefined || p.strokeWeight !== undefined)\n add(\"set_stroke_color\", {\n color: p.strokeColor ?? { r: 0, g: 0, b: 0, a: 1 },\n weight: p.strokeWeight,\n });\n if (p.gradient !== undefined)\n add(\"set_gradient_fill\", { gradientType: p.gradient.gradientType, stops: p.gradient.stops });\n if (p.cornerRadius !== undefined)\n add(\"set_corner_radius\", { radius: p.cornerRadius, corners: p.corners });\n if (p.opacity !== undefined) add(\"set_opacity\", { opacity: p.opacity });\n if (p.blendMode !== undefined) add(\"set_blend_mode\", { blendMode: p.blendMode });\n\n if (p.removeEffects) add(\"remove_effects\", {});\n for (const effect of p.effects ?? []) {\n const common = {\n color: effect.color,\n offsetX: effect.offsetX,\n offsetY: effect.offsetY,\n radius: effect.radius,\n spread: effect.spread,\n };\n if (effect.type === \"DROP_SHADOW\") add(\"add_drop_shadow\", common);\n else if (effect.type === \"INNER_SHADOW\") add(\"add_inner_shadow\", common);\n else if (effect.type === \"LAYER_BLUR\") add(\"add_blur\", { radius: effect.radius });\n else add(\"add_background_blur\", { radius: effect.radius });\n }\n\n if (p.text !== undefined) add(\"set_text_content\", { text: p.text });\n\n if (p.constraintsHorizontal !== undefined || p.constraintsVertical !== undefined)\n add(\"set_constraints\", {\n horizontal: p.constraintsHorizontal,\n vertical: p.constraintsVertical,\n });\n if (\n p.minWidth !== undefined ||\n p.maxWidth !== undefined ||\n p.minHeight !== undefined ||\n p.maxHeight !== undefined\n )\n add(\"set_min_max_size\", {\n minWidth: p.minWidth,\n maxWidth: p.maxWidth,\n minHeight: p.minHeight,\n maxHeight: p.maxHeight,\n });\n if (p.aspectRatioLocked !== undefined) add(\"set_aspect_ratio\", { lock: p.aspectRatioLocked });\n if (p.clipsContent !== undefined) add(\"set_clips_content\", { clipsContent: p.clipsContent });\n\n if (p.styleId !== undefined)\n add(\"apply_style\", { styleId: p.styleId, styleType: p.styleType });\n for (const [property, variableId] of Object.entries(p.boundVariables ?? {})) {\n add(\"bind_variable\", { property, variableId });\n }\n\n return calls;\n}\n\nexport function register(server: McpServer, sendCommand: SendCommandFn): void {\n server.tool(\n \"set_properties\",\n \"Set any visual/layout/text properties on one or more nodes in a single call: geometry (x/y/width/height/rotation), fills/strokes/gradients/cornerRadius/opacity/effects, text content, auto-layout (layoutMode, padding, alignment, spacing, layoutSizing — FILL requires the parent to have auto-layout), constraints, style application, and variable bindings. Groups map to focused operations with per-operation success/error reporting. dryRun:true previews the mapped command list without touching the canvas.\",\n {\n nodeIds: z.array(z.string()).min(1).describe(\"Node IDs to update\"),\n properties: propertiesSchema.describe(\"Properties to apply to every listed node\"),\n dryRun: z.boolean().optional().describe(\"Preview only — return the plan, execute nothing\"),\n },\n { idempotentHint: true },\n async ({ nodeIds, properties, dryRun }) => {\n try {\n const commands = nodeIds.flatMap((nodeId) =>\n mapPropertiesToCommands(nodeId, properties)\n );\n if (commands.length === 0) return textResult(\"No properties given — nothing to do.\");\n if (dryRun) {\n return jsonResult({\n dryRun: true,\n commandCount: commands.length,\n commands,\n note: \"Nothing was executed. Re-run without dryRun to apply.\",\n });\n }\n\n if (commands.length === 1) {\n const result = await sendCommand(commands[0].command as FigmaCommand, commands[0].params);\n return jsonResult(result);\n }\n const results = await sendCommand(\n \"batch_execute\",\n { commands },\n Math.max(30000, commands.length * 5000)\n );\n return jsonResult(results);\n } catch (error) {\n return errorResult(error);\n }\n }\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { SendCommandFn } from \"../../tool-registry.js\";\nimport { booleanOperationSchema, reorderDirectionSchema } from \"@figma-relai/shared\";\nimport { jsonResult, errorResult } from \"./helpers.js\";\n\nexport function register(server: McpServer, sendCommand: SendCommandFn): void {\n server.tool(\n \"edit_structure\",\n \"Structural operations on nodes: group/ungroup, reparent (move into another parent), reorder (z-order), clone, flatten to vector, boolean operations (union/subtract/intersect/exclude), delete. group/boolean/delete take nodeIds; the rest take nodeId.\",\n {\n operation: z.enum([\n \"group\",\n \"ungroup\",\n \"reparent\",\n \"reorder\",\n \"clone\",\n \"flatten\",\n \"boolean\",\n \"delete\",\n ]),\n nodeId: z.string().optional().describe(\"Target node (ungroup/reparent/reorder/clone/flatten)\"),\n nodeIds: z.array(z.string()).optional().describe(\"Target nodes (group/boolean/delete)\"),\n parentId: z.string().optional().describe(\"reparent: new parent\"),\n index: z.number().int().min(0).optional().describe(\"reparent: insertion index\"),\n direction: reorderDirectionSchema.optional().describe(\"reorder direction\"),\n booleanOperation: booleanOperationSchema.optional().describe(\"boolean: which operation\"),\n x: z.number().optional().describe(\"clone: position of the copy\"),\n y: z.number().optional(),\n },\n async ({ operation, nodeId, nodeIds, parentId, index, direction, booleanOperation, x, y }) => {\n try {\n const need = (value: unknown, what: string) => {\n if (value === undefined) throw new Error(`\"${operation}\" requires ${what}`);\n };\n let result: unknown;\n switch (operation) {\n case \"group\":\n need(nodeIds, \"nodeIds\");\n result = await sendCommand(\"group_nodes\", { nodeIds });\n break;\n case \"ungroup\":\n need(nodeId, \"nodeId\");\n result = await sendCommand(\"ungroup_nodes\", { nodeId });\n break;\n case \"reparent\":\n need(nodeId, \"nodeId\");\n need(parentId, \"parentId\");\n result = await sendCommand(\"reparent_node\", { nodeId, parentId, index });\n break;\n case \"reorder\":\n need(nodeId, \"nodeId\");\n need(direction, \"direction\");\n result = await sendCommand(\"reorder_node\", { nodeId, direction });\n break;\n case \"clone\":\n need(nodeId, \"nodeId\");\n result = await sendCommand(\"clone_node\", { nodeId, x, y });\n break;\n case \"flatten\":\n need(nodeId, \"nodeId\");\n result = await sendCommand(\"flatten_node\", { nodeId });\n break;\n case \"boolean\":\n need(nodeIds, \"nodeIds\");\n need(booleanOperation, \"booleanOperation\");\n result = await sendCommand(\"boolean_operation\", {\n nodeIds,\n operation: booleanOperation,\n });\n break;\n case \"delete\":\n if (nodeIds) result = await sendCommand(\"delete_multiple_nodes\", { nodeIds });\n else {\n need(nodeId, \"nodeId or nodeIds\");\n result = await sendCommand(\"delete_node\", { nodeId });\n }\n break;\n }\n return jsonResult(result);\n } catch (error) {\n return errorResult(error);\n }\n }\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { SendCommandFn } from \"../../tool-registry.js\";\nimport { jsonResult, errorResult, textResult } from \"./helpers.js\";\n\nexport function register(server: McpServer, sendCommand: SendCommandFn): void {\n server.tool(\n \"set_text\",\n \"Edit text nodes. Modes: single (nodeId + text), bulk (items — efficient for many nodes, e.g. translations), or character-range styling (nodeId + range with fontSize/fontWeight/letterSpacing/lineHeight). Fonts load automatically with fallbacks. To find text nodes first, use search_nodes or get_selection_context.\",\n {\n nodeId: z.string().optional().describe(\"Target text node (single / range mode)\"),\n text: z.string().optional().describe(\"New content (single mode)\"),\n items: z\n .array(z.object({ nodeId: z.string(), text: z.string() }))\n .optional()\n .describe(\"Bulk replacements\"),\n range: z\n .object({\n start: z.number().int().min(0),\n end: z.number().int().positive(),\n fontSize: z.number().positive().optional(),\n fontWeight: z.number().optional(),\n letterSpacing: z.number().optional(),\n lineHeight: z.number().optional(),\n })\n .refine((r) => r.end > r.start, { message: \"end must be greater than start\" })\n .optional()\n .describe(\"Style a character range [start, end)\"),\n },\n async ({ nodeId, text, items, range }) => {\n try {\n if (items?.length) {\n const result = await sendCommand(\n \"set_multiple_text_contents\",\n { text: items },\n Math.max(30000, items.length * 2000)\n );\n return jsonResult(result);\n }\n if (nodeId && range) {\n const result = await sendCommand(\"set_text_style_range\", { nodeId, ...range });\n return jsonResult(result);\n }\n if (nodeId && text !== undefined) {\n const result = await sendCommand(\"set_text_content\", { nodeId, text });\n return jsonResult(result);\n }\n return textResult(\n \"Provide either items (bulk), nodeId + text (single), or nodeId + range (styling).\"\n );\n } catch (error) {\n return errorResult(error);\n }\n }\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { SendCommandFn } from \"../../tool-registry.js\";\nimport { jsonResult, errorResult } from \"./helpers.js\";\n\nexport function register(server: McpServer, sendCommand: SendCommandFn): void {\n server.tool(\n \"manage_components\",\n \"Component workflow: list local components, create a component from a node, create_set (combine components as variants), instantiate (place an instance by componentKey — imports from the team library if needed), get_props / set_props (component properties on an instance), get_overrides / set_overrides (copy overrides from a source instance to targets), reset_instance (clear ALL overrides so the instance re-inherits its main component — returns property snapshots before/after so you can re-apply what mattered), detach.\",\n {\n action: z.enum([\n \"list\",\n \"create\",\n \"create_set\",\n \"instantiate\",\n \"get_props\",\n \"set_props\",\n \"get_overrides\",\n \"set_overrides\",\n \"reset_instance\",\n \"detach\",\n ]),\n nodeId: z.string().optional().describe(\"Target node (create/get_props/set_props/reset_instance/detach)\"),\n componentIds: z.array(z.string()).optional().describe(\"create_set: components to combine\"),\n componentKey: z.string().optional().describe(\"instantiate: component key (or node id)\"),\n x: z.number().optional().describe(\"instantiate: position\"),\n y: z.number().optional(),\n properties: z\n .record(z.union([z.string(), z.boolean()]))\n .optional()\n .describe(\"set_props: property name → value (variant/text/boolean/swap)\"),\n sourceInstanceId: z.string().optional().describe(\"set_overrides: copy from this instance\"),\n targetNodeIds: z.array(z.string()).optional().describe(\"set_overrides: apply to these\"),\n instanceNodeId: z.string().optional().describe(\"get_overrides: instance to inspect\"),\n },\n async (args) => {\n try {\n let result: unknown;\n switch (args.action) {\n case \"list\":\n result = await sendCommand(\"get_local_components\", {}, 60000);\n break;\n case \"create\":\n result = await sendCommand(\"create_component_from_node\", { nodeId: args.nodeId });\n break;\n case \"create_set\":\n result = await sendCommand(\"create_component_set\", { componentIds: args.componentIds });\n break;\n case \"instantiate\":\n result = await sendCommand(\"create_component_instance\", {\n componentKey: args.componentKey,\n x: args.x,\n y: args.y,\n });\n break;\n case \"get_props\":\n result = await sendCommand(\"get_component_properties\", { nodeId: args.nodeId });\n break;\n case \"set_props\":\n result = await sendCommand(\"set_component_properties\", {\n nodeId: args.nodeId,\n properties: args.properties,\n });\n break;\n case \"get_overrides\":\n result = await sendCommand(\"get_instance_overrides\", {\n instanceNodeId: args.instanceNodeId ?? args.nodeId,\n });\n break;\n case \"set_overrides\":\n result = await sendCommand(\"set_instance_overrides\", {\n sourceInstanceId: args.sourceInstanceId,\n targetNodeIds: args.targetNodeIds,\n });\n break;\n case \"reset_instance\":\n result = await sendCommand(\"reset_instance\", { nodeId: args.nodeId });\n break;\n case \"detach\":\n result = await sendCommand(\"detach_instance\", { nodeId: args.nodeId });\n break;\n }\n return jsonResult(result);\n } catch (error) {\n return errorResult(error);\n }\n }\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { SendCommandFn } from \"../../tool-registry.js\";\nimport type { FigmaCommand } from \"@figma-relai/shared\";\nimport { jsonResult, errorResult } from \"./helpers.js\";\n\n// action → [plugin command, params to forward]\nconst ACTIONS: Record<string, [string, string[]]> = {\n list_collections: [\"get_variable_collections\", []],\n list: [\"get_variables\", [\"collectionId\"]],\n create_collection: [\"create_variable_collection\", [\"name\", \"modes\"]],\n update_collection: [\"update_variable_collection\", [\"collectionId\", \"name\", \"hiddenFromPublishing\"]],\n delete_collection: [\"delete_variable_collection\", [\"collectionId\"]],\n create: [\"create_variable\", [\"collectionId\", \"name\", \"resolvedType\", \"value\"]],\n update: [\"update_variable\", [\"variableId\", \"modeId\", \"value\", \"name\", \"description\", \"hiddenFromPublishing\"]],\n delete: [\"delete_variable\", [\"variableId\"]],\n add_mode: [\"add_mode\", [\"collectionId\", \"name\"]],\n remove_mode: [\"remove_mode\", [\"collectionId\", \"modeId\"]],\n rename_mode: [\"rename_mode\", [\"collectionId\", \"modeId\", \"name\"]],\n set_scopes: [\"set_variable_scopes\", [\"variableId\", \"scopes\"]],\n set_code_syntax: [\"set_variable_code_syntax\", [\"variableId\", \"platform\", \"value\"]],\n remove_code_syntax: [\"remove_variable_code_syntax\", [\"variableId\", \"platform\"]],\n create_alias: [\"create_variable_alias\", [\"variableId\", \"targetVariableId\", \"modeId\"]],\n bind: [\"bind_variable\", [\"nodeId\", \"variableId\", \"property\"]],\n unbind: [\"unbind_variable\", [\"nodeId\", \"property\"]],\n set_node_mode: [\"set_node_variable_mode\", [\"nodeId\", \"collectionId\", \"modeId\"]],\n get_node_modes: [\"get_resolved_variable_modes\", [\"nodeId\"]],\n tokenize: [\"scan_token_drift\", [\"nodeId\", \"fix\", \"tolerance\"]],\n};\n\nexport function register(server: McpServer, sendCommand: SendCommandFn): void {\n server.tool(\n \"manage_variables\",\n \"Design-token variables: list_collections / list (variables in a collection) / create_collection / update_collection / delete_collection / create / update / delete / add_mode / remove_mode / rename_mode / set_scopes / set_code_syntax / remove_code_syntax / create_alias / bind (variable→node property) / unbind / set_node_mode / get_node_modes / tokenize (find hardcoded colors & numbers that match existing variables and bind them — fix:false to preview, fix:true to apply; scope with nodeId, default current page). Pass only the fields the action needs.\",\n {\n action: z.enum(Object.keys(ACTIONS) as [string, ...string[]]),\n collectionId: z.string().optional(),\n variableId: z.string().optional(),\n targetVariableId: z.string().optional().describe(\"create_alias: variable to alias to\"),\n nodeId: z.string().optional().describe(\"bind/unbind/set_node_mode/get_node_modes\"),\n name: z.string().optional(),\n description: z.string().optional(),\n modes: z.array(z.string()).optional().describe(\"create_collection: mode names\"),\n modeId: z.string().optional(),\n resolvedType: z.enum([\"COLOR\", \"FLOAT\", \"STRING\", \"BOOLEAN\"]).optional(),\n value: z.unknown().optional().describe(\"Variable value (color object, number, string, bool)\"),\n property: z.string().optional().describe('bind/unbind: node property (e.g. \"fills\", \"width\")'),\n scopes: z.array(z.string()).optional(),\n platform: z.enum([\"WEB\", \"ANDROID\", \"iOS\"]).optional(),\n hiddenFromPublishing: z.boolean().optional(),\n fix: z.boolean().optional().describe(\"tokenize: apply the bindings (false = report only)\"),\n tolerance: z\n .number()\n .optional()\n .describe(\"tokenize: OKLab ΔE for color matches (default 0.02 ≈ visually identical)\"),\n },\n async (args) => {\n try {\n const [command, fields] = ACTIONS[args.action as string];\n const params = Object.fromEntries(\n fields\n .map((f) => [f, (args as Record<string, unknown>)[f]])\n .filter(([, v]) => v !== undefined)\n );\n // Drift scans walk whole subtrees; give them scan-scale time\n const result = await sendCommand(\n command as FigmaCommand,\n params,\n args.action === \"tokenize\" ? 120000 : undefined\n );\n return jsonResult(result);\n } catch (error) {\n return errorResult(error);\n }\n }\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { SendCommandFn } from \"../../tool-registry.js\";\nimport { colorSchema, gradientTypeSchema, gradientStopSchema } from \"@figma-relai/shared\";\nimport { jsonResult, errorResult } from \"./helpers.js\";\n\nexport function register(server: McpServer, sendCommand: SendCommandFn): void {\n server.tool(\n \"manage_styles\",\n \"Shared styles: list all local styles; create_paint / create_text / create_effect / create_grid; update (name/properties); delete; apply (style to a node); reorder. To bind variables instead of styles, use manage_variables.\",\n {\n action: z.enum([\n \"list\",\n \"create_paint\",\n \"create_text\",\n \"create_effect\",\n \"create_grid\",\n \"update\",\n \"delete\",\n \"apply\",\n \"reorder\",\n ]),\n name: z.string().optional().describe(\"Style name (create_*/update)\"),\n styleId: z.string().optional().describe(\"Target style (update/delete/apply/reorder)\"),\n styleType: z.enum([\"PAINT\", \"TEXT\", \"EFFECT\", \"GRID\"]).optional().describe(\"apply/reorder\"),\n nodeId: z.string().optional().describe(\"apply: target node\"),\n color: colorSchema.optional().describe(\"create_paint/create_effect\"),\n gradientType: gradientTypeSchema.optional(),\n gradientStops: z.array(gradientStopSchema).optional(),\n fontFamily: z.string().optional().describe(\"create_text\"),\n fontSize: z.number().positive().optional(),\n fontWeight: z.number().optional(),\n lineHeight: z.number().optional(),\n letterSpacing: z.number().optional(),\n effectType: z\n .enum([\"DROP_SHADOW\", \"INNER_SHADOW\", \"LAYER_BLUR\", \"BACKGROUND_BLUR\"])\n .optional()\n .describe(\"create_effect\"),\n offsetX: z.number().optional(),\n offsetY: z.number().optional(),\n radius: z.number().min(0).optional(),\n spread: z.number().optional(),\n grids: z.array(z.record(z.unknown())).optional().describe(\"create_grid: layout grid objects\"),\n properties: z.record(z.unknown()).optional().describe(\"update: properties to change\"),\n afterStyleId: z.string().optional().describe(\"reorder: place after this style\"),\n },\n async (args) => {\n try {\n let result: unknown;\n switch (args.action) {\n case \"list\":\n result = await sendCommand(\"get_styles\", {});\n break;\n case \"create_paint\":\n result = await sendCommand(\"create_paint_style\", {\n name: args.name,\n color: args.color,\n gradientType: args.gradientType,\n gradientStops: args.gradientStops,\n });\n break;\n case \"create_text\":\n result = await sendCommand(\"create_text_style\", {\n name: args.name,\n fontFamily: args.fontFamily,\n fontSize: args.fontSize,\n fontWeight: args.fontWeight,\n lineHeight: args.lineHeight,\n letterSpacing: args.letterSpacing,\n });\n break;\n case \"create_effect\":\n result = await sendCommand(\"create_effect_style\", {\n name: args.name,\n effectType: args.effectType,\n color: args.color,\n offsetX: args.offsetX,\n offsetY: args.offsetY,\n radius: args.radius,\n spread: args.spread,\n });\n break;\n case \"create_grid\":\n result = await sendCommand(\"create_grid_style\", { name: args.name, grids: args.grids });\n break;\n case \"update\":\n result = await sendCommand(\"update_style\", {\n styleId: args.styleId,\n name: args.name,\n properties: args.properties,\n });\n break;\n case \"delete\":\n result = await sendCommand(\"delete_style\", { styleId: args.styleId });\n break;\n case \"apply\":\n result = await sendCommand(\"apply_style\", {\n nodeId: args.nodeId,\n styleId: args.styleId,\n styleType: args.styleType,\n });\n break;\n case \"reorder\":\n result = await sendCommand(\"reorder_style\", {\n styleId: args.styleId,\n afterStyleId: args.afterStyleId,\n styleType: args.styleType,\n });\n break;\n }\n return jsonResult(result);\n } catch (error) {\n return errorResult(error);\n }\n }\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { SendCommandFn } from \"../../tool-registry.js\";\nimport { colorSchema } from \"@figma-relai/shared\";\nimport { jsonResult, errorResult } from \"./helpers.js\";\n\nexport function register(server: McpServer, sendCommand: SendCommandFn): void {\n server.tool(\n \"manage_pages\",\n \"Page operations: list all pages, create/rename/delete a page, or set a page's background color. To make a page current, use navigate with switch_page.\",\n {\n action: z.enum([\"list\", \"create\", \"rename\", \"delete\", \"set_background\"]),\n pageId: z.string().optional().describe(\"Target page (rename/delete/set_background)\"),\n name: z.string().optional().describe(\"Page name (create/rename)\"),\n color: colorSchema.optional().describe(\"Background color (set_background)\"),\n },\n async ({ action, pageId, name, color }) => {\n try {\n let result: unknown;\n switch (action) {\n case \"list\":\n result = await sendCommand(\"get_pages\", {});\n break;\n case \"create\":\n result = await sendCommand(\"create_page\", { name });\n break;\n case \"rename\":\n result = await sendCommand(\"rename_page\", { pageId, name });\n break;\n case \"delete\":\n result = await sendCommand(\"delete_page\", { pageId });\n break;\n case \"set_background\":\n result = await sendCommand(\"set_page_background\", { pageId, color });\n break;\n }\n return jsonResult(result);\n } catch (error) {\n return errorResult(error);\n }\n }\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { SendCommandFn } from \"../../tool-registry.js\";\nimport { jsonResult, errorResult } from \"./helpers.js\";\n\nexport function register(server: McpServer, sendCommand: SendCommandFn): void {\n server.tool(\n \"navigate\",\n \"Control the designer's view: focus (scroll+zoom to a node), select (set the selection), get_viewport / set_viewport (x/y/zoom), or switch_page.\",\n {\n action: z.enum([\"focus\", \"select\", \"get_viewport\", \"set_viewport\", \"switch_page\"]),\n nodeId: z.string().optional().describe(\"focus target\"),\n nodeIds: z.array(z.string()).optional().describe(\"select targets\"),\n x: z.number().optional().describe(\"set_viewport center x\"),\n y: z.number().optional(),\n zoom: z.number().positive().optional(),\n pageId: z.string().optional().describe(\"switch_page target\"),\n },\n async ({ action, nodeId, nodeIds, x, y, zoom, pageId }) => {\n try {\n let result: unknown;\n switch (action) {\n case \"focus\":\n result = await sendCommand(\"set_focus\", { nodeId });\n break;\n case \"select\":\n result = await sendCommand(\"set_selections\", { nodeIds });\n break;\n case \"get_viewport\":\n result = await sendCommand(\"get_viewport\", {});\n break;\n case \"set_viewport\":\n result = await sendCommand(\"set_viewport\", { x, y, zoom });\n break;\n case \"switch_page\":\n result = await sendCommand(\"switch_page\", { pageId });\n break;\n }\n return jsonResult(result);\n } catch (error) {\n return errorResult(error);\n }\n }\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { SendCommandFn } from \"../../tool-registry.js\";\nimport { exportFormatSchema } from \"@figma-relai/shared\";\nimport { jsonResult, errorResult, textResult } from \"./helpers.js\";\n\nexport function register(server: McpServer, sendCommand: SendCommandFn): void {\n server.tool(\n \"export_asset\",\n \"Export a node as PNG/JPG/SVG/PDF. Returns base64 data for saving to disk. For a quick visual check of your work, prefer the screenshot tool (returns a viewable image).\",\n {\n nodeId: z.string().describe(\"Node to export\"),\n format: exportFormatSchema.optional().describe(\"Default PNG\"),\n scale: z.number().positive().optional().describe(\"Export scale (default 1)\"),\n },\n { readOnlyHint: true },\n async ({ nodeId, format, scale }) => {\n try {\n const result = await sendCommand(\"export_node_as_image\", { nodeId, format, scale }, 60000);\n return jsonResult(result);\n } catch (error) {\n return errorResult(error);\n }\n }\n );\n\n server.tool(\n \"add_image\",\n \"Place an image: from a URL (creates a new image node) or as a fill on an existing node (base64 imageData). scaleMode controls how the image fits.\",\n {\n url: z.string().optional().describe(\"Image URL — creates a new node\"),\n nodeId: z.string().optional().describe(\"Existing node — sets its fill from imageData\"),\n imageData: z.string().optional().describe(\"Base64 image data (with nodeId)\"),\n x: z.number().optional(),\n y: z.number().optional(),\n width: z.number().positive().optional(),\n height: z.number().positive().optional(),\n name: z.string().optional(),\n scaleMode: z.enum([\"FILL\", \"FIT\", \"CROP\", \"TILE\"]).optional(),\n },\n async ({ url, nodeId, imageData, x, y, width, height, name, scaleMode }) => {\n try {\n if (url) {\n const result = await sendCommand(\n \"create_image_from_url\",\n { url, x, y, width, height, name, scaleMode },\n 60000\n );\n return jsonResult(result);\n }\n if (nodeId && imageData) {\n const result = await sendCommand(\"set_image_fill\", { nodeId, imageData, scaleMode }, 60000);\n return jsonResult(result);\n }\n return textResult(\"Provide either url (new image node) or nodeId + imageData (image fill).\");\n } catch (error) {\n return errorResult(error);\n }\n }\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { SendCommandFn } from \"../../tool-registry.js\";\nimport { jsonResult, errorResult } from \"./helpers.js\";\n\nexport function register(server: McpServer, sendCommand: SendCommandFn): void {\n server.tool(\n \"import_from_library\",\n \"Import a component, style, or variable from an enabled team library by its key. Component keys come from the design system or get_local_components; imported components can then be instantiated with manage_components.\",\n {\n kind: z.enum([\"component\", \"style\", \"variable\"]),\n key: z.string().describe(\"Library key\"),\n },\n async ({ kind, key }) => {\n try {\n const command =\n kind === \"component\"\n ? \"import_component_by_key\"\n : kind === \"style\"\n ? \"import_style_by_key\"\n : \"import_variable_by_key\";\n const result = await sendCommand(command, { key }, 60000);\n return jsonResult(result);\n } catch (error) {\n return errorResult(error);\n }\n }\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { SendCommandFn } from \"../../tool-registry.js\";\nimport { jsonResult, errorResult, textResult } from \"./helpers.js\";\n\nexport function register(server: McpServer, sendCommand: SendCommandFn): void {\n server.tool(\n \"annotate\",\n \"Read or write Dev Mode annotations. get: read annotations on a node. set: add/update one annotation (labelMarkdown). set_multiple: batch annotations.\",\n {\n action: z.enum([\"get\", \"set\", \"set_multiple\"]),\n nodeId: z.string().optional().describe(\"Target node (get/set)\"),\n labelMarkdown: z.string().optional().describe(\"Annotation text (set)\"),\n categoryId: z.string().optional(),\n annotations: z\n .array(\n z.object({\n nodeId: z.string(),\n labelMarkdown: z.string(),\n categoryId: z.string().optional(),\n })\n )\n .optional()\n .describe(\"Batch annotations (set_multiple)\"),\n },\n async ({ action, nodeId, labelMarkdown, categoryId, annotations }) => {\n try {\n if (action === \"get\") {\n const result = await sendCommand(\"get_annotations\", { nodeId });\n return jsonResult(result);\n }\n if (action === \"set\") {\n if (!nodeId || labelMarkdown === undefined)\n return textResult(\"set requires nodeId and labelMarkdown.\");\n const result = await sendCommand(\"set_annotation\", { nodeId, labelMarkdown, categoryId });\n return jsonResult(result);\n }\n if (!annotations?.length) return textResult(\"set_multiple requires annotations.\");\n const result = await sendCommand(\"set_multiple_annotations\", { annotations });\n return jsonResult(result);\n } catch (error) {\n return errorResult(error);\n }\n }\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { SendCommandFn } from \"../../tool-registry.js\";\nimport { jsonResult, errorResult } from \"./helpers.js\";\n\nexport function register(server: McpServer, sendCommand: SendCommandFn): void {\n server.tool(\n \"get_node_data\",\n \"Raw node data at a chosen detail level: summary (shallow), tree (sparse structure for orientation), full (deeper serialization), css (CSS representation), variables (bound variable ids). For human-oriented summaries prefer get_node_details / get_selection_context.\",\n {\n nodeIds: z.array(z.string()).min(1).describe(\"One or more node ids\"),\n detail: z.enum([\"summary\", \"tree\", \"full\", \"css\", \"variables\"]).optional()\n .describe(\"Default summary\"),\n depth: z.number().int().min(0).optional().describe(\"Override serialization depth\"),\n maxNodes: z.number().int().positive().optional().describe(\"Override node budget\"),\n },\n { readOnlyHint: true },\n async ({ nodeIds, detail = \"summary\", depth, maxNodes }) => {\n try {\n if (detail === \"css\" || detail === \"variables\") {\n const command = detail === \"css\" ? \"get_css\" : \"get_bound_variables\";\n const results = [];\n for (const nodeId of nodeIds) {\n results.push({ nodeId, data: await sendCommand(command, { nodeId }) });\n }\n return jsonResult(nodeIds.length === 1 ? results[0].data : results);\n }\n if (detail === \"tree\") {\n const results = [];\n for (const nodeId of nodeIds) {\n results.push(await sendCommand(\"get_node_tree\", { nodeId, depth, maxNodes }));\n }\n return jsonResult(nodeIds.length === 1 ? results[0] : results);\n }\n if (nodeIds.length > 1) {\n const result = await sendCommand(\"get_nodes_info\", { nodeIds });\n return jsonResult(result);\n }\n const result = await sendCommand(\"get_node_info\", {\n nodeId: nodeIds[0],\n depth: depth ?? (detail === \"full\" ? 4 : 1),\n maxNodes,\n });\n return jsonResult(result);\n } catch (error) {\n return errorResult(error);\n }\n }\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { SendCommandFn } from \"../../tool-registry.js\";\nimport { jsonResult, errorResult } from \"./helpers.js\";\n\nexport function register(server: McpServer, sendCommand: SendCommandFn): void {\n server.tool(\n \"execute_figma\",\n \"Run JavaScript against the Figma Plugin API inside the plugin sandbox — the escape hatch for anything the other tools don't cover. The code runs in an async function with `figma` AND `relai` in scope. relai helpers avoid the classic pitfalls: relai.text(parent, chars, {font,size,color}) loads fonts first; relai.autoLayout(direction, props) makes a hugging auto-layout frame; relai.set(node, props) applies layoutMode first and routes width/height through resize; relai.hug(node); relai.focusRing(node); await relai.page(p => ...) finds pages by content, not name; relai.query('FRAME[name^=Card] > TEXT') is a CSS-like search (types, name matchers, descendant/child, comma); relai.placeholder(node) shows a construction veil — remove with (node, false) when done. Errors carry a Hint with the fix; scripts are NOT atomic — on error, partial changes persist, so keep scripts small and idempotent. Nodes created via relai plus any node ids you RETURN are linted for silent mistakes (e.g. spread shadows without clipsContent) and come back as `warnings`. Return ALL created/mutated node ids. Work incrementally; verify with screenshot. When BUILDING UI: call get_design_system first and instantiate the file's own components / bind its variables instead of drawing raw shapes — hand-drawn near-copies of existing components read as drift to the design team. The designer can disable this tool via the plugin's 'Allow code execution' toggle.\",\n {\n code: z.string().describe(\"JavaScript source. May use await. Return a JSON-serializable value.\"),\n description: z\n .string()\n .optional()\n .describe(\"One line shown in the plugin's activity feed describing what this does\"),\n timeoutMs: z\n .number()\n .int()\n .min(1000)\n .max(300000)\n .optional()\n .describe(\"Execution timeout in ms (default 60000) — raise for scripts creating hundreds of nodes\"),\n },\n async ({ code, description, timeoutMs }) => {\n try {\n const result = await sendCommand(\"execute_code\", { code, description }, timeoutMs ?? 60000);\n return jsonResult(result);\n } catch (error) {\n return errorResult(error);\n }\n }\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { SendCommandFn } from \"../../tool-registry.js\";\nimport { jsonResult, errorResult, textResult } from \"./helpers.js\";\n\n// Comments live behind Figma's REST API (the Plugin API cannot see them), so\n// this tool needs a personal access token. Without FIGMA_TOKEN it stays\n// discoverable but explains how to unlock itself.\n\nconst API = \"https://api.figma.com/v1\";\n\n// figma.com/file/KEY/... and figma.com/design/KEY/... both carry the file key\nexport function parseFileKey(input: string): string | null {\n const url = input.match(/figma\\.com\\/(?:file|design)\\/([A-Za-z0-9]+)/);\n if (url) return url[1];\n if (/^[A-Za-z0-9]{15,}$/.test(input)) return input;\n return null;\n}\n\ninterface RawComment {\n id: string;\n message: string;\n user?: { handle?: string };\n created_at?: string;\n resolved_at?: string | null;\n parent_id?: string;\n client_meta?: { node_id?: string; node_offset?: { x: number; y: number }; x?: number; y?: number };\n}\n\nfunction compactComment(c: RawComment) {\n return {\n id: c.id,\n message: c.message,\n author: c.user?.handle,\n created_at: c.created_at,\n ...(c.resolved_at ? { resolved: true } : {}),\n ...(c.parent_id ? { replyTo: c.parent_id } : {}),\n ...(c.client_meta?.node_id ? { nodeId: c.client_meta.node_id } : {}),\n };\n}\n\nexport function register(server: McpServer, sendCommand: SendCommandFn): void {\n server.tool(\n \"manage_comments\",\n \"Read and write comments on the Figma file: list (with node anchors — great for 'apply the feedback in the comments' or polling for designer requests; filter with unresolved:true and since:<ISO date>), add (optionally pinned to a node), reply, delete. Comment-driven workflow: designers leave asks as comments in Figma; poll list (unresolved + since last check), do the work, then reply on the thread with what was done. Requires a FIGMA_TOKEN env var (personal access token with comment scopes, generated at figma.com Settings → Security); the canvas tools work without it. The file is auto-detected from the open plugin when possible — otherwise pass fileUrl.\",\n {\n action: z.enum([\"list\", \"add\", \"reply\", \"delete\"]),\n fileUrl: z.string().optional().describe(\"Figma file URL or key (auto-detected when omitted)\"),\n message: z.string().optional().describe(\"Comment text (add/reply)\"),\n commentId: z.string().optional().describe(\"Target comment (reply/delete)\"),\n nodeId: z.string().optional().describe(\"add: pin the comment to this node\"),\n x: z.number().optional().describe(\"add: canvas position (with y, when not pinning to a node)\"),\n y: z.number().optional(),\n since: z\n .string()\n .optional()\n .describe(\"list: only comments created after this ISO 8601 timestamp\"),\n unresolved: z.boolean().optional().describe(\"list: only unresolved threads\"),\n },\n async ({ action, fileUrl, message, commentId, nodeId, x, y, since, unresolved }) => {\n const token = process.env.FIGMA_TOKEN;\n if (!token) {\n return textResult(\n \"Comments need a Figma personal access token. Generate one at figma.com → Settings → Security → Personal access tokens (enable comment scopes), then add it to the MCP config: \\\"env\\\": { \\\"FIGMA_TOKEN\\\": \\\"figd_...\\\" } and restart. Everything else works without it.\"\n );\n }\n\n try {\n // Resolve the file key: explicit input → the plugin's own file\n let fileKey = fileUrl ? parseFileKey(fileUrl) : null;\n if (fileUrl && !fileKey) {\n return textResult(`Could not extract a file key from \"${fileUrl}\" — pass a figma.com/design/... URL.`);\n }\n if (!fileKey) {\n const info = (await sendCommand(\"get_file_info\", {})) as { fileKey?: string | null };\n fileKey = info?.fileKey ?? null;\n }\n if (!fileKey) {\n return textResult(\n \"Figma doesn't expose this file's key to the plugin. Pass fileUrl with the file's figma.com URL (copy it from the browser or Share dialog).\"\n );\n }\n\n const request = async (method: string, path: string, body?: unknown) => {\n const res = await fetch(`${API}${path}`, {\n method,\n headers: {\n \"X-Figma-Token\": token,\n ...(body ? { \"Content-Type\": \"application/json\" } : {}),\n },\n ...(body ? { body: JSON.stringify(body) } : {}),\n });\n const json = (await res.json().catch(() => ({}))) as Record<string, unknown>;\n if (!res.ok) {\n throw new Error(\n `Figma API ${res.status}: ${(json as { err?: string; message?: string }).err ?? (json as { message?: string }).message ?? \"request failed\"}` +\n (res.status === 403 ? \" — check the token's comment scopes and file access\" : \"\")\n );\n }\n return json;\n };\n\n switch (action) {\n case \"list\": {\n const data = await request(\"GET\", `/files/${fileKey}/comments`);\n let raw = (data.comments as RawComment[]) ?? [];\n if (unresolved) raw = raw.filter((c) => !c.resolved_at);\n if (since) {\n const cutoff = Date.parse(since);\n if (Number.isNaN(cutoff)) {\n return textResult(`since \"${since}\" is not a parseable ISO 8601 timestamp.`);\n }\n raw = raw.filter((c) => c.created_at && Date.parse(c.created_at) > cutoff);\n }\n const comments = raw.slice(0, 100).map(compactComment);\n return jsonResult({ count: comments.length, comments, checkedAt: new Date().toISOString() });\n }\n case \"add\": {\n if (!message) return textResult(\"add requires message.\");\n const client_meta = nodeId\n ? { node_id: nodeId, node_offset: { x: x ?? 0, y: y ?? 0 } }\n : x !== undefined && y !== undefined\n ? { x, y }\n : undefined;\n const data = await request(\"POST\", `/files/${fileKey}/comments`, {\n message,\n ...(client_meta ? { client_meta } : {}),\n });\n return jsonResult(compactComment(data as unknown as RawComment));\n }\n case \"reply\": {\n if (!message || !commentId) return textResult(\"reply requires commentId and message.\");\n const data = await request(\"POST\", `/files/${fileKey}/comments`, {\n message,\n comment_id: commentId,\n });\n return jsonResult(compactComment(data as unknown as RawComment));\n }\n case \"delete\": {\n if (!commentId) return textResult(\"delete requires commentId.\");\n await request(\"DELETE\", `/files/${fileKey}/comments/${commentId}`);\n return textResult(`Comment ${commentId} deleted.`);\n }\n }\n } catch (error) {\n return errorResult(error);\n }\n }\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { SendCommandFn } from \"../../tool-registry.js\";\nimport { jsonResult, errorResult } from \"./helpers.js\";\nimport { parseFileKey } from \"./comments.js\";\n\n// The \"look before you draw\" tool. Layered honestly around what each API can\n// see: the plugin reports local + used-remote items and enabled-library\n// variable collections; a library's FULL component catalog needs the REST API\n// (FIGMA_TOKEN + that library file's key).\n\nexport function register(server: McpServer, sendCommand: SendCommandFn): void {\n server.tool(\n \"get_design_system\",\n \"Inventory the design system available to this file — call this BEFORE building UI, then prefer instantiating existing components (manage_components action:instantiate takes local and library keys) and binding existing variables over drawing raw shapes. Reports: local components/styles/variable collections with usage counts, remote components/styles the file already uses, and enabled libraries' variable collections. To list a library's full component catalog, pass libraryFileUrl (requires FIGMA_TOKEN). Results are cached per session — pass refresh:true after big library changes.\",\n {\n refresh: z.boolean().optional().describe(\"Rescan instead of using the session cache\"),\n libraryFileUrl: z\n .string()\n .optional()\n .describe(\n \"figma.com URL or key of a LIBRARY file to catalog via REST (needs FIGMA_TOKEN)\"\n ),\n },\n { readOnlyHint: true },\n async ({ refresh, libraryFileUrl }) => {\n try {\n const data = (await sendCommand(\n \"get_design_system\",\n { refresh: refresh ?? false },\n 120000\n )) as Record<string, unknown>;\n\n if (libraryFileUrl) {\n data.libraryCatalog = await fetchLibraryCatalog(libraryFileUrl);\n }\n\n return jsonResult(data);\n } catch (error) {\n return errorResult(error);\n }\n }\n );\n\n server.tool(\n \"manage_conventions\",\n \"File-level design conventions — a CLAUDE.md that lives INSIDE this Figma file (shared plugin data, travels with the file). action:get reads it, action:set overwrites it with markdown. get_document_overview auto-includes it, and whatever it says (naming rules, spacing habits, do-not-touch areas, library preferences) should be FOLLOWED like user instructions. When the designer states a durable preference ('always use our green', 'never touch the Archive page'), offer to record it here so every future session — from any AI client — inherits it.\",\n {\n action: z.enum([\"get\", \"set\"]),\n content: z.string().optional().describe(\"set: the full markdown doc (overwrites; max 20k chars)\"),\n },\n async ({ action, content }) => {\n try {\n if (action === \"set\") {\n return jsonResult(await sendCommand(\"set_conventions\", { content: content ?? \"\" }));\n }\n return jsonResult(await sendCommand(\"get_conventions\", {}));\n } catch (error) {\n return errorResult(error);\n }\n }\n );\n}\n\nasync function fetchLibraryCatalog(libraryFileUrl: string): Promise<unknown> {\n const token = process.env.FIGMA_TOKEN;\n if (!token) {\n return {\n note: \"Full library catalogs need a FIGMA_TOKEN env var (personal access token, file read scope). Without it, components the file already uses are still listed above — or keep a 'DS palette' page with one instance of each key component so they show up there.\",\n };\n }\n const fileKey = parseFileKey(libraryFileUrl);\n if (!fileKey) {\n return { note: `Could not extract a file key from \"${libraryFileUrl}\".` };\n }\n\n const get = async (path: string) => {\n const res = await fetch(`https://api.figma.com/v1${path}`, {\n headers: { \"X-Figma-Token\": token },\n });\n const json = (await res.json().catch(() => ({}))) as Record<string, unknown>;\n if (!res.ok) {\n throw new Error(\n `Figma API ${res.status} for ${path}: ${(json as { err?: string }).err ?? \"request failed\"}`\n );\n }\n return json;\n };\n\n const [components, styles] = await Promise.all([\n get(`/files/${fileKey}/components`),\n get(`/files/${fileKey}/styles`),\n ]);\n const meta = (r: unknown) =>\n ((r as { meta?: Record<string, unknown> }).meta ?? {}) as Record<string, unknown>;\n\n return {\n components: ((meta(components).components as Array<Record<string, unknown>>) ?? []).map(\n (c) => ({ key: c.key, name: c.name, description: c.description || undefined })\n ),\n styles: ((meta(styles).styles as Array<Record<string, unknown>>) ?? []).map((s) => ({\n key: s.key,\n name: s.name,\n type: s.style_type,\n })),\n };\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { SendCommandFn } from \"../tool-registry.js\";\n\nfunction textResult(text: string) {\n return { content: [{ type: \"text\" as const, text }] };\n}\n\nexport function register(server: McpServer, sendCommand: SendCommandFn): void {\n server.tool(\n \"batch_execute\",\n \"Execute multiple commands in a single round-trip. Use when performing 3+ similar operations (e.g., styling multiple nodes, creating many elements). Commands run sequentially. Pass dryRun:true to preview the exact command list without touching the canvas — useful for showing the designer a plan before a large batch.\",\n {\n commands: z\n .array(\n z.object({\n command: z.string().describe(\"Command name\"),\n params: z.record(z.string(), z.unknown()).optional().describe(\"Command parameters\"),\n })\n )\n .describe(\"Array of commands to execute sequentially\"),\n dryRun: z.boolean().optional().describe(\"Preview only — return the plan, execute nothing\"),\n },\n async ({ commands, dryRun }) => {\n try {\n if (dryRun) {\n return textResult(\n JSON.stringify({\n dryRun: true,\n commandCount: commands.length,\n commands,\n note: \"Nothing was executed. Re-run without dryRun to apply.\",\n })\n );\n }\n const result = await sendCommand(\n \"batch_execute\",\n { commands },\n commands.length * 30000 // Scale timeout by command count\n );\n return textResult(JSON.stringify(result));\n } catch (error) {\n return textResult(`Error: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n );\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { SendCommandFn } from \"../../tool-registry.js\";\nimport { standardResult } from \"../../semantic/response.js\";\nimport { errorResult, noSelectionError } from \"../../semantic/errors.js\";\nimport { normalizeNode, normalizeNodes, calculateTokenCoverage } from \"../../semantic/normalize.js\";\nimport type {\n DocumentOverviewData,\n SelectionContextData,\n NodeDetailsData,\n SearchNodesData,\n DesignTokensData,\n} from \"@figma-relai/shared\";\n\n// The plugin's get_styles returns {paintStyles, textStyles, effectStyles,\n// gridStyles}; a flat array is tolerated for robustness. Exported for tests.\nexport function styleCountsFrom(styles: unknown): {\n paint: number;\n text: number;\n effect: number;\n grid: number;\n total: number;\n} {\n const counts = { paint: 0, text: 0, effect: 0, grid: 0 };\n if (Array.isArray(styles)) {\n for (const s of styles as Array<{ type?: string }>) {\n const t = (s.type || \"\").toLowerCase() as keyof typeof counts;\n if (t in counts) counts[t]++;\n }\n } else if (styles && typeof styles === \"object\") {\n const o = styles as Record<string, unknown>;\n counts.paint = Array.isArray(o.paintStyles) ? o.paintStyles.length : 0;\n counts.text = Array.isArray(o.textStyles) ? o.textStyles.length : 0;\n counts.effect = Array.isArray(o.effectStyles) ? o.effectStyles.length : 0;\n counts.grid = Array.isArray(o.gridStyles) ? o.gridStyles.length : 0;\n }\n return { ...counts, total: counts.paint + counts.text + counts.effect + counts.grid };\n}\n\nexport function register(server: McpServer, sendCommand: SendCommandFn): void {\n // ─── get_document_overview ───────────────────────────────────────\n server.tool(\n \"get_document_overview\",\n \"Get the full document structure: pages, component/style/variable counts. Always call this first to understand the file. Follow with get_selection_context or search_nodes.\",\n {},\n { readOnlyHint: true },\n async () => {\n try {\n const [docInfo, collections, styles, conventions] = await Promise.all([\n sendCommand(\"get_document_info\") as Promise<any>,\n sendCommand(\"get_variable_collections\") as Promise<any[]>,\n sendCommand(\"get_styles\") as Promise<any[]>,\n // Older plugin builds don't have the handler — degrade quietly\n sendCommand(\"get_conventions\", {}).catch(() => null) as Promise<any>,\n ]);\n\n // Counting components needs a full document walk — the plugin doesn't\n // do that here, so report \"unknown\" instead of a misleading 0.\n const componentCount = docInfo.componentCount ?? null;\n\n const stylesByType = styleCountsFrom(styles);\n\n const data: DocumentOverviewData = {\n name: docInfo.name,\n currentPage: docInfo.currentPage,\n pages: docInfo.pages || [],\n counts: {\n components: componentCount,\n styles: stylesByType.total,\n variableCollections: Array.isArray(collections) ? collections.length : 0,\n },\n };\n\n // File conventions are standing designer instructions — surface them\n // where every session starts so they cannot be missed\n const conventionsText: string | null = conventions?.content ?? null;\n\n return standardResult({\n summary:\n `\"${data.name}\" — ${data.pages.length} pages, ` +\n (data.counts.components != null ? `${data.counts.components} components, ` : \"\") +\n `${data.counts.styles} styles, ${data.counts.variableCollections} variable collections` +\n (data.counts.components == null ? \" (component inventory via get_design_system)\" : \"\") +\n (conventionsText ? \". This file has conventions — follow them (see data.conventions).\" : \"\"),\n data: { ...data, ...(conventionsText ? { conventions: conventionsText } : {}) },\n recommended_next: [\n { tool: \"get_selection_context\", reason: \"Inspect currently selected nodes\" },\n { tool: \"search_nodes\", reason: \"Find specific nodes by name or type\" },\n { tool: \"get_design_tokens\", reason: \"Explore the design token system\" },\n ],\n });\n } catch (error) {\n return errorResult(\n \"connection_error\",\n `Failed to get document info: ${error instanceof Error ? error.message : String(error)}`,\n { suggestion: \"Ensure Figma plugin is connected. Call join_room first.\", tool: \"join_room\" }\n );\n }\n }\n );\n\n // ─── get_selection_context ──────────────────────────────────────\n server.tool(\n \"get_selection_context\",\n \"Get full context for the current Figma selection: node properties, fills, layout, token bindings, and children summary. Use as the starting point for any inspection or modification workflow. Follow with analyze_* tools or update_node.\",\n {},\n { readOnlyHint: true },\n async () => {\n try {\n const selection = await sendCommand(\"get_selection\") as any;\n if (!selection?.nodes?.length) {\n return noSelectionError();\n }\n\n const nodeIds = selection.nodes.map((n: any) => n.id);\n\n // Fetch detailed info and variable bindings in parallel\n const [nodesInfo, ...bindings] = await Promise.all([\n sendCommand(\"get_nodes_info\", { nodeIds, depth: 2 }) as Promise<any[]>,\n ...nodeIds.map((id: string) =>\n sendCommand(\"get_bound_variables\", { nodeId: id }).catch(() => null) as Promise<any>\n ),\n ]);\n\n const nodes = (Array.isArray(nodesInfo) ? nodesInfo : []).map((raw: any, i: number) => {\n const summary = normalizeNode(raw);\n if (!summary) return null;\n\n const boundVars = bindings[i]?.boundVariables || null;\n summary.tokenCoverage = calculateTokenCoverage(raw, boundVars);\n if (boundVars) {\n summary.fillToken = extractTokenName(boundVars, \"fills\");\n summary.strokeToken = extractTokenName(boundVars, \"strokes\");\n }\n return summary;\n }).filter(Boolean);\n\n const data: SelectionContextData = {\n nodes: nodes as any[],\n pageInfo: selection.currentPage || { id: \"\", name: \"\" },\n };\n\n const avgCoverage = nodes.length > 0\n ? Math.round(nodes.reduce((sum: number, n: any) => sum + (n.tokenCoverage || 0), 0) / nodes.length * 100)\n : 0;\n\n const warnings = [];\n if (avgCoverage < 50) {\n warnings.push({\n category: \"tokens\" as const,\n message: `Token coverage is ${avgCoverage}% — many properties are not bound to design variables`,\n });\n }\n\n return standardResult({\n summary: `Selected ${nodes.length} node(s): ${nodes.map((n: any) => `'${n.name}' (${n.type})`).join(\", \")}. Token coverage: ${avgCoverage}%`,\n data,\n warnings,\n recommended_next: [\n { tool: \"analyze_color_usage\", reason: \"Audit color consistency and token coverage\" },\n { tool: \"update_node\", reason: \"Modify selected node properties\" },\n { tool: \"screenshot\", reason: \"Visually inspect the selection\" },\n ],\n });\n } catch (error) {\n return errorResult(\n \"connection_error\",\n `Failed to get selection: ${error instanceof Error ? error.message : String(error)}`,\n { suggestion: \"Ensure Figma plugin is connected\", tool: \"join_room\" }\n );\n }\n }\n );\n\n // ─── get_node_details ───────────────────────────────────────────\n server.tool(\n \"get_node_details\",\n \"Get a single node's full properties, CSS, token bindings, and children. Use after search_nodes or get_selection_context to inspect a specific node. Follow with update_node or analyze_* tools.\",\n {\n nodeId: z.string().describe(\"The node ID to inspect\"),\n },\n { readOnlyHint: true },\n async ({ nodeId }) => {\n try {\n const [nodeInfo, boundVars, css] = await Promise.all([\n sendCommand(\"get_node_info\", { nodeId, depth: 2 }) as Promise<any>,\n sendCommand(\"get_bound_variables\", { nodeId }).catch(() => null) as Promise<any>,\n sendCommand(\"get_css\", { nodeId }).catch(() => null) as Promise<any>,\n ]);\n\n if (!nodeInfo) {\n return errorResult(\n \"invalid_input\",\n `Node '${nodeId}' not found`,\n { suggestion: \"Use search_nodes to find the correct node ID\", tool: \"search_nodes\" }\n );\n }\n\n const node = normalizeNode(nodeInfo);\n if (!node) {\n return errorResult(\n \"invalid_input\",\n `Could not process node '${nodeId}'`,\n { suggestion: \"Try get_node_info directly for raw data\", tool: \"get_node_info\" }\n );\n }\n\n const bv = boundVars?.boundVariables || null;\n node.tokenCoverage = calculateTokenCoverage(nodeInfo, bv);\n if (bv) {\n node.fillToken = extractTokenName(bv, \"fills\");\n node.strokeToken = extractTokenName(bv, \"strokes\");\n }\n\n const children = nodeInfo.children\n ? normalizeNodes(nodeInfo.children)\n : undefined;\n\n const data: NodeDetailsData = {\n node,\n css: css?.css,\n boundVariables: bv || undefined,\n children,\n };\n\n return standardResult({\n summary: `'${node.name}' (${node.type}, ${node.size.width}×${node.size.height}). Token coverage: ${Math.round((node.tokenCoverage || 0) * 100)}%`,\n data,\n recommended_next: [\n { tool: \"update_node\", reason: \"Modify this node's properties\", args: { nodeId } },\n { tool: \"analyze_color_usage\", reason: \"Check color token usage\", args: { nodeId } },\n ],\n });\n } catch (error) {\n return errorResult(\n \"connection_error\",\n `Failed to get node details: ${error instanceof Error ? error.message : String(error)}`,\n { suggestion: \"Ensure Figma plugin is connected\", tool: \"join_room\" }\n );\n }\n }\n );\n\n // ─── search_nodes ───────────────────────────────────────────────\n server.tool(\n \"search_nodes\",\n \"Search for nodes by name and/or type within a scope. Returns matching node IDs, names, and types. Use to find specific elements before inspecting or modifying them. Follow with get_node_details or update_node.\",\n {\n query: z.string().optional().describe(\"Name substring to search for\"),\n types: z.array(z.string()).optional().describe(\"Node types to filter: FRAME, TEXT, COMPONENT, INSTANCE, RECTANGLE, etc.\"),\n parentId: z.string().optional().describe(\"Scope search to children of this node (default: current page)\"),\n },\n { readOnlyHint: true },\n async ({ query, types, parentId }) => {\n try {\n const result = await sendCommand(\"find_nodes\", {\n name: query,\n types,\n parentId,\n }) as any[];\n\n const matches = (Array.isArray(result) ? result : []).map((n: any) => ({\n id: n.id,\n name: n.name,\n type: n.type,\n parentName: n.parent?.name,\n }));\n\n const data: SearchNodesData = {\n matches,\n total: matches.length,\n };\n\n return standardResult({\n summary: `Found ${matches.length} node(s)${query ? ` matching '${query}'` : \"\"}${types?.length ? ` of type ${types.join(\"/\")}` : \"\"}`,\n data,\n recommended_next: matches.length > 0\n ? [\n { tool: \"get_node_details\", reason: \"Inspect a specific node\", args: { nodeId: matches[0].id } },\n { tool: \"navigate_to\", reason: \"Focus on a found node\", args: { nodeId: matches[0].id } },\n ]\n : [\n { tool: \"get_document_overview\", reason: \"Check document structure\" },\n ],\n });\n } catch (error) {\n return errorResult(\n \"connection_error\",\n `Search failed: ${error instanceof Error ? error.message : String(error)}`,\n { suggestion: \"Ensure Figma plugin is connected\", tool: \"join_room\" }\n );\n }\n }\n );\n\n // ─── get_design_tokens ──────────────────────────────────────────\n server.tool(\n \"get_design_tokens\",\n \"Get an overview of the design token system: variable collections, modes, variable counts, and style counts. Use to understand the design system before binding tokens or creating new variables. Follow with manage_variables or bind_tokens.\",\n {},\n { readOnlyHint: true },\n async () => {\n try {\n const [collections, styles] = await Promise.all([\n sendCommand(\"get_variable_collections\") as Promise<any[]>,\n sendCommand(\"get_styles\") as Promise<any[]>,\n ]);\n\n const collectionSummaries = (Array.isArray(collections) ? collections : []).map((c: any) => ({\n id: c.id,\n name: c.name,\n modes: Array.isArray(c.modes) ? c.modes : [],\n variableCount: Array.isArray(c.variableIds) ? c.variableIds.length : 0,\n }));\n\n const { total: _ignored, ...stylesByType } = styleCountsFrom(styles);\n\n const totalVars = collectionSummaries.reduce((sum, c) => sum + c.variableCount, 0);\n\n const data: DesignTokensData = {\n collections: collectionSummaries,\n styles: stylesByType,\n };\n\n return standardResult({\n summary: `${collectionSummaries.length} collection(s) with ${totalVars} variables. Styles: ${stylesByType.paint} paint, ${stylesByType.text} text, ${stylesByType.effect} effect, ${stylesByType.grid} grid`,\n data,\n recommended_next: [\n { tool: \"manage_variables\", reason: \"Create or update design tokens\" },\n { tool: \"analyze_color_usage\", reason: \"Check token coverage on selected nodes\" },\n ],\n });\n } catch (error) {\n return errorResult(\n \"connection_error\",\n `Failed to get design tokens: ${error instanceof Error ? error.message : String(error)}`,\n { suggestion: \"Ensure Figma plugin is connected\", tool: \"join_room\" }\n );\n }\n }\n );\n\n // ─── screenshot ─────────────────────────────────────────────────\n server.tool(\n \"screenshot\",\n \"Take a PNG screenshot of a node or the current view. Returns an image visible to the AI. Use to visually verify changes or inspect design details. Works for both context inspection and verification after modifications.\",\n {\n nodeId: z.string().optional().describe(\"Node ID to screenshot (default: current view)\"),\n },\n { readOnlyHint: true },\n async ({ nodeId }) => {\n try {\n const result = await sendCommand(\"get_screenshot\", nodeId ? { nodeId } : {}) as any;\n\n // get_screenshot returns image data — pass through as-is for image content type\n if (result?.imageData) {\n return {\n content: [\n {\n type: \"image\" as const,\n data: result.imageData,\n mimeType: \"image/png\",\n },\n {\n type: \"text\" as const,\n text: JSON.stringify({\n summary: `Screenshot taken${nodeId ? ` of node ${nodeId}` : \" of current view\"}`,\n recommended_next: [\n { tool: \"get_selection_context\", reason: \"Get structured data about the selection\" },\n { tool: \"update_node\", reason: \"Make changes based on what you see\" },\n ],\n }),\n },\n ],\n };\n }\n\n // Fallback: result might be in a different format\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(result) }],\n };\n } catch (error) {\n return errorResult(\n \"connection_error\",\n `Screenshot failed: ${error instanceof Error ? error.message : String(error)}`,\n { suggestion: \"Ensure Figma plugin is connected\", tool: \"join_room\" }\n );\n }\n }\n );\n}\n\n// Extract token/variable name from bound variables\nfunction extractTokenName(boundVars: Record<string, unknown>, prefix: string): string | null {\n for (const [key, value] of Object.entries(boundVars)) {\n if (key.startsWith(prefix) || key === prefix) {\n if (value && typeof value === \"object\" && \"name\" in (value as any)) {\n return (value as any).name;\n }\n if (typeof value === \"string\") return value;\n }\n }\n return null;\n}\n","import type {\n ToolResponse,\n ToolWarning,\n RecommendedTool,\n PartialFailure,\n} from \"@figma-relai/shared\";\n\n// Build a standard v2 tool success response\nexport function standardResult<T>(opts: {\n summary: string;\n data: T;\n warnings?: ToolWarning[];\n recommended_next?: RecommendedTool[];\n partial_failures?: PartialFailure[];\n}) {\n const response: ToolResponse<T> = {\n summary: opts.summary,\n data: opts.data,\n };\n if (opts.warnings?.length) response.warnings = opts.warnings;\n if (opts.recommended_next?.length) response.recommended_next = opts.recommended_next;\n if (opts.partial_failures?.length) response.partial_failures = opts.partial_failures;\n\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(response) }],\n };\n}\n\n// Simple text result (for compatibility with v1 tools)\nexport function textResult(text: string) {\n return { content: [{ type: \"text\" as const, text }] };\n}\n","import type { ErrorCategory, ToolError, RecoveryOption } from \"@figma-relai/shared\";\n\n// Build a structured error response for v2 tools\nexport function errorResult(\n category: ErrorCategory,\n message: string,\n recovery: RecoveryOption,\n extra?: {\n preconditions?: { required: string; current_state: string };\n partial_result?: unknown;\n }\n) {\n const error: ToolError = {\n category,\n message,\n recovery,\n };\n if (extra?.preconditions) error.preconditions = extra.preconditions;\n if (extra?.partial_result !== undefined) error.partial_result = extra.partial_result;\n\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify({ error }, null, 2) }],\n };\n}\n\n// Shortcut for common precondition failures\nexport function noSelectionError() {\n return errorResult(\n \"precondition_failed\",\n \"No nodes selected in Figma\",\n {\n suggestion: \"Select nodes in Figma, or use search_nodes to find nodes by name/type\",\n tool: \"search_nodes\",\n },\n { preconditions: { required: \"At least 1 node selected\", current_state: \"Selection is empty\" } }\n );\n}\n\nexport function nodeNotFoundError(nodeId: string) {\n return errorResult(\n \"invalid_input\",\n `Node '${nodeId}' not found`,\n {\n suggestion: \"The node may have been deleted or the ID is incorrect. Use search_nodes to find the correct node.\",\n tool: \"search_nodes\",\n }\n );\n}\n\nexport function typeMismatchError(nodeId: string, nodeName: string, nodeType: string, requiredTypes: string[]) {\n return errorResult(\n \"type_mismatch\",\n `Node '${nodeName}' (${nodeId}) is ${nodeType}, but this operation requires ${requiredTypes.join(\" or \")}`,\n {\n suggestion: `Target a ${requiredTypes[0]} node instead, or check the parent node`,\n tool: \"get_node_details\",\n args: { nodeId },\n },\n { preconditions: { required: `Node type: ${requiredTypes.join(\" | \")}`, current_state: `Node type: ${nodeType}` } }\n );\n}\n\nexport function connectionError() {\n return errorResult(\n \"connection_error\",\n \"Not connected to Figma plugin\",\n {\n suggestion: \"Call join_room first with the room name from the Figma plugin UI\",\n tool: \"join_room\",\n },\n { preconditions: { required: \"Connected to Figma plugin\", current_state: \"No active connection\" } }\n );\n}\n","import type { NodeSummary, LayoutSummary } from \"@figma-relai/shared\";\nimport { rgbaToHex } from \"@figma-relai/shared\";\n\n// Convert raw Figma node data to a semantic NodeSummary\nexport function normalizeNode(raw: any): NodeSummary | null {\n if (!raw) return null;\n\n const summary: NodeSummary = {\n id: raw.id,\n name: raw.name,\n type: raw.type,\n size: {\n width: raw.width ?? raw.absoluteBoundingBox?.width ?? 0,\n height: raw.height ?? raw.absoluteBoundingBox?.height ?? 0,\n },\n position: {\n x: raw.x ?? raw.absoluteBoundingBox?.x ?? 0,\n y: raw.y ?? raw.absoluteBoundingBox?.y ?? 0,\n },\n };\n\n // Fill color → hex\n const fill = extractFillColor(raw);\n if (fill) summary.fill = fill;\n\n // Stroke → hex\n const stroke = extractStrokeColor(raw);\n if (stroke) summary.stroke = stroke;\n\n // Corner radius\n if (raw.cornerRadius !== undefined) {\n summary.cornerRadius = raw.cornerRadius === \"mixed\" ? \"mixed\" : raw.cornerRadius;\n }\n\n // Opacity\n if (raw.opacity !== undefined && raw.opacity < 1) {\n summary.opacity = raw.opacity;\n }\n\n // Layout\n summary.layout = extractLayout(raw);\n\n // Children summary\n if (raw.children?.length > 0) {\n summary.childSummary = summarizeChildren(raw.children);\n }\n\n // Component status\n summary.componentStatus = extractComponentStatus(raw);\n\n return summary;\n}\n\n// Normalize an array of raw nodes\nexport function normalizeNodes(rawNodes: any[]): NodeSummary[] {\n return rawNodes.map(normalizeNode).filter((n): n is NodeSummary => n !== null);\n}\n\n// Extract the first solid fill color as hex\nfunction extractFillColor(node: any): string | undefined {\n if (!node.fills?.length) return undefined;\n const solidFill = node.fills.find((f: any) => f.type === \"SOLID\" && f.visible !== false);\n if (!solidFill?.color) return undefined;\n\n if (typeof solidFill.color === \"string\" && solidFill.color.startsWith(\"#\")) {\n return solidFill.color;\n }\n return rgbaToHex({\n r: solidFill.color.r,\n g: solidFill.color.g,\n b: solidFill.color.b,\n a: solidFill.opacity ?? solidFill.color.a ?? 1,\n });\n}\n\n// Extract the first stroke color as hex\nfunction extractStrokeColor(node: any): string | undefined {\n if (!node.strokes?.length) return undefined;\n const stroke = node.strokes.find((s: any) => s.type === \"SOLID\" && s.visible !== false);\n if (!stroke?.color) return undefined;\n\n if (typeof stroke.color === \"string\" && stroke.color.startsWith(\"#\")) {\n return stroke.color;\n }\n return rgbaToHex({\n r: stroke.color.r,\n g: stroke.color.g,\n b: stroke.color.b,\n a: stroke.opacity ?? stroke.color.a ?? 1,\n });\n}\n\n// Extract layout info into a compact summary\nfunction extractLayout(node: any): LayoutSummary | null {\n if (!node.layoutMode || node.layoutMode === \"NONE\") return null;\n\n const pt = node.paddingTop ?? 0;\n const pr = node.paddingRight ?? 0;\n const pb = node.paddingBottom ?? 0;\n const pl = node.paddingLeft ?? 0;\n\n let padding: string;\n if (pt === pr && pr === pb && pb === pl) {\n padding = `${pt}px all`;\n } else if (pt === pb && pl === pr) {\n padding = `${pt}/${pl}`;\n } else {\n padding = `${pt}/${pr}/${pb}/${pl}`;\n }\n\n return {\n mode: node.layoutMode,\n padding,\n gap: node.itemSpacing ?? 0,\n sizing: {\n horizontal: node.primaryAxisSizingMode ?? node.layoutSizingHorizontal ?? \"FIXED\",\n vertical: node.counterAxisSizingMode ?? node.layoutSizingVertical ?? \"FIXED\",\n },\n };\n}\n\n// Summarize children as a compact string like \"3 children: 1 TEXT, 2 FRAME\"\nfunction summarizeChildren(children: any[]): string {\n const typeCounts = new Map<string, number>();\n for (const child of children) {\n const type = child.type || \"UNKNOWN\";\n typeCounts.set(type, (typeCounts.get(type) || 0) + 1);\n }\n const parts = Array.from(typeCounts.entries())\n .map(([type, count]) => `${count} ${type}`)\n .join(\", \");\n return `${children.length} children: ${parts}`;\n}\n\n// Extract component status\nfunction extractComponentStatus(node: any): string | null {\n if (node.type === \"COMPONENT\") return \"component\";\n if (node.type === \"COMPONENT_SET\") return \"component_set\";\n if (node.type === \"INSTANCE\") {\n const mainName = node.mainComponent?.name || node.componentName;\n return mainName ? `instance of '${mainName}'` : \"instance\";\n }\n return null;\n}\n\n// Count how many properties are bound to variables vs total color/spacing properties\nexport function calculateTokenCoverage(\n node: any,\n boundVariables: Record<string, unknown> | null\n): number {\n let totalProps = 0;\n let boundProps = 0;\n\n // Count fill properties\n if (node.fills?.length > 0) {\n totalProps++;\n if (boundVariables && hasBinding(boundVariables, \"fills\")) boundProps++;\n }\n\n // Count stroke properties\n if (node.strokes?.length > 0) {\n totalProps++;\n if (boundVariables && hasBinding(boundVariables, \"strokes\")) boundProps++;\n }\n\n // Count spacing properties\n for (const prop of [\"itemSpacing\", \"paddingTop\", \"paddingRight\", \"paddingBottom\", \"paddingLeft\"]) {\n if (node[prop] !== undefined && node[prop] > 0) {\n totalProps++;\n if (boundVariables && hasBinding(boundVariables, prop)) boundProps++;\n }\n }\n\n // Corner radius\n if (node.cornerRadius !== undefined && node.cornerRadius > 0) {\n totalProps++;\n if (boundVariables && hasBinding(boundVariables, \"cornerRadius\")) boundProps++;\n }\n\n if (totalProps === 0) return 1; // No styleable properties = fully covered\n return Math.round((boundProps / totalProps) * 100) / 100;\n}\n\nfunction hasBinding(boundVars: Record<string, unknown>, prefix: string): boolean {\n return Object.keys(boundVars).some((key) => key.startsWith(prefix) || key === prefix);\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { CallToolResult } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { SendCommandFn } from \"../../tool-registry.js\";\nimport { standardResult } from \"../../semantic/response.js\";\nimport { errorResult, noSelectionError } from \"../../semantic/errors.js\";\nimport { normalizeNode } from \"../../semantic/normalize.js\";\nimport { computeHealthScore, type HealthInputs } from \"../../semantic/health.js\";\nimport { rgbaToHex } from \"@figma-relai/shared\";\nimport type {\n ColorUsageData,\n ColorUsageIssue,\n LayoutQualityData,\n LayoutIssue,\n ComponentHealthData,\n AccessibilityData,\n AccessibilityIssue,\n DiffNodesData,\n NodeDiffField,\n} from \"@figma-relai/shared\";\n\n// The consolidated tool surface exposes one analyze_design tool; the four\n// aspect implementations below register through an interceptor that collects\n// their handlers instead of exposing them individually. diff_nodes stays a\n// real tool (it has a different signature).\nconst ASPECT_TOOL: Record<string, string> = {\n color: \"analyze_color_usage\",\n layout: \"analyze_layout_quality\",\n components: \"analyze_component_health\",\n accessibility: \"analyze_accessibility\",\n};\n\nexport function register(server: McpServer, sendCommand: SendCommandFn): void {\n type ToolHandler = (args: { nodeId?: string }) => Promise<CallToolResult>;\n const aspectHandlers = new Map<string, ToolHandler>();\n\n const interceptor = new Proxy(server, {\n get(target, prop, receiver) {\n if (prop !== \"tool\") return Reflect.get(target, prop, receiver);\n return (name: string, ...rest: unknown[]) => {\n if (name.startsWith(\"analyze_\")) {\n aspectHandlers.set(name, rest[rest.length - 1] as ToolHandler);\n return;\n }\n return (target.tool as (...a: unknown[]) => unknown).call(target, name, ...rest);\n };\n },\n }) as McpServer;\n\n registerAnalysisTools(interceptor, sendCommand);\n\n server.tool(\n \"analyze_design\",\n \"Audit the design from one aspect: color (token coverage, unbound fills/strokes), layout (auto-layout quality, spacing consistency), components (detached instances, component health), accessibility (WCAG contrast incl. large-text thresholds, touch targets, minimum text sizes), tokens (hardcoded values that match an existing variable — each finding names the variable to bind; fix in one shot with manage_variables action:tokenize fix:true), or overall (runs color/layout/components/accessibility and returns a weighted 0-100 health score — good for audits and reports). Defaults to the current selection; tokens defaults to the current page.\",\n {\n aspect: z.enum([\"color\", \"layout\", \"components\", \"accessibility\", \"tokens\", \"overall\"]),\n nodeId: z.string().optional().describe(\"Root node to analyze (default: current selection)\"),\n },\n { readOnlyHint: true },\n async ({ aspect, nodeId }) => {\n if (aspect === \"overall\") {\n return runOverallAudit(aspectHandlers, nodeId);\n }\n if (aspect === \"tokens\") {\n return runTokenDrift(sendCommand, nodeId);\n }\n const handler = aspectHandlers.get(ASPECT_TOOL[aspect]);\n if (!handler) throw new Error(`Unknown aspect: ${aspect}`);\n return handler({ nodeId });\n }\n );\n}\n\n// Token drift is a report-only pass over scan_token_drift; the write path\n// lives in manage_variables (action: tokenize) so this tool stays read-only.\nasync function runTokenDrift(\n sendCommand: SendCommandFn,\n nodeId?: string\n): Promise<CallToolResult> {\n const data = (await sendCommand(\"scan_token_drift\", { nodeId, fix: false }, 120000)) as {\n findings?: Array<{ variableName?: string }>;\n stats?: { nodesScanned?: number; matched?: number };\n note?: string;\n };\n const matched = data.stats?.matched ?? 0;\n return standardResult({\n summary:\n data.note ??\n (matched === 0\n ? `No token drift: nothing hardcoded matches an existing variable (${data.stats?.nodesScanned ?? 0} nodes scanned).`\n : `${matched} hardcoded value(s) match an existing variable and could be bound.`),\n data,\n warnings:\n matched > 0\n ? [\n {\n category: \"general\" as const,\n message: `${matched} value(s) drift from tokens they visually match`,\n },\n ]\n : [],\n recommended_next:\n matched > 0\n ? [\n {\n tool: \"manage_variables\",\n reason: 'Bind them in one pass: action \"tokenize\" with fix: true',\n },\n ]\n : [],\n });\n}\n\n// Runs all four aspect analyses and folds them into one weighted score.\n// A failed aspect is excluded and the remaining weights renormalize.\nasync function runOverallAudit(\n aspectHandlers: Map<string, (args: { nodeId?: string }) => Promise<CallToolResult>>,\n nodeId?: string\n): Promise<CallToolResult> {\n const parse = (result: CallToolResult): any => {\n try {\n const text = (result.content?.[0] as { text?: string })?.text ?? \"\";\n const parsed = JSON.parse(text);\n return parsed?.data ?? null;\n } catch {\n return null;\n }\n };\n\n const run = async (tool: string) => {\n const handler = aspectHandlers.get(tool);\n if (!handler) return null;\n try {\n return parse(await handler({ nodeId }));\n } catch {\n return null;\n }\n };\n\n const [color, layout, components, accessibility] = await Promise.all([\n run(\"analyze_color_usage\"),\n run(\"analyze_layout_quality\"),\n run(\"analyze_component_health\"),\n run(\"analyze_accessibility\"),\n ]);\n\n const inputs: HealthInputs = {\n color: color\n ? { tokenCoverage: color.tokenCoverage ?? 0, unboundCount: color.unboundCount ?? 0 }\n : null,\n layout: layout\n ? {\n autoLayoutCoverage: layout.autoLayoutCoverage ?? 0,\n issueCount: layout.issues?.length ?? 0,\n }\n : null,\n components: components\n ? {\n totalInstances: components.totalInstances ?? 0,\n detachedCount: components.detachedCount ?? 0,\n }\n : null,\n accessibility: accessibility ? { issueCount: accessibility.issueCount ?? 0 } : null,\n };\n\n const health = computeHealthScore(inputs);\n const excluded = (Object.keys(inputs) as Array<keyof HealthInputs>).filter((k) => !inputs[k]);\n\n const worst = [...health.categories].sort((a, b) => a.score - b.score)[0];\n return standardResult({\n summary: `Design health: ${health.score}/100 (grade ${health.grade}). Weakest area: ${worst ? `${worst.category} at ${worst.score}` : \"n/a\"}.`,\n data: {\n ...health,\n ...(excluded.length > 0 ? { excluded } : {}),\n details: { color, layout, components, accessibility },\n },\n warnings:\n health.grade === \"A\"\n ? []\n : health.categories\n .filter((c) => c.score < 75)\n .map((c) => ({\n category: \"general\" as const,\n message: `${c.category}: ${c.score}/100 — ${c.note}`,\n })),\n recommended_next: worst\n ? [\n {\n tool: \"analyze_design\",\n reason: `Drill into the weakest area with aspect: \"${worst.category}\"`,\n },\n ]\n : [],\n });\n}\n\nfunction registerAnalysisTools(server: McpServer, sendCommand: SendCommandFn): void {\n // ─── analyze_color_usage ────────────────────────────────────────\n server.tool(\n \"analyze_color_usage\",\n \"Audit color consistency and design token coverage for a node tree. Reports which fill/stroke colors are not bound to variables. Use after get_selection_context to diagnose token gaps. Follow with bind_tokens to fix issues.\",\n {\n nodeId: z.string().optional().describe(\"Root node to analyze (default: current selection)\"),\n },\n { readOnlyHint: true },\n async ({ nodeId }) => {\n try {\n // Resolve target node(s)\n let targetIds: string[];\n if (nodeId) {\n targetIds = [nodeId];\n } else {\n const selection = await sendCommand(\"get_selection\") as any;\n if (!selection?.nodes?.length) return noSelectionError();\n targetIds = selection.nodes.map((n: any) => n.id);\n }\n\n const unboundColors: ColorUsageIssue[] = [];\n const counters = { totalProps: 0, boundCount: 0 };\n let hiddenCount = 0;\n let scanned = 0;\n let capped = false;\n\n for (const id of targetIds) {\n // Fast path: one plugin-side recursive walk. Deep (all levels) and\n // reports hidden (visible:false) unbound paints, which the legacy\n // two-level path silently skipped.\n let audit: any = null;\n try {\n audit = await sendCommand(\"audit_colors\", { nodeId: id }, 60000);\n } catch {\n audit = null; // plugin build without the handler — legacy path below\n }\n if (audit && typeof audit.totalProperties === \"number\") {\n counters.totalProps += audit.totalProperties;\n counters.boundCount += audit.boundCount ?? 0;\n hiddenCount += audit.hiddenCount ?? 0;\n scanned += audit.scanned ?? 0;\n capped = capped || !!audit.capped;\n for (const issue of audit.issues ?? []) unboundColors.push(issue);\n continue;\n }\n\n const [nodeInfo, boundVars] = await Promise.all([\n sendCommand(\"get_node_info\", { nodeId: id, depth: 2, maxNodes: 200 }) as Promise<any>,\n sendCommand(\"get_bound_variables\", { nodeId: id }).catch(() => null) as Promise<any>,\n ]);\n if (!nodeInfo) continue;\n\n const bv = boundVars?.boundVariables || {};\n collectColorIssues(nodeInfo, bv, unboundColors, counters);\n\n // Also scan children (1 level deep for performance)\n if (nodeInfo.children) {\n for (const child of nodeInfo.children) {\n const childBv = await sendCommand(\"get_bound_variables\", { nodeId: child.id }).catch(() => null) as any;\n const cbv = childBv?.boundVariables || {};\n collectColorIssues(child, cbv, unboundColors, counters);\n }\n }\n }\n\n const tokenCoverage =\n counters.totalProps > 0\n ? Math.round((counters.boundCount / counters.totalProps) * 100) / 100\n : 1;\n\n const data: ColorUsageData = {\n totalProperties: counters.totalProps,\n boundCount: counters.boundCount,\n unboundCount: unboundColors.length,\n tokenCoverage,\n unboundColors,\n ...(hiddenCount ? { hiddenCount } : {}),\n ...(scanned ? { scanned } : {}),\n ...(capped ? { capped } : {}),\n };\n\n const visibleIssues = unboundColors.length - hiddenCount;\n const warnings = unboundColors.length > 0\n ? [{ category: \"tokens\" as const, message: `${unboundColors.length} color(s) not bound to design tokens${hiddenCount ? ` (${hiddenCount} on hidden paints)` : \"\"}` }]\n : [];\n\n return standardResult({\n summary:\n `Color audit: ${visibleIssues} unbound color(s)` +\n (hiddenCount ? ` + ${hiddenCount} on hidden paints` : \"\") +\n `. Token coverage: ${Math.round(data.tokenCoverage * 100)}%` +\n (capped ? \" (scan capped — large subtree)\" : \"\"),\n data,\n warnings,\n recommended_next: unboundColors.length > 0\n ? [\n { tool: \"bind_tokens\", reason: \"Bind unbound colors to design tokens\" },\n { tool: \"get_design_tokens\", reason: \"See available tokens for binding\" },\n ]\n : [\n { tool: \"analyze_layout_quality\", reason: \"Check layout quality next\" },\n ],\n });\n } catch (error) {\n return errorResult(\n \"connection_error\",\n `Analysis failed: ${error instanceof Error ? error.message : String(error)}`,\n { suggestion: \"Ensure Figma plugin is connected\", tool: \"join_room\" }\n );\n }\n }\n );\n\n // ─── analyze_layout_quality ─────────────────────────────────────\n server.tool(\n \"analyze_layout_quality\",\n \"Check layout quality: auto-layout usage, magic numbers in spacing/padding, and sizing consistency. Use after get_selection_context to find layout improvements. Follow with set_auto_layout to fix issues.\",\n {\n nodeId: z.string().optional().describe(\"Root node to analyze (default: current selection)\"),\n },\n { readOnlyHint: true },\n async ({ nodeId }) => {\n try {\n let targetId: string;\n if (nodeId) {\n targetId = nodeId;\n } else {\n const selection = await sendCommand(\"get_selection\") as any;\n if (!selection?.nodes?.length) return noSelectionError();\n targetId = selection.nodes[0].id;\n }\n\n const nodeInfo = await sendCommand(\"get_node_info\", { nodeId: targetId, depth: 8, maxNodes: 500 }) as any;\n if (!nodeInfo) {\n return errorResult(\"invalid_input\", `Node '${targetId}' not found`, { suggestion: \"Use search_nodes\", tool: \"search_nodes\" });\n }\n\n const issues: LayoutIssue[] = [];\n let totalFrames = 0;\n let autoLayoutCount = 0;\n\n analyzeLayoutNode(nodeInfo, issues, { totalFrames: 0, autoLayoutCount: 0 });\n\n // Count from issues to get proper totals\n const frameNodes = collectFrames(nodeInfo);\n totalFrames = frameNodes.length;\n autoLayoutCount = frameNodes.filter((f: any) => f.layoutMode && f.layoutMode !== \"NONE\").length;\n\n const data: LayoutQualityData = {\n totalFrames,\n autoLayoutCount,\n autoLayoutCoverage: totalFrames > 0 ? Math.round((autoLayoutCount / totalFrames) * 100) / 100 : 1,\n issues,\n };\n\n return standardResult({\n summary: `Layout audit: ${autoLayoutCount}/${totalFrames} frames use auto-layout (${Math.round(data.autoLayoutCoverage * 100)}%). ${issues.length} issue(s) found.`,\n data,\n warnings: issues.filter(i => i.severity === \"warning\").map(i => ({\n category: \"layout\" as const,\n message: i.issue,\n nodeId: i.nodeId,\n })),\n recommended_next: issues.length > 0\n ? [{ tool: \"set_auto_layout\", reason: \"Fix layout issues on specific frames\" }]\n : [{ tool: \"analyze_color_usage\", reason: \"Check color token coverage next\" }],\n });\n } catch (error) {\n return errorResult(\n \"connection_error\",\n `Analysis failed: ${error instanceof Error ? error.message : String(error)}`,\n { suggestion: \"Ensure Figma plugin is connected\", tool: \"join_room\" }\n );\n }\n }\n );\n\n // ─── analyze_component_health ───────────────────────────────────\n server.tool(\n \"analyze_component_health\",\n \"Check component system health: detached instances, unused components, and override consistency. Use to audit design system adherence. Follow with create_component or update_instance to fix issues.\",\n {\n nodeId: z.string().optional().describe(\"Scope to analyze (default: current page)\"),\n },\n { readOnlyHint: true },\n async ({ nodeId }) => {\n try {\n const [instances, components] = await Promise.all([\n sendCommand(\"scan_nodes_by_types\", {\n types: [\"INSTANCE\"],\n parentId: nodeId,\n }, 120000) as Promise<any[]>,\n sendCommand(\"get_local_components\") as Promise<any[]>,\n ]);\n\n const instanceList = Array.isArray(instances) ? instances : [];\n const componentList = Array.isArray(components) ? components : [];\n\n const issues: Array<{ nodeId: string; nodeName: string; issue: string }> = [];\n\n // Find detached-looking instances (no mainComponent reference)\n let detachedCount = 0;\n for (const inst of instanceList) {\n if (!inst.mainComponent && !inst.componentId) {\n detachedCount++;\n issues.push({\n nodeId: inst.id,\n nodeName: inst.name,\n issue: \"Instance appears detached from its main component\",\n });\n }\n }\n\n const data: ComponentHealthData = {\n totalComponents: componentList.length,\n totalInstances: instanceList.length,\n detachedCount,\n issues,\n };\n\n return standardResult({\n summary: `Components: ${componentList.length} defined, ${instanceList.length} instances, ${detachedCount} potentially detached`,\n data,\n recommended_next: [\n { tool: \"get_design_tokens\", reason: \"Review design system completeness\" },\n { tool: \"search_nodes\", reason: \"Find specific components by name\" },\n ],\n });\n } catch (error) {\n return errorResult(\n \"connection_error\",\n `Analysis failed: ${error instanceof Error ? error.message : String(error)}`,\n { suggestion: \"Ensure Figma plugin is connected\", tool: \"join_room\" }\n );\n }\n }\n );\n\n // ─── analyze_accessibility ──────────────────────────────────────\n server.tool(\n \"analyze_accessibility\",\n \"Check accessibility: text contrast ratios against backgrounds, touch target sizes. Use to ensure designs meet WCAG guidelines. Follow with update_node to fix contrast or sizing issues.\",\n {\n nodeId: z.string().optional().describe(\"Root node to analyze (default: current selection)\"),\n },\n { readOnlyHint: true },\n async ({ nodeId }) => {\n try {\n let targetId: string;\n if (nodeId) {\n targetId = nodeId;\n } else {\n const selection = await sendCommand(\"get_selection\") as any;\n if (!selection?.nodes?.length) return noSelectionError();\n targetId = selection.nodes[0].id;\n }\n\n const nodeInfo = await sendCommand(\"get_node_info\", { nodeId: targetId, depth: 8, maxNodes: 500 }) as any;\n if (!nodeInfo) {\n return errorResult(\"invalid_input\", `Node '${targetId}' not found`, { suggestion: \"Use search_nodes\", tool: \"search_nodes\" });\n }\n\n const issues: AccessibilityIssue[] = [];\n checkAccessibility(nodeInfo, null, issues);\n\n const data: AccessibilityData = {\n issueCount: issues.length,\n issues,\n };\n\n return standardResult({\n summary: `Accessibility: ${issues.length} issue(s) found`,\n data,\n warnings: issues.map(i => ({\n category: \"accessibility\" as const,\n message: i.issue,\n nodeId: i.nodeId,\n })),\n recommended_next: issues.length > 0\n ? [{ tool: \"update_node\", reason: \"Fix accessibility issues\" }]\n : [{ tool: \"validate_design_rules\", reason: \"Run full design validation\" }],\n });\n } catch (error) {\n return errorResult(\n \"connection_error\",\n `Analysis failed: ${error instanceof Error ? error.message : String(error)}`,\n { suggestion: \"Ensure Figma plugin is connected\", tool: \"join_room\" }\n );\n }\n }\n );\n\n // ─── diff_nodes ─────────────────────────────────────────────────\n const CHECKPOINT_KEY = \"relai.checkpoint\";\n server.tool(\n \"diff_nodes\",\n \"Compare two nodes and list their differences (fills, strokes, size, layout, etc.), or audit changes over time with checkpoints: checkpoint:\\\"save\\\" snapshots nodeIdA's key properties; checkpoint:\\\"compare\\\" later diffs the current state against that snapshot — useful before/after an editing session to show the designer exactly what changed.\",\n {\n nodeIdA: z.string().describe(\"First node ID (or the checkpoint target)\"),\n nodeIdB: z.string().optional().describe(\"Second node ID (omit when using checkpoint)\"),\n checkpoint: z.enum([\"save\", \"compare\"]).optional()\n .describe(\"save: snapshot nodeIdA now; compare: diff current vs saved snapshot\"),\n },\n { readOnlyHint: true },\n async ({ nodeIdA, nodeIdB, checkpoint }) => {\n try {\n if (checkpoint === \"save\") {\n const node = (await sendCommand(\"get_node_info\", { nodeId: nodeIdA, depth: 2 })) as any;\n if (!node) return errorResult(\"invalid_input\", `Node '${nodeIdA}' not found`, { suggestion: \"Check node ID\", tool: \"search_nodes\" });\n const summary = normalizeNode(node);\n await sendCommand(\"set_plugin_data\", {\n nodeId: nodeIdA,\n key: CHECKPOINT_KEY,\n value: JSON.stringify({ ts: Date.now(), name: node.name, summary }),\n });\n return standardResult({\n summary: `Checkpoint saved for '${node.name}' (${nodeIdA}). Run diff_nodes with checkpoint:\"compare\" after editing to see what changed.`,\n data: { nodeId: nodeIdA, saved: true },\n recommended_next: [],\n });\n }\n\n if (checkpoint === \"compare\") {\n const [node, stored] = await Promise.all([\n sendCommand(\"get_node_info\", { nodeId: nodeIdA, depth: 2 }) as Promise<any>,\n sendCommand(\"get_plugin_data\", { nodeId: nodeIdA, key: CHECKPOINT_KEY }) as Promise<any>,\n ]);\n if (!node) return errorResult(\"invalid_input\", `Node '${nodeIdA}' not found`, { suggestion: \"Check node ID\", tool: \"search_nodes\" });\n const raw = typeof stored === \"string\" ? stored : stored?.value;\n if (!raw) {\n return errorResult(\"invalid_input\", `No checkpoint saved on '${nodeIdA}'`, {\n suggestion: 'Save one first with checkpoint:\"save\"', tool: \"diff_nodes\",\n });\n }\n const saved = JSON.parse(raw);\n const before = saved.summary;\n const after = normalizeNode(node);\n\n const differences: NodeDiffField[] = [];\n if (before && after) {\n compareField(differences, \"type\", before.type, after.type);\n compareField(differences, \"fill\", before.fill, after.fill);\n compareField(differences, \"stroke\", before.stroke, after.stroke);\n compareField(differences, \"cornerRadius\", before.cornerRadius, after.cornerRadius);\n compareField(differences, \"opacity\", before.opacity, after.opacity);\n compareField(differences, \"width\", before.size?.width, after.size.width);\n compareField(differences, \"height\", before.size?.height, after.size.height);\n compareField(differences, \"layout.mode\", before.layout?.mode, after.layout?.mode);\n compareField(differences, \"layout.gap\", before.layout?.gap, after.layout?.gap);\n compareField(differences, \"layout.padding\", before.layout?.padding, after.layout?.padding);\n }\n const age = Math.round((Date.now() - (saved.ts ?? Date.now())) / 1000);\n return standardResult({\n summary: differences.length === 0\n ? `'${node.name}' is unchanged since the checkpoint ${age}s ago`\n : `${differences.length} propert${differences.length === 1 ? \"y\" : \"ies\"} changed on '${node.name}' since the checkpoint ${age}s ago`,\n data: {\n nodeId: nodeIdA,\n checkpointTs: saved.ts,\n identical: differences.length === 0,\n differences,\n },\n recommended_next: [],\n });\n }\n\n if (!nodeIdB) {\n return errorResult(\"invalid_input\", \"Provide nodeIdB, or use checkpoint:\\\"save\\\"/\\\"compare\\\" with nodeIdA alone\", {\n suggestion: \"Two-node diff needs both ids\", tool: \"diff_nodes\",\n });\n }\n\n const [nodeA, nodeB] = await Promise.all([\n sendCommand(\"get_node_info\", { nodeId: nodeIdA, depth: 2 }) as Promise<any>,\n sendCommand(\"get_node_info\", { nodeId: nodeIdB, depth: 2 }) as Promise<any>,\n ]);\n\n if (!nodeA) return errorResult(\"invalid_input\", `Node '${nodeIdA}' not found`, { suggestion: \"Check node ID\", tool: \"search_nodes\" });\n if (!nodeB) return errorResult(\"invalid_input\", `Node '${nodeIdB}' not found`, { suggestion: \"Check node ID\", tool: \"search_nodes\" });\n\n const summaryA = normalizeNode(nodeA);\n const summaryB = normalizeNode(nodeB);\n\n const differences: NodeDiffField[] = [];\n if (summaryA && summaryB) {\n compareField(differences, \"type\", summaryA.type, summaryB.type);\n compareField(differences, \"fill\", summaryA.fill, summaryB.fill);\n compareField(differences, \"stroke\", summaryA.stroke, summaryB.stroke);\n compareField(differences, \"cornerRadius\", summaryA.cornerRadius, summaryB.cornerRadius);\n compareField(differences, \"opacity\", summaryA.opacity, summaryB.opacity);\n compareField(differences, \"width\", summaryA.size.width, summaryB.size.width);\n compareField(differences, \"height\", summaryA.size.height, summaryB.size.height);\n compareField(differences, \"layout.mode\", summaryA.layout?.mode, summaryB.layout?.mode);\n compareField(differences, \"layout.gap\", summaryA.layout?.gap, summaryB.layout?.gap);\n compareField(differences, \"layout.padding\", summaryA.layout?.padding, summaryB.layout?.padding);\n }\n\n const data: DiffNodesData = {\n nodeA: { id: nodeIdA, name: nodeA.name },\n nodeB: { id: nodeIdB, name: nodeB.name },\n identical: differences.length === 0,\n differences,\n };\n\n return standardResult({\n summary: differences.length === 0\n ? `'${nodeA.name}' and '${nodeB.name}' are identical in key properties`\n : `${differences.length} difference(s) between '${nodeA.name}' and '${nodeB.name}'`,\n data,\n recommended_next: differences.length > 0\n ? [{ tool: \"update_node\", reason: \"Align properties between nodes\" }]\n : [],\n });\n } catch (error) {\n return errorResult(\n \"connection_error\",\n `Diff failed: ${error instanceof Error ? error.message : String(error)}`,\n { suggestion: \"Ensure Figma plugin is connected\", tool: \"join_room\" }\n );\n }\n }\n );\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────\n\nexport function collectColorIssues(\n node: any,\n boundVars: Record<string, unknown>,\n issues: ColorUsageIssue[],\n counters: { totalProps: number; boundCount: number }\n) {\n // Check fills (counted as one bindable property per node)\n if (node.fills?.length > 0) {\n const solidFills = node.fills.filter((f: any) => f.type === \"SOLID\" && f.visible !== false);\n if (solidFills.length > 0) {\n counters.totalProps++;\n const hasFillBinding = Object.keys(boundVars).some(k => k.startsWith(\"fills\"));\n if (hasFillBinding) {\n counters.boundCount++;\n } else {\n for (const fill of solidFills) {\n if (!fill.color) continue;\n const color = typeof fill.color === \"string\" ? fill.color : rgbaToHex({\n r: fill.color.r, g: fill.color.g, b: fill.color.b, a: fill.color.a ?? 1,\n });\n issues.push({\n nodeId: node.id,\n nodeName: node.name,\n property: \"fill\",\n color,\n });\n }\n }\n }\n }\n\n // Check strokes (counted as one bindable property per node)\n if (node.strokes?.length > 0) {\n const solidStrokes = node.strokes.filter((s: any) => s.type === \"SOLID\" && s.visible !== false);\n if (solidStrokes.length > 0) {\n counters.totalProps++;\n const hasStrokeBinding = Object.keys(boundVars).some(k => k.startsWith(\"strokes\"));\n if (hasStrokeBinding) {\n counters.boundCount++;\n } else {\n for (const stroke of solidStrokes) {\n if (!stroke.color) continue;\n const color = typeof stroke.color === \"string\" ? stroke.color : rgbaToHex({\n r: stroke.color.r, g: stroke.color.g, b: stroke.color.b, a: stroke.color.a ?? 1,\n });\n issues.push({\n nodeId: node.id,\n nodeName: node.name,\n property: \"stroke\",\n color,\n });\n }\n }\n }\n }\n}\n\nfunction collectFrames(node: any): any[] {\n const frames: any[] = [];\n if (node.type === \"FRAME\" || node.type === \"COMPONENT\" || node.type === \"COMPONENT_SET\") {\n frames.push(node);\n }\n if (node.children) {\n for (const child of node.children) {\n frames.push(...collectFrames(child));\n }\n }\n return frames;\n}\n\nfunction analyzeLayoutNode(node: any, issues: LayoutIssue[], _counters: { totalFrames: number; autoLayoutCount: number }) {\n if (node.type === \"FRAME\" || node.type === \"COMPONENT\") {\n if (!node.layoutMode || node.layoutMode === \"NONE\") {\n if (node.children?.length >= 2) {\n issues.push({\n nodeId: node.id,\n nodeName: node.name,\n issue: `Frame '${node.name}' has ${node.children.length} children but no auto-layout`,\n severity: \"warning\",\n suggestion: \"Add auto-layout with set_auto_layout for responsive behavior\",\n });\n }\n }\n }\n\n if (node.children) {\n for (const child of node.children) {\n analyzeLayoutNode(child, issues, _counters);\n }\n }\n}\n\nfunction checkAccessibility(node: any, parentBg: any, issues: AccessibilityIssue[]) {\n // Check touch target sizes for interactive elements\n if (node.type === \"INSTANCE\" || node.name?.toLowerCase().includes(\"button\")) {\n const w = node.width ?? node.absoluteBoundingBox?.width ?? 0;\n const h = node.height ?? node.absoluteBoundingBox?.height ?? 0;\n if ((w > 0 && w < 44) || (h > 0 && h < 44)) {\n issues.push({\n nodeId: node.id,\n nodeName: node.name,\n issue: `Touch target too small: ${Math.round(w)}×${Math.round(h)}px (minimum 44×44px)`,\n });\n }\n }\n\n if (node.type === \"TEXT\") {\n const fontSize = typeof node.fontSize === \"number\" ? node.fontSize : null;\n const fontWeight = typeof node.fontWeight === \"number\" ? node.fontWeight : 400;\n\n // Minimum readable size (common floor; WCAG has no hard px but <11 is trouble)\n if (fontSize !== null && fontSize < 11) {\n issues.push({\n nodeId: node.id,\n nodeName: node.name,\n issue: `Text size ${fontSize}px is below the 11px readability floor`,\n });\n }\n\n const textFill = node.fills?.find((f: any) => f.type === \"SOLID\" && f.visible !== false);\n if (textFill?.color && parentBg?.color) {\n if (parentBg.solid) {\n // WCAG 1.4.3: large text (≥24px, or ≥18.66px bold) needs 3:1; else 4.5:1.\n // Effective color accounts for fill and node opacity blended over the bg.\n const alpha =\n (textFill.opacity ?? 1) *\n (typeof node.opacity === \"number\" ? node.opacity : 1) *\n (textFill.color.a ?? 1);\n const effective = blendOver(textFill.color, parentBg.color, alpha);\n const isLarge =\n fontSize !== null && (fontSize >= 24 || (fontSize >= 18.66 && fontWeight >= 700));\n const required = isLarge ? 3 : 4.5;\n const ratio = calculateContrastRatio(effective, parentBg.color);\n if (ratio < required) {\n issues.push({\n nodeId: node.id,\n nodeName: node.name,\n issue: `Low contrast ratio: ${ratio.toFixed(1)}:1 (minimum ${required}:1 for ${isLarge ? \"large\" : \"body\"} text${alpha < 1 ? \", opacity included\" : \"\"})`,\n contrastRatio: Math.round(ratio * 10) / 10,\n requiredRatio: required,\n });\n }\n } else {\n // Text sits on an image/gradient — contrast can't be computed statically\n issues.push({\n nodeId: node.id,\n nodeName: node.name,\n issue: `Text sits on a ${parentBg.kind} background — contrast cannot be verified automatically; check manually or add a solid scrim`,\n });\n }\n }\n }\n\n // Track the nearest background for children: solid color when available,\n // otherwise remember that it's an image/gradient so contrast is flagged\n let bg = parentBg;\n if (node.type !== \"TEXT\" && node.fills?.length > 0) {\n const visible = node.fills.filter((f: any) => f.visible !== false);\n const solid = visible.find((f: any) => f.type === \"SOLID\");\n const nonSolid = visible.find((f: any) => f.type !== \"SOLID\");\n if (nonSolid) {\n const type = String(nonSolid.type ?? \"IMAGE\");\n bg = {\n color: solid?.color ?? { r: 0.5, g: 0.5, b: 0.5 },\n solid: false,\n kind: type.startsWith(\"GRADIENT\") ? \"gradient\" : type.toLowerCase(),\n };\n } else if (solid?.color) {\n bg = { color: solid.color, solid: true, kind: \"solid\" };\n }\n }\n\n if (node.children) {\n for (const child of node.children) {\n checkAccessibility(child, bg, issues);\n }\n }\n}\n\n// Alpha-composite fg over bg (both 0-1 RGB)\nfunction blendOver(fg: any, bg: any, alpha: number): { r: number; g: number; b: number } {\n const a = Math.max(0, Math.min(1, alpha));\n return {\n r: fg.r * a + bg.r * (1 - a),\n g: fg.g * a + bg.g * (1 - a),\n b: fg.b * a + bg.b * (1 - a),\n };\n}\n\nfunction calculateContrastRatio(fg: any, bg: any): number {\n const fgL = relativeLuminance(fg.r ?? 0, fg.g ?? 0, fg.b ?? 0);\n const bgL = relativeLuminance(bg.r ?? 0, bg.g ?? 0, bg.b ?? 0);\n const lighter = Math.max(fgL, bgL);\n const darker = Math.min(fgL, bgL);\n return (lighter + 0.05) / (darker + 0.05);\n}\n\nfunction relativeLuminance(r: number, g: number, b: number): number {\n // r, g, b are in 0-1 range (Figma format)\n const rL = r <= 0.03928 ? r / 12.92 : Math.pow((r + 0.055) / 1.055, 2.4);\n const gL = g <= 0.03928 ? g / 12.92 : Math.pow((g + 0.055) / 1.055, 2.4);\n const bL = b <= 0.03928 ? b / 12.92 : Math.pow((b + 0.055) / 1.055, 2.4);\n return 0.2126 * rL + 0.7152 * gL + 0.0722 * bL;\n}\n\nfunction compareField(diffs: NodeDiffField[], field: string, a: unknown, b: unknown) {\n if (a !== b) {\n diffs.push({ field, nodeA: a, nodeB: b });\n }\n}\n","// Aggregates the four analyze_design aspects into one weighted health score.\n// Pure so it can be unit-tested without a live plugin.\n\nexport interface HealthInputs {\n // null = that aspect's analysis was unavailable (excluded, weights renormalize)\n color: { tokenCoverage: number; unboundCount: number } | null;\n layout: { autoLayoutCoverage: number; issueCount: number } | null;\n components: { totalInstances: number; detachedCount: number } | null;\n accessibility: { issueCount: number } | null;\n}\n\nexport interface CategoryScore {\n category: \"color\" | \"layout\" | \"components\" | \"accessibility\";\n score: number; // 0-100\n weight: number;\n note: string;\n}\n\nexport interface HealthScore {\n score: number; // 0-100 weighted\n grade: \"A\" | \"B\" | \"C\" | \"D\";\n categories: CategoryScore[];\n}\n\nconst WEIGHTS = { color: 0.3, layout: 0.25, components: 0.2, accessibility: 0.25 };\n\nconst clamp = (n: number) => Math.max(0, Math.min(100, Math.round(n)));\n\nexport function computeHealthScore(inputs: HealthInputs): HealthScore {\n const categories: CategoryScore[] = [];\n\n if (inputs.color) {\n categories.push({\n category: \"color\",\n score: clamp(inputs.color.tokenCoverage * 100),\n weight: WEIGHTS.color,\n note: `${Math.round(inputs.color.tokenCoverage * 100)}% of color properties bound to tokens (${inputs.color.unboundCount} unbound)`,\n });\n }\n if (inputs.layout) {\n // Coverage sets the baseline; each concrete issue costs a little on top\n categories.push({\n category: \"layout\",\n score: clamp(inputs.layout.autoLayoutCoverage * 100 - inputs.layout.issueCount * 3),\n weight: WEIGHTS.layout,\n note: `${Math.round(inputs.layout.autoLayoutCoverage * 100)}% auto-layout coverage, ${inputs.layout.issueCount} issue(s)`,\n });\n }\n if (inputs.components) {\n const { totalInstances, detachedCount } = inputs.components;\n categories.push({\n category: \"components\",\n score: totalInstances > 0 ? clamp((1 - detachedCount / totalInstances) * 100) : 100,\n weight: WEIGHTS.components,\n note:\n totalInstances > 0\n ? `${detachedCount}/${totalInstances} instances look detached`\n : \"no instances in scope\",\n });\n }\n if (inputs.accessibility) {\n categories.push({\n category: \"accessibility\",\n score: clamp(100 - inputs.accessibility.issueCount * 8),\n weight: WEIGHTS.accessibility,\n note: `${inputs.accessibility.issueCount} issue(s) found`,\n });\n }\n\n const totalWeight = categories.reduce((s, c) => s + c.weight, 0);\n const score =\n totalWeight > 0\n ? clamp(categories.reduce((s, c) => s + c.score * c.weight, 0) / totalWeight)\n : 0;\n\n const grade = score >= 90 ? \"A\" : score >= 75 ? \"B\" : score >= 55 ? \"C\" : \"D\";\n return { score, grade, categories };\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { SendCommandFn } from \"../../tool-registry.js\";\nimport { standardResult } from \"../../semantic/response.js\";\nimport { errorResult, noSelectionError } from \"../../semantic/errors.js\";\nimport { normalizeNode, calculateTokenCoverage } from \"../../semantic/normalize.js\";\nimport type {\n VerifyChangesData,\n ValidateDesignRulesData,\n DesignRuleResult,\n} from \"@figma-relai/shared\";\n\nexport function register(server: McpServer, sendCommand: SendCommandFn): void {\n // ─── verify_changes ─────────────────────────────────────────────\n server.tool(\n \"verify_changes\",\n \"Verify that a node's current properties match expected values. Use after update_node, set_auto_layout, or batch_execute to confirm changes applied correctly. Returns match/mismatch for each checked field.\",\n {\n nodeId: z.string().describe(\"Node ID to verify\"),\n expected: z.record(z.string(), z.unknown()).describe(\"Expected property values, e.g. { fill: '#3B82F6', cornerRadius: 8 }\"),\n },\n { readOnlyHint: true },\n async ({ nodeId, expected }) => {\n try {\n const nodeInfo = await sendCommand(\"get_node_info\", { nodeId, depth: 2 }) as any;\n if (!nodeInfo) {\n return errorResult(\n \"invalid_input\",\n `Node '${nodeId}' not found — it may have been deleted`,\n { suggestion: \"Use search_nodes to find the node\", tool: \"search_nodes\" }\n );\n }\n\n const normalized = normalizeNode(nodeInfo);\n if (!normalized) {\n return errorResult(\n \"invalid_input\",\n `Could not normalize node '${nodeId}'`,\n { suggestion: \"Try get_node_details for raw data\", tool: \"get_node_details\", args: { nodeId } }\n );\n }\n\n const fields: VerifyChangesData[\"fields\"] = [];\n for (const [key, expectedValue] of Object.entries(expected)) {\n const actual = getNestedValue(normalized, nodeInfo, key);\n const match = deepEqual(actual, expectedValue);\n fields.push({ field: key, expected: expectedValue, actual, match });\n }\n\n const allMatch = fields.every(f => f.match);\n\n const data: VerifyChangesData = {\n nodeId,\n allMatch,\n fields,\n };\n\n return standardResult({\n summary: allMatch\n ? `All ${fields.length} checked properties match expected values`\n : `${fields.filter(f => !f.match).length} of ${fields.length} properties don't match expected values`,\n data,\n recommended_next: allMatch\n ? [{ tool: \"screenshot\", reason: \"Visually confirm the changes\" }]\n : [{ tool: \"update_node\", reason: \"Re-apply changes that didn't match\", args: { nodeId } }],\n });\n } catch (error) {\n return errorResult(\n \"connection_error\",\n `Verification failed: ${error instanceof Error ? error.message : String(error)}`,\n { suggestion: \"Ensure Figma plugin is connected\", tool: \"join_room\" }\n );\n }\n }\n );\n\n // ─── validate_design_rules ──────────────────────────────────────\n server.tool(\n \"validate_design_rules\",\n \"Run design quality rules on a node: token coverage, auto-layout usage, naming conventions, and accessibility basics. Use after modifications or during design audits. Returns pass/fail for each rule with fix suggestions.\",\n {\n nodeId: z.string().optional().describe(\"Root node to validate (default: current selection)\"),\n },\n { readOnlyHint: true },\n async ({ nodeId }) => {\n try {\n let targetId: string;\n if (nodeId) {\n targetId = nodeId;\n } else {\n const selection = await sendCommand(\"get_selection\") as any;\n if (!selection?.nodes?.length) return noSelectionError();\n targetId = selection.nodes[0].id;\n }\n\n const [nodeInfo, boundVars] = await Promise.all([\n sendCommand(\"get_node_info\", { nodeId: targetId, depth: 2 }) as Promise<any>,\n sendCommand(\"get_bound_variables\", { nodeId: targetId }).catch(() => null) as Promise<any>,\n ]);\n\n if (!nodeInfo) {\n return errorResult(\"invalid_input\", `Node '${targetId}' not found`, { suggestion: \"Use search_nodes\", tool: \"search_nodes\" });\n }\n\n const bv = boundVars?.boundVariables || {};\n const results: DesignRuleResult[] = [];\n\n // Rule 1: Token coverage\n const coverage = calculateTokenCoverage(nodeInfo, bv);\n results.push({\n rule: \"token_coverage\",\n passed: coverage >= 0.8,\n severity: coverage >= 0.5 ? \"warning\" : \"error\",\n message: `Token coverage: ${Math.round(coverage * 100)}% (target: 80%+)`,\n nodeId: targetId,\n fix: coverage < 0.8\n ? { tool: \"bind_tokens\", reason: \"Bind unbound properties to design tokens\", args: { nodeId: targetId } }\n : undefined,\n });\n\n // Rule 2: Auto-layout usage\n if (nodeInfo.type === \"FRAME\" || nodeInfo.type === \"COMPONENT\") {\n const hasAutoLayout = nodeInfo.layoutMode && nodeInfo.layoutMode !== \"NONE\";\n const hasChildren = nodeInfo.children?.length >= 2;\n results.push({\n rule: \"auto_layout\",\n passed: hasAutoLayout || !hasChildren,\n severity: \"warning\",\n message: hasAutoLayout\n ? `Auto-layout: ${nodeInfo.layoutMode}`\n : hasChildren\n ? `No auto-layout on frame with ${nodeInfo.children.length} children`\n : \"No children requiring auto-layout\",\n nodeId: targetId,\n fix: !hasAutoLayout && hasChildren\n ? { tool: \"set_auto_layout\", reason: \"Add auto-layout for responsive behavior\", args: { nodeId: targetId } }\n : undefined,\n });\n }\n\n // Rule 3: Naming convention (no default names)\n const hasDefaultName = /^(Frame|Rectangle|Ellipse|Group|Text|Vector|Line|Polygon|Star)\\s*\\d*$/.test(nodeInfo.name);\n results.push({\n rule: \"naming_convention\",\n passed: !hasDefaultName,\n severity: \"info\",\n message: hasDefaultName\n ? `'${nodeInfo.name}' uses a default Figma name — rename for clarity`\n : `Name '${nodeInfo.name}' looks intentional`,\n nodeId: targetId,\n fix: hasDefaultName\n ? { tool: \"update_node\", reason: \"Rename with a semantic name\", args: { nodeId: targetId } }\n : undefined,\n });\n\n // Rule 4: Touch target minimum size (for interactive elements)\n if (nodeInfo.type === \"INSTANCE\" || nodeInfo.name?.toLowerCase().includes(\"button\")) {\n const w = nodeInfo.width ?? 0;\n const h = nodeInfo.height ?? 0;\n const adequate = w >= 44 && h >= 44;\n results.push({\n rule: \"touch_target_size\",\n passed: adequate,\n severity: \"warning\",\n message: adequate\n ? `Touch target: ${Math.round(w)}×${Math.round(h)}px (OK)`\n : `Touch target: ${Math.round(w)}×${Math.round(h)}px (minimum 44×44px)`,\n nodeId: targetId,\n fix: !adequate\n ? { tool: \"update_node\", reason: \"Increase size to meet touch target minimum\", args: { nodeId: targetId } }\n : undefined,\n });\n }\n\n // Rule 5: Orphaned instances (main component deleted — the instance\n // survives on a detached internal copy and silently stops updating)\n try {\n const orph = await sendCommand(\"find_orphan_instances\", { nodeId: targetId }, 60000) as any;\n if (orph && typeof orph.scanned === \"number\") {\n const found: any[] = orph.orphans ?? [];\n results.push({\n rule: \"orphaned_instances\",\n passed: found.length === 0,\n severity: \"warning\",\n message: found.length\n ? `${found.length} instance(s) reference deleted components (of ${orph.scanned} scanned): ${found.slice(0, 3).map((o: any) => o.name).join(\", \")}${found.length > 3 ? \"…\" : \"\"}`\n : `No orphaned instances (${orph.scanned} scanned)`,\n nodeId: targetId,\n fix: found.length\n ? { tool: \"manage_components\", reason: \"Re-instantiate from a living component, or detach deliberately\", args: { action: \"list\" } }\n : undefined,\n });\n }\n } catch {\n // plugin build without the handler — rule silently absent\n }\n\n const passed = results.filter(r => r.passed).length;\n const failed = results.filter(r => !r.passed).length;\n\n const data: ValidateDesignRulesData = {\n rulesChecked: results.length,\n passed,\n failed,\n results,\n };\n\n return standardResult({\n summary: `Design validation: ${passed}/${results.length} rules passed, ${failed} failed`,\n data,\n recommended_next: failed > 0\n ? results.filter(r => !r.passed && r.fix).map(r => r.fix!).slice(0, 3)\n : [{ tool: \"screenshot\", reason: \"Visually confirm the design quality\" }],\n });\n } catch (error) {\n return errorResult(\n \"connection_error\",\n `Validation failed: ${error instanceof Error ? error.message : String(error)}`,\n { suggestion: \"Ensure Figma plugin is connected\", tool: \"join_room\" }\n );\n }\n }\n );\n\n // ─── verify_visual ──────────────────────────────────────────────\n server.tool(\n \"verify_visual\",\n \"The write→see→assert loop in one call: screenshots a node AND (optionally) checks expected property values. Returns the image plus structured pass/fail. Use after visual edits instead of separate screenshot + verify_changes calls.\",\n {\n nodeId: z.string().describe(\"Node to verify\"),\n expected: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\"Expected property values, e.g. { cornerRadius: 8, width: 320 }\"),\n },\n { readOnlyHint: true },\n async ({ nodeId, expected }) => {\n try {\n const [shot, nodeInfo] = await Promise.all([\n sendCommand(\"get_screenshot\", { nodeId }, 60000) as Promise<{\n imageData?: string;\n mimeType?: string;\n }>,\n expected\n ? (sendCommand(\"get_node_info\", { nodeId, depth: 2 }) as Promise<unknown>)\n : Promise.resolve(null),\n ]);\n\n const content: Array<\n | { type: \"image\"; data: string; mimeType: string }\n | { type: \"text\"; text: string }\n > = [];\n if (shot?.imageData) {\n content.push({\n type: \"image\",\n data: shot.imageData,\n mimeType: shot.mimeType ?? \"image/png\",\n });\n }\n\n if (expected && nodeInfo) {\n const normalized = normalizeNode(nodeInfo) ?? {};\n const fields = Object.entries(expected).map(([key, expectedValue]) => {\n const actual = getNestedValue(normalized, nodeInfo, key);\n return { field: key, expected: expectedValue, actual, match: deepEqual(actual, expectedValue) };\n });\n const failing = fields.filter((f) => !f.match);\n content.push({\n type: \"text\",\n text: JSON.stringify(\n {\n summary:\n failing.length === 0\n ? `All ${fields.length} checked properties match — confirm the screenshot looks right`\n : `${failing.length}/${fields.length} properties do NOT match`,\n fields,\n },\n null,\n 2\n ),\n });\n } else if (!shot?.imageData) {\n content.push({ type: \"text\", text: \"Screenshot unavailable for this node.\" });\n }\n\n return { content };\n } catch (error) {\n return errorResult(\n \"connection_error\",\n `Visual verification failed: ${error instanceof Error ? error.message : String(error)}`,\n { suggestion: \"Ensure Figma plugin is connected\", tool: \"join_room\" }\n );\n }\n }\n );\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────\n\nfunction getNestedValue(normalized: any, raw: any, key: string): unknown {\n // Check normalized summary first\n if (key in normalized) return normalized[key];\n // Check common nested paths\n if (key === \"width\") return normalized.size?.width;\n if (key === \"height\") return normalized.size?.height;\n if (key === \"x\") return normalized.position?.x;\n if (key === \"y\") return normalized.position?.y;\n // Fallback to raw node data\n return raw[key];\n}\n\nfunction deepEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n if (a == null || b == null) return false;\n if (typeof a === \"number\" && typeof b === \"number\") {\n return Math.abs(a - b) < 0.01; // Float tolerance\n }\n if (typeof a === \"string\" && typeof b === \"string\") {\n return a.toLowerCase() === b.toLowerCase();\n }\n return JSON.stringify(a) === JSON.stringify(b);\n}\n","# Figma Plugin API Cheat Sheet — for `execute_figma`\n\nRules and patterns for writing code that runs in the plugin sandbox. Work in small incremental scripts and `screenshot` between steps.\n\n## Non-negotiable rules (dynamic-page mode)\n\n- **Node lookup is async**: `await figma.getNodeByIdAsync(id)` — `getNodeById` throws in this plugin.\n- **Load pages before traversal**: `await page.loadAsync()` before `page.findAll(...)` on a non-current page; `figma.currentPage` is always loaded.\n- **Load fonts before ANY text edit**: `await figma.loadFontAsync(textNode.fontName)` — if `fontName === figma.mixed`, load every range: `for (const f of textNode.getRangeAllFontNames(0, textNode.characters.length)) await figma.loadFontAsync(f)`.\n- **`figma.mixed` is a Symbol**: properties like `fontSize`, `cornerRadius`, `fills` return it when values differ across ranges/children. Check `=== figma.mixed` before using; never JSON-serialize it.\n\n## Common patterns\n\n```js\n// Selection\nconst sel = figma.currentPage.selection; // read\nfigma.currentPage.selection = [node]; // write\n\n// Create + place\nconst frame = figma.createFrame();\nframe.resize(320, 200); // width/height are read-only; use resize()\nparent.appendChild(frame); // default parent is currentPage\n\n// Fills/strokes are ARRAYS and must be reassigned wholesale\nnode.fills = [{ type: \"SOLID\", color: { r: 1, g: 0.5, b: 0 } }]; // rgb 0-1, no alpha key — use opacity\nconst fills = JSON.parse(JSON.stringify(node.fills)); // clone before mutating\nfills[0].color.r = 0; node.fills = fills;\n\n// Auto-layout: set layoutMode FIRST, then padding/spacing/align\nframe.layoutMode = \"VERTICAL\";\nframe.itemSpacing = 8; frame.paddingTop = 16;\nchild.layoutSizingHorizontal = \"FILL\"; // requires PARENT with auto-layout\n\n// Components\nconst comp = await figma.importComponentByKeyAsync(key); // team library\nconst inst = comp.createInstance();\ninst.setProperties({ Variant: \"Primary\" }); // throws on unknown property names\n\n// Variables\nconst collections = await figma.variables.getLocalVariableCollectionsAsync();\nconst v = figma.variables.createVariable(\"name\", collection, \"COLOR\");\nv.setValueForMode(modeId, { r: 0, g: 0, b: 0 });\nnode.setBoundVariable(\"fills\", v); // binding paint needs figma.variables.setBoundVariableForPaint on the paint object for fills in older APIs — prefer setBoundVariable where available\n\n// Export (returns Uint8Array)\nconst bytes = await node.exportAsync({ format: \"PNG\", constraint: { type: \"SCALE\", value: 2 } });\n```\n\n## `relai.*` helpers — the shortest path is the correct one\n\nAlongside `figma`, scripts get a `relai` object whose helpers are immune to the pitfalls below. Prefer them:\n\n```js\nawait relai.text(parent, \"Hello\", { font: {family:\"IBM Plex Mono\", style:\"Regular\"}, size: 14, color: {r:0,g:0,b:0} });\n // loads the font BEFORE writing characters\nconst card = relai.autoLayout(\"VERTICAL\", { name: \"Card\", itemSpacing: 8 });\n // auto-layout frame, both axes hugging\nrelai.set(node, { layoutMode: \"HORIZONTAL\", width: 320, opacity: 0.9 });\n // layoutMode applied first; width/height via resize()\nrelai.hug(node); // HUG that sticks — call after appending children\nrelai.focusRing(button); // clipsContent + double spread shadows that render\nconst page = await relai.page(p => p.children.some(c => c.name === \"Button\"));\n // find pages by CONTENT — names get renamed\nconst titles = relai.query('FRAME[name^=Card] > TEXT');\n // CSS-like search on the current page; relai.query(node, sel) scopes to a subtree.\n // Supported: TYPE, *, [name=] [name*=] [name^=] [name$=], descendant, >, comma.\n // NOT supported: pseudo-classes, dot-paths, sibling combinators — use findAll.\nrelai.placeholder(section); // construction veil so the designer sees work-in-progress\nrelai.placeholder(section, false); // ALWAYS remove when the section is done\n```\n\nTwo important facts: **scripts are NOT atomic** — on error, changes made before the throw persist, so keep scripts small and clean up after failures; and results may carry a `warnings` array for silent mistakes the lint catches on relai-created nodes and any node ids you return (e.g. spread shadows on a non-clipping frame). Convention: **return every created/mutated node id** (`return { createdNodeIds: [...] }`) — it powers both follow-up calls and the lint.\n\n## Pitfalls that throw (or silently do the wrong thing)\n\nWhen one of these throws inside `execute_figma`, the error already carries the remedy as a `Hint:` — this list is generated from the same registry (`packages/shared/src/pitfalls.ts`).\n\n<!-- PITFALLS:START -->\n- **Editing text without loading its font throws** (`unloaded font`). `await figma.loadFontAsync(textNode.fontName)` first; new TextNodes default to Inter Regular; when `fontName === figma.mixed`, load every font from `getRangeAllFontNames()`.\n- **`getNodeById` throws in dynamic-page mode** — always `await figma.getNodeByIdAsync(id)`.\n- **Traversing a non-current page throws until you `await page.loadAsync()`** — `figma.currentPage` is always loaded, other pages are not.\n- **`layoutSizingHorizontal/Vertical` throw without auto-layout** — FILL requires the parent to have a `layoutMode`, HUG requires it on the node itself.\n- **`createPage()` throws on the free plan once a file has 3 pages** — reuse an existing page instead.\n- **`width`/`height` are read-only** — use `node.resize(w, h)`.\n- **`figma.mixed` is a Symbol** returned by `fontSize`, `cornerRadius`, `fills` etc. when values differ across ranges/children — check `=== figma.mixed` before use; never JSON-serialize it.\n- **Exact-name lookups are fragile** — designers rename pages and layers freely; locate nodes by type/content instead of `name ===`.\n- **Stale node ids throw `does not exist`** — nodes get deleted while you work; re-read before editing and check `node.removed`.\n- **Nodes are non-extensible** — `node.myCustomProp = x` throws `object is not extensible`; use `setPluginData` or return the data instead.\n- **Shadow `spread` renders only on shapes or frames with `clipsContent: true`** — a focus ring built from spread shadows is invisible on a non-clipping frame/component.\n- **`resize()` on an auto-layout frame silently pins that axis to FIXED**, overriding `primaryAxisSizingMode: \"AUTO\"`. Append children first, then set `layoutSizingHorizontal = \"HUG\"`; use `resize` only for the fixed cross-axis.\n- **Per-corner radius** (`topLeftRadius` …) only exists on RectangleCornerMixin nodes (rectangles, frames, components) — polygons, stars and lines throw.\n- **Instance children can't be added or removed** — detach first, or edit the main component.\n- **Figma's slot feature (Convert to slot, ⇧⌘S) has no Plugin API** — no createSlot/convertToSlot exists (verified against typings 1.123 and at runtime, 2026-07). Scaffold a frame named \"Slot\", select it for the designer (navigate select), and let them press the shortcut.\n- **A converted SLOT node stops hugging** — after the designer converts a frame to a slot it carries its own fixed size. Re-assert `layoutSizingVertical = \"HUG\"` (and the intended horizontal mode) on the SLOT node afterwards; the API can still edit its layout props.\n- **Variantizing can silently pin the hug axis to FIXED** — observed after clone → counterAxisSizingMode/width-variable changes → combineAsVariants: the variants' `primaryAxisSizingMode` ended up FIXED though the source hugged. Always verify sizing modes on every variant after combineAsVariants and re-assert `\"AUTO\"`.\n<!-- PITFALLS:END -->\n\nAlso: `resize(w, h)` throws on `w <= 0 || h <= 0`; `layoutWrap = \"WRAP\"` is HORIZONTAL-only, `counterAxisAlignItems = \"BASELINE\"` too; writing to `locked` nodes is allowed by the API but surprises designers — check first.\n\n## Return values\n\nReturn JSON-serializable data (the bridge summarizes nodes automatically and truncates >50k chars). Prefer returning `{ id, name, type }` summaries over whole nodes. `console.log` is captured and returned in `logs`.\n\n---\n\n*Tool parameter contracts are deliberately not duplicated in this document — every tool is self-describing over MCP, and `npx figma-relai docs <tool>` (or the generated `docs/manifest.json`) is the always-current reference.*\n","# Design Tokens Strategy — 4-Tier Token Architecture\n\n## Token Hierarchy\n\n### Tier 1 — Core (static)\nRaw values. Never referenced directly by components.\n- Naming: `color-static/{hue}/{shade}`, `spacing-static/{value}`\n- Examples: `color-static/slate/50`, `color-static/rose/500`\n- Single mode: Value\n- hiddenFromPublishing: true\n\n### Tier 1 — Core (dynamic)\nReferences static tokens. Handles Light/Dark inversion.\n- Naming: `color-dynamic/{hue}/{shade}`\n- Light mode: shade 50 → static/50, shade 900 → static/900\n- Dark mode: shade 50 → static/900, shade 900 → static/50 (inverted)\n- 2 modes: Light / Dark\n- hiddenFromPublishing: true\n\n### Tier 2 — Themes\nSemantic tokens. Define brand personality.\n- Naming: `color/{role}/{variant}`, `typography/{style}/{property}`, `border/{type}/{size}`\n- Color roles: background, content, border, icon\n- Color variants: surface-page, surface-default, surface-subtle, surface-knockout, disabled, utility/{status}/{emphasis|subtle}\n- Typography: headline-{lg|md|sm}, title-{lg|md}, body-{lg|md|sm}[-bold], label-{lg|md|sm}, code-{md|sm}[-bold]\n- Each typography style has: font-family, font-weight, font-size, letter-spacing, line-height\n- Modes: one per brand (e.g., Brand A, Brand B)\n- description: required — explain purpose and usage constraints\n- scopes: set appropriately (TEXT_FILL for content, STROKE_COLOR for border, FRAME_FILL for background, etc.)\n\n### Tier 3 — Components\nComponent-specific tokens. Reference Tier 2 or dynamic Tier 1.\n- Naming: `{component}/color/{role}/{state}`, `{component}/size/{variant}`\n- States: default, hover, pressed, disabled, selected, selected-hover, selected-pressed, selected-disabled\n- Sizes: sm, md, lg\n- Examples: `button/color/background/default`, `button/size/md`, `navigation/color/content/selected`\n- Modes: same as Tier 2 (one per brand)\n- Not every component needs Tier 3 — only when reuse or shared decision-making justifies it\n\n## Key Rules\n- Components MUST reference tokens only — never raw hex/px values\n- Tier 1 is internal plumbing — never expose to consumers\n- Adding a new brand = adding a mode to Tier 2 and Tier 3 collections\n- Light/Dark switching is handled entirely in Tier 1 dynamic — no brand-level light/dark logic needed\n\n## Workflow\n1. `get_design_tokens` → understand existing collections and modes\n2. `manage_variables` (list) with collectionId → inspect current tokens\n3. `manage_variables` (create_collection) → new collection with modes\n4. `manage_variables` (create) → define tokens with values per mode\n5. `manage_variables` (bind) → connect tokens to node properties\n6. `manage_variables` (set_scopes) → restrict UI picker visibility\n7. `manage_variables` (set_code_syntax) → set Dev Mode code references\n\n## Verification\n- `analyze_design` (aspect: color) → find unbound colors (token coverage)\n- `validate_design_rules` → check token_coverage rule\n- `get_node_data` (detail: variables) on key nodes → confirm bindings are correct\n\n---\n\n*Tool parameter contracts are deliberately not duplicated in this document — every tool is self-describing over MCP, and `npx figma-relai docs <tool>` (or the generated `docs/manifest.json`) is the always-current reference.*\n","# Component Architecture — Component Conventions\n\n## Token-First Principle\nEvery visual property must reference a token. No raw values in components.\n- Colors → Tier 2 semantic tokens or Tier 3 component tokens\n- Sizes (height, spacing) → Tier 2 or Tier 3 size tokens\n- Typography → Tier 2 typography tokens\n- Border radius/width → Tier 2 border tokens\n\n## Tier 3 Token Pattern\nWhen a component needs brand-differentiated values:\n\n`{component}/color/{role}/{state}`\n- Roles: background, border, content\n- States: default, hover, pressed, disabled\n- Selected states: selected, selected-hover, selected-pressed, selected-disabled\n- Variants: primary, ai, critical, ghost (prefix before role)\n\nExample — Button tokens:\n- `button/color/background/default` → neutral button bg\n- `button/primary/color/background/hover` → primary variant hover\n- `button/size/sm` / `button/size/md` / `button/size/lg`\n\n## State Management\nStandard interactive states:\n- default → hover → pressed → disabled (always present)\n- selected → selected-hover → selected-pressed → selected-disabled (for toggleable elements)\n\n## Size Variants\nUse sm / md / lg consistently. Define as Tier 3 FLOAT tokens when brand-differentiated.\n- `{component}/size/sm`, `{component}/size/md`, `{component}/size/lg`\n\n## Component Structure\n1. Use auto-layout (VERTICAL or HORIZONTAL) for all containers\n2. Use HUG for content-driven sizes, FILL for responsive elements\n3. Use component properties for configurable aspects:\n - BOOLEAN: toggle visibility (icons, labels)\n - INSTANCE_SWAP: swap nested components\n - VARIANT: select between variant sets\n - TEXT: configurable text content\n\n## Workflow\n1. `get_selection_context` → understand current component structure\n2. `manage_components` (list) → check existing components\n3. Design the component with auto-layout\n4. Create variants for states using `manage_components` (create_set)\n5. `manage_variables` (bind) → attach Tier 2/3 tokens to all visual properties\n6. `manage_components` (set_props) → configure instance properties\n\n## Verification\n- `analyze_design` (aspect: components) → find detached instances, unused components\n- `verify_changes` → confirm properties match expected values\n- `get_node_data` (detail: variables) → ensure all fills/strokes are token-bound\n\n---\n\n*Tool parameter contracts are deliberately not duplicated in this document — every tool is self-describing over MCP, and `npx figma-relai docs <tool>` (or the generated `docs/manifest.json`) is the always-current reference.*\n","# Design Audit Strategy\n\n## Phase 1: Overview\n1. `get_document_overview` → pages, component/style/variable counts\n2. `get_design_tokens` → token system structure (collections, modes, coverage)\n\n## Phase 2: Color & Token Audit\n1. `analyze_design` (aspect: color) → find colors not backed by variables\n2. `get_node_data` (detail: variables) on key nodes → verify correct tier references\n3. Check: components should reference Tier 2/3 tokens, never Tier 1 or raw values\n\n## Phase 3: Layout Quality\n1. `analyze_design` (aspect: layout) → detect missing auto-layout, inconsistent spacing\n2. Check: all containers should use auto-layout (not absolute positioning)\n3. Check: spacing should use token values, not arbitrary px\n\n## Phase 4: Component Health\n1. `analyze_design` (aspect: components) → detached instances, unused components\n2. `manage_components` (list) → review component inventory\n3. Check: all instances should be connected to their main component\n\n## Phase 5: Accessibility\n1. `analyze_design` (aspect: accessibility) → contrast ratios, touch target sizes\n2. Check: minimum contrast 4.5:1 for text, 3:1 for large text\n3. Check: touch targets ≥ 44×44px\n\n## Phase 6: Comprehensive Validation\n1. `validate_design_rules` → runs all checks in one pass:\n - token_coverage: % of nodes with variable bindings\n - auto_layout: % of frames using auto-layout\n - naming_convention: layer naming quality\n - touch_target_size: minimum size compliance\n\n## Reporting\n- `screenshot` before and after fixes\n- `annotate` (set) / `annotate` (set_multiple) to flag issues directly in the design\n- Summarize findings by severity (critical → warning → info)\n\n---\n\n*Tool parameter contracts are deliberately not duplicated in this document — every tool is self-describing over MCP, and `npx figma-relai docs <tool>` (or the generated `docs/manifest.json`) is the always-current reference.*\n","# Token Audit — Token Hierarchy Compliance Check\n\n## Purpose\nVerify that a design correctly uses the 4-tier token hierarchy:\n- No raw color/size values (everything should be token-bound)\n- Correct tier references (components → Tier 2/3, never Tier 1 directly)\n- Consistent scope usage\n\n## Audit Process\n\n### Step 1: Scope the Audit\n- `get_selection_context` → identify the area to audit\n- Or `get_document_overview` → audit the full document\n\n### Step 2: Color Token Coverage\n- `analyze_design` (aspect: color) → find all colors and whether they're token-bound\n- Flag any raw hex values not backed by variables\n\n### Step 3: Variable Binding Check\n- `get_node_data` (detail: variables) on key nodes → check what's bound\n- For each binding, verify the variable comes from the correct tier:\n - ✅ Component referencing Tier 2 (e.g., `color/content/default`)\n - ✅ Component referencing Tier 3 (e.g., `button/color/background/default`)\n - ❌ Component referencing Tier 1 (e.g., `color-static/slate/500`)\n - ❌ Component referencing Tier 1 dynamic (e.g., `color-dynamic/slate/500`)\n\n### Step 4: Scope Validation\n- `manage_variables` (list) → check that scopes are set correctly:\n - Color content tokens → TEXT_FILL\n - Color background tokens → FRAME_FILL, SHAPE_FILL\n - Color border tokens → STROKE_COLOR\n - Size tokens → WIDTH_HEIGHT\n - Border radius → CORNER_RADIUS\n - Border width → STROKE_FLOAT\n\n### Step 5: Comprehensive Check\n- `validate_design_rules` → run all design rules at once\n\n## Output Format\nReport findings as:\n- **Coverage**: X% of nodes have token bindings\n- **Tier violations**: list of nodes referencing wrong tier\n- **Raw values**: list of unbound colors/sizes with suggested token mappings\n- **Scope issues**: variables with missing or incorrect scopes\n\n---\n\n*Tool parameter contracts are deliberately not duplicated in this document — every tool is self-describing over MCP, and `npx figma-relai docs <tool>` (or the generated `docs/manifest.json`) is the always-current reference.*\n","# Component Specification Generator\n\n## Purpose\nGenerate a structured specification document for a component, covering its properties, variants, token bindings, and states.\n\n## Process\n\n### Step 1: Identify the Component\n- `get_selection_context` → read the selected component/instance\n- Or `search_nodes` by name to find it\n\n### Step 2: Extract Properties\n- `manage_components` (get_props) → list all configurable properties (VARIANT, BOOLEAN, INSTANCE_SWAP, TEXT)\n- `get_node_details` → full node structure with children summary\n\n### Step 3: Token Bindings\n- `get_node_data` (detail: variables) → list all token bindings on the component and its children\n- `manage_variables` (list) → resolve variable names, descriptions, scopes, codeSyntax\n- Map bindings to the 4-tier token structure\n\n### Step 4: Visual Reference\n- `screenshot` → capture the component in its default state\n- If variants exist, capture key states (default, hover, disabled, etc.)\n\n### Step 5: Generate Spec\n\nOutput format:\n\n#### {Component Name}\n**Description**: (from context or user input)\n\n**Properties**\n| Name | Type | Values | Default |\n|------|------|--------|---------|\n\n**Token Bindings**\n| Property | Token | Tier | Value (default mode) |\n|----------|-------|------|---------------------|\n\n**States**\n| State | Visual Changes |\n|-------|---------------|\n\n**Size Variants**\n| Size | Height | Token |\n|------|--------|-------|\n\n## Tips\n- For components from a library (remote: true), some properties may be read-only\n- Use `manage_components` (get_overrides) to see what's been customized on instances\n- Include codeSyntax values for developer handoff\n\n---\n\n*Tool parameter contracts are deliberately not duplicated in this document — every tool is self-describing over MCP, and `npx figma-relai docs <tool>` (or the generated `docs/manifest.json`) is the always-current reference.*\n","# Comment-driven tasks\n\nDesigners leave requests as **Figma comments**; you pick them up, do the work, and reply on the thread. This turns Relai into an async collaborator without the designer ever leaving Figma — comments are their native input surface.\n\n## Honest model\n\nThis is **polling, not a live feed**. An MCP server only acts when called, so requests are noticed when you check — at the start of a session, when the user says \"check the comments\", or on a loop the user runs in their own client. Say so if the user expects real-time pickup.\n\nRequires `FIGMA_TOKEN` (personal access token with comment scopes). A free-plan token works on the user's own files.\n\n## The loop\n\n1. **Scan** — `manage_comments` `action:\"list\"` with `unresolved:true`, plus `since:<checkedAt from the previous scan>` after the first pass. Keep the returned `checkedAt` as the next cursor.\n2. **Select** — treat a comment as a task when it reads as an instruction (\"make this...\", \"fix...\", \"@relai ...\"). Skip chatter between humans and threads you already replied to (your replies carry your token account's handle).\n3. **Anchor** — pinned comments carry a `nodeId`. Start there: `get_node_details` / `screenshot` for context. Unpinned comments apply to the file broadly; ask before guessing a target.\n4. **Claim** — reply on the thread *before* working: `action:\"reply\"` with a one-liner like `🤖 On it — <what you understood>`. This prevents double-work across sessions and tells the designer they were heard.\n5. **Execute** — normal Relai flow: design-system first, verify with `verify_visual` / `screenshot`.\n6. **Report back** — reply on the same thread with what changed and the node ids touched, e.g. `🤖 Done: CTA restyled to primary/600, radius token applied (2 nodes). Reply here if it's off.` The REST API cannot mark threads resolved — the designer resolves it, which doubles as their sign-off.\n\n## One-shot phrasing for users\n\nUsers can drive the whole loop with a single ask: *\"Check the file's comments and handle anything addressed to you, then report back on each thread.\"* For a standing loop, they re-issue that ask periodically (or wire it to their client's scheduler if it has one).\n\n---\n\n*Tool parameter contracts are deliberately not duplicated in this document — every tool is self-describing over MCP, and `npx figma-relai docs <tool>` (or the generated `docs/manifest.json`) is the always-current reference.*\n","# Design-system-first building\n\nThe difference between \"AI slop\" and work a design team accepts is almost always this: **slop draws new shapes; good work reuses the file's own system**. Before building any UI in a file that has one, wire yourself to it.\n\n## The sequence\n\n1. **`get_design_system`** — one call, cached per session. Read what exists: components (sorted by usage — high-usage items are the file's vocabulary), variable collections, styles, and the remote items the file already consumes. If the team's library lives in another file and `FIGMA_TOKEN` is set, pass `libraryFileUrl` for the full catalog.\n2. **`manage_conventions` (get)** — if the file carries conventions, they outrank your defaults. (`get_document_overview` includes them automatically.)\n3. **Compose from instances** — `manage_components` `action:\"instantiate\"` with the component key (works for local AND enabled-library keys; remote keys import automatically). Set variants/text via `set_props`. Only draw raw shapes for genuinely new elements.\n4. **Bind, don't hardcode** — colors/spacing/radius come from the file's variables (`manage_variables` `action:\"bind\"`, or variable fields in `set_properties`). If you must hardcode during exploration, run `analyze_design aspect:\"tokens\"` afterward and fix with `manage_variables action:\"tokenize\" fix:true`.\n5. **Verify like a designer** — `screenshot` / `verify_visual` after each increment, not at the end.\n\n## When the file has no system\n\nDon't invent variables for a one-off request. But if the work IS system-shaped (a palette, a type scale, components), build variables first, then styles/components on top — and offer to record naming decisions in `manage_conventions`.\n\n## Signals you're drifting\n\n- You drew a rectangle that looks like an existing Button/Card/Badge → replace it with an instance.\n- A hex value appears in your code that `get_design_system` lists as a variable → bind instead.\n- You renamed or restructured library instances the designer didn't ask about → undo; instances belong to their component.\n\n---\n\n*Tool parameter contracts are deliberately not duplicated in this document — every tool is self-describing over MCP, and `npx figma-relai docs <tool>` (or the generated `docs/manifest.json`) is the always-current reference.*\n","# Janitorial cleanup\n\nThe chores designers postpone for months — layer renaming, token drift, spacing normalization — are where an agent earns trust fastest. These jobs are big, mechanical, and easy to verify. Do them conservatively and loudly.\n\n## Ground rules\n\n- **Preview before bulk.** Use `dryRun:true` on `batch_execute` / `set_properties`, or report findings first (`analyze_design`), and tell the designer the scale (\"about 140 renames on this page — go?\"). If the plugin's approval gate is on, big writes will ask them anyway.\n- **Scope tightly.** Work page by page (or within the designer's selection). Never sweep the whole file unasked.\n- **Never rename or restyle library instances' internals** — only top-level frames/groups the team owns.\n\n## Recipes\n\n### Rename layers by content\n`Frame 427` tells nobody anything. Walk the target scope with `execute_figma` + `relai.query`, and derive names:\n- A frame whose only text child says \"Submit\" → `Button/Submit` (match the file's existing naming pattern from `get_design_system`, don't invent one).\n- Text nodes → their content, truncated (`Heading: Pricing plans`).\n- Skip nodes that already have deliberate names (anything not matching `/^(Frame|Group|Rectangle|Ellipse|Vector|Line) \\d+$/`).\nReturn the rename list; apply via one `batch_execute` of `rename_node` commands.\n\n### Tokenize hardcoded values\n`analyze_design aspect:\"tokens\"` finds hardcoded colors/numbers that visually match existing variables; `manage_variables action:\"tokenize\" fix:true` binds them in one pass. Report anything close-but-not-matching (deltaE just over tolerance) instead of silently snapping it.\n\n### Normalize spacing\nIn auto-layout scopes, collect `itemSpacing`/padding values; flag off-scale values (not on the file's 4/8pt grid or spacing variables) and propose the nearest on-scale value. Apply only after the designer confirms the mapping.\n\n### Sweep detached instances\n`analyze_design aspect:\"components\"` lists likely-detached instances. Offer to re-link obvious ones (matching component still exists) and just report the rest — re-attaching wrong is worse than detached.\n\n## Report format\n\nEnd with counts and jump-points: what changed, what was skipped and why, node ids for spot-checking (the designer can click entries in the plugin feed).\n\n---\n\n*Tool parameter contracts are deliberately not duplicated in this document — every tool is self-describing over MCP, and `npx figma-relai docs <tool>` (or the generated `docs/manifest.json`) is the always-current reference.*\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\n\n// Skill documents are inlined into the bundle at build time (tsup .md loader),\n// so they ship with the npm package and need no filesystem access at runtime.\nimport figmaPluginApi from \"../../../docs/skills/figma-plugin-api.md\";\nimport designTokensStrategy from \"../../../docs/skills/design-tokens-strategy.md\";\nimport componentArchitecture from \"../../../docs/skills/component-architecture-strategy.md\";\nimport designAuditStrategy from \"../../../docs/skills/design-audit-strategy.md\";\nimport tokenAudit from \"../../../docs/skills/token-audit.md\";\nimport componentSpec from \"../../../docs/skills/component-spec.md\";\nimport commentDrivenTasks from \"../../../docs/skills/comment-driven-tasks.md\";\nimport designSystemFirst from \"../../../docs/skills/design-system-first.md\";\nimport janitorialCleanup from \"../../../docs/skills/janitorial-cleanup.md\";\n\nconst SKILLS: Array<[name: string, description: string, text: string]> = [\n [\n \"figma-plugin-api\",\n \"Cheat sheet for writing execute_figma code: dynamic-page rules, font loading, auto-layout pitfalls, common patterns. Load before non-trivial execute_figma work.\",\n figmaPluginApi,\n ],\n [\n \"design-tokens-strategy\",\n \"4-tier design-token architecture: naming, mode design, tier reference rules. Load before creating or restructuring variables.\",\n designTokensStrategy,\n ],\n [\n \"component-architecture-strategy\",\n \"Component conventions: token-first properties, state handling, size variants, variant naming. Load before building components.\",\n componentArchitecture,\n ],\n [\n \"design-audit-strategy\",\n \"End-to-end design audit workflow: overview → tokens → per-aspect analysis → report.\",\n designAuditStrategy,\n ],\n [\n \"token-audit\",\n \"Token-compliance check: find raw values, tier violations, scope issues, unbound properties.\",\n tokenAudit,\n ],\n [\n \"component-spec\",\n \"Generate a structured component specification: properties, variants, token bindings, state matrix.\",\n componentSpec,\n ],\n [\n \"comment-driven-tasks\",\n \"Async collaboration via Figma comments: poll unresolved threads, claim, execute, report back on-thread. Load when asked to 'handle the comments' or work comment-driven.\",\n commentDrivenTasks,\n ],\n [\n \"design-system-first\",\n \"Build UI from the file's own system: inventory → conventions → instantiate components → bind variables → verify. Load before building screens in any file that has a design system.\",\n designSystemFirst,\n ],\n [\n \"janitorial-cleanup\",\n \"Bulk cleanup recipes: content-based layer renaming, tokenizing hardcoded values, spacing normalization, detached-instance sweeps — with preview-first discipline.\",\n janitorialCleanup,\n ],\n];\n\nexport function registerPrompts(server: McpServer): void {\n for (const [name, description, text] of SKILLS) {\n server.prompt(name, description, () => ({\n messages: [\n {\n role: \"user\" as const,\n content: { type: \"text\" as const, text },\n },\n ],\n }));\n }\n}\n"],"mappings":"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","names":["z","z","z","register","z","z","register","register","z","register","z","register","z","register","z","register","z","register","z","register","z","register","z","register","z","register","z","register","z","register","z","register","z","register","z","register","z","register","z","register","z","register","z","register","z","register","z","result","register","z","register","z","result","register","z","register","z","register","z","register","z","register","z","register","z","register","z","textResult","register","z","errorResult","register","errorResult","z","register","z","register","z","errorResult","differences","register","z","register","z","errorResult","z"]}