genable-mcp 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/tools-schema.json +3 -3
- package/package.json +6 -6
package/dist/tools-schema.json
CHANGED
|
@@ -183,7 +183,7 @@
|
|
|
183
183
|
},
|
|
184
184
|
{
|
|
185
185
|
"name": "replace_props",
|
|
186
|
-
"description": "
|
|
186
|
+
"description": "Bulk find-and-replace property values across a subtree (target node + all descendants). Destructive batch mutation — no preview, no undo across many nodes. Returns per-rule match counts.\n\nUse when:\n- Theming pass: change every #FFF fill to #000 across a screen\n- Token migration: bump every fontSize from 14 to 16\n- Normalizing values left inconsistent by earlier passes\n- The alternative is N targeted single-node calls (set_text / set_fill / edit)\n\nReturns: { data: { replacements: [{ rule: 0, matched: 12 }, { rule: 1, matched: 0 }] } }\n\nParameters beyond schema:\n- `node` is the subtree root; search recurses into all descendants (depth-first).\n- Each rule's `from` is an EXACT-match string (no substring, no regex). For typed props (fontSize, opacity), pass values as strings — the executor coerces.\n- Zero matches do NOT error — they return matched: 0. Sanity-check with discover_props first if you're unsure values exist.\n\nSkip when:\n- Updating a single known node — use set_text / set_fill / set_stroke / set_layout for type-aware single-intent edits, or edit for generic.\n- Values are variable-bound (tokens) — replace_props bypasses bindings; use bind_variable to swap the token instead.\n- You need partial / fuzzy match — replace_props is exact-only; you'll need find_nodes + a loop.\n\nExamples:\n // single rule, white -> black\n replace_props({node: \"1:2\", rules: [{prop: \"fillColor\", from: \"#FFF\", to: \"#000\"}]})\n\n // batch theme update — both rules applied in one pass\n replace_props({node: \"1:2\", rules: [\n {prop: \"fillColor\", from: \"#FFF\", to: \"#000\"},\n {prop: \"fontSize\", from: \"14\", to: \"16\"}\n ]})",
|
|
187
187
|
"parameters": {
|
|
188
188
|
"type": "object",
|
|
189
189
|
"properties": {
|
|
@@ -730,7 +730,7 @@
|
|
|
730
730
|
},
|
|
731
731
|
{
|
|
732
732
|
"name": "create_instance",
|
|
733
|
-
"description": "Create an instance of a component.\n\nExamples:\n create_instance({node: \"1:2\"})\n create_instance({node: \"1:2\", parent: \"1:4\"})",
|
|
733
|
+
"description": "Create an instance of an existing component. Mutates the canvas — appends a new InstanceNode as the last child of `parent` (or the active page root if omitted). The instance is LINKED to the component master, so future component edits propagate. Returns the new instance's nodeId.\n\nUse when:\n- Spawning runtime copies of a Component master (buttons, list items, cards)\n- Reusing a design-system component in a fresh layout\n- Programmatic instantiation outside a jsx() tree-build\n\nReturns: { data: { id: \"5:42\", name: \"Button\", componentId: \"1:2\" } }\n\nParameters beyond schema:\n- `node` must be a Component node (not Frame, Text, or another Instance). Discover IDs with find_nodes({ type: \"COMPONENT\" }).\n- `parent` optional. If parent is auto-layout, the instance enters the flow and inherits sizing rules. If omitted, the instance is placed at the active page root with detached position — may overlap existing content; set explicit position with edit afterwards.\n\nSkip when:\n- Duplicating a non-component node — instance creation will fail; use clone_node instead.\n- Building a subtree from scratch — use jsx with <instance ref=\"ComponentName\"/> for atomic single-call construction.\n\nExamples:\n create_instance({node: \"1:2\"}) // at page root\n create_instance({node: \"1:2\", parent: \"1:4\"}) // inside frame 1:4",
|
|
734
734
|
"parameters": {
|
|
735
735
|
"type": "object",
|
|
736
736
|
"properties": {
|
|
@@ -1203,7 +1203,7 @@
|
|
|
1203
1203
|
},
|
|
1204
1204
|
{
|
|
1205
1205
|
"name": "session_note",
|
|
1206
|
-
"description": "Read / write your own session scratchpad. Persists across turns within one design session (\"New Design\" resets it). Notes are how state carries from this turn into the next — the next session loads them as context.\n\nActions:\n action: \"read\" → read({key}) returns the current value (empty string if unset)\n action: \"write\" → write({key, value}) replaces or deletes (pass value:\"\" to delete)\n action: \"list\" → list({}) returns [{key, chars}] for all existing notes\n\nSlots — FORWARD-LOOKING (what we plan / commit to):\n - plan — this turn's intent + step outline (write at turn start)\n - decisions — locked choices: style picked + reason, accent token, font scale, hero treatment, etc. (write BEFORE jsx)\n - brand — durable brand notes pulled from a project design.md (if user supplied one)\n - todo — TRULY unfinished work for the next turn (omit if everything shipped)\n\nSlots — BACKWARD-LOOKING (what happened, write AT TURN END):\n - failures — tool calls that failed this turn + how you worked around them.\n Example: \"jsx items='stretch' rejected (DSL valid: center|start|end|space-between|baseline); retried with 'center'.\"\n If a failure repeats a class you've seen before, name the class.\n - gotchas — validator warnings you noticed but chose not to fix + why.\n Example: \"4 LOW_CONTRAST on nav links (2.5:1) — deliberate for ambient-grey style; revisit if user complains.\"\n Also: magic numbers / hand-tuned positions and what motivated them.\n Example: \"Glow ellipses at (-180, 220) / (1060, 70) — placed half outside frame to bleed in.\"\n - learnings — surprises about this codebase / DSL / Figma API.\n Example: \"radial-gradient(circle at X% Y%) rejected — DSL only takes the simple form. Same trap as CSS-prior bleed elsewhere.\"\n\nREQUIRED behavior:\n - First turn: write at least `decisions` BEFORE any jsx (commit-before-act).\n - Every turn end: write at least ONE of `failures / gotchas / learnings` if ANY of these happened this turn:\n • a tool call returned an error\n • a tool call returned warnings you chose not to fix\n • you hand-tuned a coordinate / size / color away from a value the model would have picked\n • you found a DSL behavior that surprised you\n \"All clean, no carry-over\" is almost never accurate — at least one backward slot belongs.\n - jsx that uses a color / font / size should round-trip through `decisions` (token traceability).\n\nExamples:\n session_note({action: \"write\", key: \"decisions\", value: \"Style: fintech-dark.\\nAccent: #3B82F6 (style.accent — NOT indigo).\\nFont: Space Grotesk display / Inter body.\\nHero treatment: split (overrides anatomy VERTICAL — desktop convention).\\nH1 size: 32 (style.display).\"})\n session_note({action: \"write\", key: \"failures\", value: \"jsx #6 align='stretch' rejected (DSL valid: center|start|end|space-between|baseline) — retried with 'center'. Same CSS-prior class as gradient: model has CSS values that DSL doesn't accept.\"})\n session_note({action: \"write\", key: \"gotchas\", value: \"8 LOW_CONTRAST warnings on nav links + secondary CTA (2.5:1 against dark bg). Left as-is — user prompt didn't require WCAG pass; flagging in case next iteration tightens contrast.\"})\n session_note({action: \"write\", key: \"learnings\", value: \"layoutPositioning='absolute' children render correctly inside auto-layout frame, but parent needs clipsContent=true to suppress overflow on big glow ellipses.\"})\n session_note({action: \"read\", key: \"decisions\"})\n session_note({action: \"list\"})",
|
|
1206
|
+
"description": "Read / write your own session scratchpad. Persists across turns within one design session (\"New Design\" resets it). Notes are how state carries from this turn into the next — the next session loads them as context.\n\nActions:\n action: \"read\" → read({key}) returns the current value (empty string if unset)\n action: \"write\" → write({key, value}) replaces or deletes (pass value:\"\" to delete)\n action: \"list\" → list({}) returns [{key, chars}] for all existing notes\n\nSlots — FORWARD-LOOKING (what we plan / commit to):\n - plan — this turn's intent + step outline (write at turn start)\n - decisions — locked choices: style picked + reason, accent token, font scale, hero treatment, etc. (write BEFORE jsx)\n - brand — durable brand notes pulled from a project design.md (if user supplied one)\n - todo — TRULY unfinished work for the next turn (omit if everything shipped)\n\nSlots — BACKWARD-LOOKING (what happened, write AT TURN END — AUTO-MERGE on write):\n - failures — tool calls that failed this turn + how you worked around them.\n Example: \"jsx items='stretch' rejected (DSL valid: center|start|end|space-between|baseline); retried with 'center'.\"\n If a failure repeats a class you've seen before, name the class.\n - gotchas — validator warnings you noticed but chose not to fix + why.\n Example: \"4 LOW_CONTRAST on nav links (2.5:1) — deliberate for ambient-grey style; revisit if user complains.\"\n Also: magic numbers / hand-tuned positions and what motivated them.\n Example: \"Glow ellipses at (-180, 220) / (1060, 70) — placed half outside frame to bleed in.\"\n - learnings — surprises about this codebase / DSL / Figma API.\n Example: \"radial-gradient(circle at X% Y%) rejected — DSL only takes the simple form. Same trap as CSS-prior bleed elsewhere.\"\n\nBACKWARD-LOOKING slots auto-merge: writing to `failures / gotchas / learnings` appends to prior content after a \"---\" divider — your new value never silently overwrites accumulated retrospective notes. To replace fresh, first `write({value: \"\"})` to clear, then write again. The result `data.merged=true` flag confirms when merge happened.\n\nREQUIRED behavior:\n - First turn: write at least `decisions` BEFORE any jsx (commit-before-act).\n - Subsequent turns: `read` `decisions` and `learnings` BEFORE any jsx — those slots survive across turns and your conversationHistory won't carry the full content reliably. Your turn's adjacent <system-reminder> snapshot also surfaces current notes, but explicit `read` proves you considered them.\n - Every turn end: write at least ONE of `failures / gotchas / learnings` if ANY of these happened this turn:\n • a tool call returned an error\n • a tool call returned warnings you chose not to fix\n • you hand-tuned a coordinate / size / color away from a value the model would have picked\n • you found a DSL behavior that surprised you\n \"All clean, no carry-over\" is almost never accurate — at least one backward slot belongs.\n - jsx that uses a color / font / size should round-trip through `decisions` (token traceability).\n\nExamples:\n session_note({action: \"write\", key: \"decisions\", value: \"Style: fintech-dark.\\nAccent: #3B82F6 (style.accent — NOT indigo).\\nFont: Space Grotesk display / Inter body.\\nHero treatment: split (overrides anatomy VERTICAL — desktop convention).\\nH1 size: 32 (style.display).\"})\n session_note({action: \"write\", key: \"failures\", value: \"jsx #6 align='stretch' rejected (DSL valid: center|start|end|space-between|baseline) — retried with 'center'. Same CSS-prior class as gradient: model has CSS values that DSL doesn't accept.\"})\n session_note({action: \"write\", key: \"gotchas\", value: \"8 LOW_CONTRAST warnings on nav links + secondary CTA (2.5:1 against dark bg). Left as-is — user prompt didn't require WCAG pass; flagging in case next iteration tightens contrast.\"})\n session_note({action: \"write\", key: \"learnings\", value: \"layoutPositioning='absolute' children render correctly inside auto-layout frame, but parent needs clipsContent=true to suppress overflow on big glow ellipses.\"})\n session_note({action: \"read\", key: \"decisions\"})\n session_note({action: \"list\"})",
|
|
1207
1207
|
"parameters": {
|
|
1208
1208
|
"type": "object",
|
|
1209
1209
|
"properties": {
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "genable-mcp",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"mcpName": "io.github.
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"mcpName": "io.github.musepy/genable-mcp",
|
|
5
5
|
"description": "Write-side MCP server for Figma — build, edit, restructure, and search Figma designs from Claude Code, Cursor, Cline, or any MCP client. Complements Figma's official MCP (which is read-only). 41 tools covering tree creation (JSX), variables/tokens, components, cross-page navigation, and visual verification.",
|
|
6
|
-
"author": "
|
|
6
|
+
"author": "musepy <muse40007@gmail.com> (https://github.com/musepy)",
|
|
7
7
|
"bugs": {
|
|
8
|
-
"url": "https://github.com/
|
|
8
|
+
"url": "https://github.com/musepy/genable/issues"
|
|
9
9
|
},
|
|
10
10
|
"main": "dist/index.js",
|
|
11
11
|
"bin": {
|
|
@@ -65,10 +65,10 @@
|
|
|
65
65
|
"publishConfig": {
|
|
66
66
|
"access": "public"
|
|
67
67
|
},
|
|
68
|
-
"homepage": "https://github.com/
|
|
68
|
+
"homepage": "https://github.com/musepy/genable/tree/main/tools/mcp-server#readme",
|
|
69
69
|
"repository": {
|
|
70
70
|
"type": "git",
|
|
71
|
-
"url": "git+https://github.com/
|
|
71
|
+
"url": "git+https://github.com/musepy/genable.git",
|
|
72
72
|
"directory": "tools/mcp-server"
|
|
73
73
|
},
|
|
74
74
|
"license": "MIT"
|