conductor-figma 3.0.3 → 3.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +138 -48
- package/figma-plugin/code.js +10 -10
- package/figma-plugin/manifest.json +2 -2
- package/package.json +1 -1
- package/src/server.js +37 -29
package/README.md
CHANGED
|
@@ -1,27 +1,32 @@
|
|
|
1
1
|
# conductor-figma
|
|
2
2
|
|
|
3
|
-
Design-intelligent MCP server for Figma. 201 tools across 17 categories. Every tool has built-in design intelligence — 8px grid, type scales, semantic colors, accessibility checks, component defaults.
|
|
3
|
+
Design-intelligent MCP server for Figma. 201 tools across 17 categories. Every tool has built-in design intelligence — 8px grid, type scales, semantic colors, accessibility checks, component defaults. Works with Cursor and Claude Code.
|
|
4
4
|
|
|
5
5
|
```
|
|
6
6
|
npx conductor-figma
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## How to use
|
|
10
10
|
|
|
11
|
+
### 1. Clone the repo (for the Figma plugin)
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
```bash
|
|
14
|
+
git clone https://github.com/dragoon0x/conductor.git
|
|
15
|
+
```
|
|
13
16
|
|
|
14
|
-
|
|
17
|
+
### 2. Import the Figma plugin
|
|
15
18
|
|
|
16
|
-
|
|
19
|
+
Open Figma Desktop:
|
|
17
20
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
1. Go to **Plugins → Development → Import plugin from manifest**
|
|
22
|
+
2. Navigate to `conductor/figma-plugin/manifest.json`
|
|
23
|
+
3. Click **Open**
|
|
24
|
+
|
|
25
|
+
The plugin is now installed. You only need to do this once.
|
|
21
26
|
|
|
22
|
-
|
|
27
|
+
### 3. Add to Cursor
|
|
23
28
|
|
|
24
|
-
|
|
29
|
+
Open `~/.cursor/mcp.json` and add conductor:
|
|
25
30
|
|
|
26
31
|
```json
|
|
27
32
|
{
|
|
@@ -34,55 +39,140 @@ In Figma: **Plugins → Development → Import plugin from manifest** → select
|
|
|
34
39
|
}
|
|
35
40
|
```
|
|
36
41
|
|
|
37
|
-
|
|
42
|
+
Restart Cursor.
|
|
43
|
+
|
|
44
|
+
### 4. Connect and design
|
|
45
|
+
|
|
46
|
+
1. Open a Figma file
|
|
47
|
+
2. Run the plugin: **Plugins → Development → Conductor**
|
|
48
|
+
3. The plugin should show a green dot (Connected)
|
|
49
|
+
4. In Cursor chat, type `@conductor` followed by any command
|
|
50
|
+
|
|
51
|
+
### Example prompts
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
@conductor Create a dark hero section with a big heading and a purple CTA button
|
|
55
|
+
|
|
56
|
+
@conductor Check contrast between #ffffff and #6366f1
|
|
57
|
+
|
|
58
|
+
@conductor Create a dashboard layout with sidebar, KPI cards, and chart area
|
|
59
|
+
|
|
60
|
+
@conductor Audit accessibility on my current selection
|
|
61
|
+
|
|
62
|
+
@conductor Replace all #6366f1 with #3b82f6 across the file
|
|
63
|
+
|
|
64
|
+
@conductor Export this frame as React + Tailwind code
|
|
65
|
+
|
|
66
|
+
@conductor Scan my file and show me all off-grid spacing
|
|
67
|
+
|
|
68
|
+
@conductor Generate a color palette from #6366f1
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Alternative: use local path (faster startup)
|
|
72
|
+
|
|
73
|
+
Instead of `npx`, point directly to the cloned repo:
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"mcpServers": {
|
|
78
|
+
"conductor": {
|
|
79
|
+
"command": "node",
|
|
80
|
+
"args": ["/path/to/conductor/bin/conductor.js"]
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## How it works
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
You type in Cursor → MCP server (stdio) → WebSocket :3055 → Figma plugin → Canvas
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Cursor starts the MCP server automatically. The server opens a WebSocket on port 3055. The Figma plugin connects to that WebSocket and executes commands on the canvas.
|
|
93
|
+
|
|
94
|
+
## What makes this different
|
|
95
|
+
|
|
96
|
+
Other MCP servers for Figma are API wrappers. You give exact pixel values, they obey — even when those values are wrong. Conductor applies design rules before anything touches the canvas.
|
|
97
|
+
|
|
98
|
+
You say "create a button." A typical MCP makes a rectangle. Conductor makes a 44px-tall frame with 20px horizontal padding, 10px radius, 15px Semi Bold text — because that's what a button actually is.
|
|
99
|
+
|
|
100
|
+
## 201 tools in 17 categories
|
|
101
|
+
|
|
102
|
+
### Create & Layout (20)
|
|
103
|
+
create_frame, create_text, create_rectangle, create_ellipse, create_line, create_svg_node, create_component, create_component_instance, create_component_set, create_smart_component, set_auto_layout, create_section, create_page, create_table_frame, create_form, create_nav_bar, create_card_grid, create_sidebar_layout, create_footer, create_header
|
|
104
|
+
|
|
105
|
+
### Modify & Style (25)
|
|
106
|
+
modify_node, set_fill, set_stroke, set_effects, set_image_fill, style_text_range, set_constraints, delete_node, move_to_parent, duplicate_node, group_nodes, ungroup_nodes, resize_node, align_nodes, set_corner_radius, set_opacity, set_blend_mode, set_clip_content, rename_node, lock_node, set_visibility, reorder_node, set_layout_sizing, flatten_node, set_rotation
|
|
107
|
+
|
|
108
|
+
### Vector & Shape (8)
|
|
109
|
+
create_vector, boolean_operation, create_polygon, create_star, offset_path, create_arrow, create_icon (35 built-in), create_divider
|
|
110
|
+
|
|
111
|
+
### Read & Inspect (18)
|
|
112
|
+
get_selection, get_page_structure, get_node_info, get_nodes_info, find_nodes, get_local_styles, get_local_variables, list_components, list_pages, get_document_info, set_selection, set_focus, get_annotations, set_annotation, list_available_fonts, read_node_css, get_selection_colors, measure_distance
|
|
113
|
+
|
|
114
|
+
### Variables & Tokens (10)
|
|
115
|
+
create_variable_collection, create_variable, bind_variable, get_variables, update_variable, delete_variable, create_design_tokens, import_tokens, export_tokens, swap_mode
|
|
116
|
+
|
|
117
|
+
### Export & Code (12)
|
|
118
|
+
export_as_svg, export_as_png, export_to_react, export_design_specs, export_assets, screenshot, copy_css, generate_stylesheet, export_color_palette, export_typography, export_component_inventory, export_spacing_tokens
|
|
119
|
+
|
|
120
|
+
### Accessibility & Lint (12)
|
|
121
|
+
audit_accessibility, check_contrast, fix_touch_targets, lint_design, fix_spacing, check_naming, suggest_improvements, validate_component, check_consistency, generate_a11y_report, color_blindness_check, responsive_check
|
|
122
|
+
|
|
123
|
+
### Batch Operations (17)
|
|
124
|
+
batch_rename, batch_style, batch_replace_text, batch_replace_color, batch_resize, batch_align, batch_delete, batch_duplicate, batch_set_visibility, batch_lock, select_all_by_type, clean_hidden_layers, batch_set_font, batch_round_values, batch_remove_strokes, batch_remove_effects, batch_set_corner_radius
|
|
125
|
+
|
|
126
|
+
### Design System (10)
|
|
127
|
+
scan_design_system, create_style_guide, detect_inconsistencies, normalize_design, extract_components, get_design_craft_guide, suggest_color_palette, suggest_type_scale, import_design_system, compare_to_system
|
|
128
|
+
|
|
129
|
+
### Responsive (5)
|
|
130
|
+
create_responsive_variant, set_breakpoint, convert_to_responsive, generate_mobile, stack_for_mobile
|
|
131
|
+
|
|
132
|
+
### Typography (10)
|
|
133
|
+
type_scale_apply, type_audit, type_set_hierarchy, type_check_measure, type_normalize, type_list_styles, type_pair_suggest, type_replace_font, set_text_content, type_create_style
|
|
134
|
+
|
|
135
|
+
### Color (10)
|
|
136
|
+
color_palette_generate, color_extract, color_harmonize, color_darkmode, color_lightmode, color_check_all, color_create_style, color_apply_style, color_replace_global, color_generate_semantic
|
|
38
137
|
|
|
39
|
-
|
|
138
|
+
### Prototype & Interaction (10)
|
|
139
|
+
create_prototype_link, create_scroll_behavior, set_overflow, create_overlay, set_fixed_position, create_hover_state, create_flow, list_flows, remove_prototype_link, set_transition
|
|
40
140
|
|
|
41
|
-
|
|
141
|
+
### Page Management (8)
|
|
142
|
+
create_new_page, switch_page, duplicate_page, delete_page, rename_page, sort_pages, merge_pages, page_overview
|
|
42
143
|
|
|
43
|
-
|
|
144
|
+
### Library & Components (8)
|
|
145
|
+
search_library, list_team_libraries, swap_component, detach_instance, reset_overrides, component_audit, batch_swap_component, publish_components
|
|
44
146
|
|
|
45
|
-
|
|
147
|
+
### Annotation & Handoff (10)
|
|
148
|
+
annotate_spacing, annotate_colors, annotate_typography, create_measurement, create_spec_sheet, annotate_grid, annotate_hierarchy, create_component_docs, annotate_responsive, create_changelog
|
|
46
149
|
|
|
47
|
-
|
|
150
|
+
### Effects & Styles (8)
|
|
151
|
+
create_glassmorphism, create_neumorphism, create_noise_texture, set_gradient_fill, create_shadow_system, apply_backdrop_blur, create_border_gradient, remove_all_effects
|
|
48
152
|
|
|
49
|
-
##
|
|
153
|
+
## Design intelligence engine
|
|
50
154
|
|
|
51
|
-
|
|
52
|
-
|----------|-------|-----------|
|
|
53
|
-
| Create & Layout | 20 | Frames, text, shapes, smart components (18 types), sections, pages, forms, tables, nav bars, cards, sidebars |
|
|
54
|
-
| Modify & Style | 25 | Fills (solid + gradients), strokes, effects, image fills, text ranges, constraints, transforms |
|
|
55
|
-
| Vector & Shape | 8 | Paths, booleans, polygons, stars, 35 built-in icons, arrows, dividers |
|
|
56
|
-
| Read & Inspect | 18 | Selection, page tree, node info, search, CSS export, fonts, annotations, measurements |
|
|
57
|
-
| Variables & Tokens | 10 | Collections, modes, binding, W3C import/export, full token system from brand color |
|
|
58
|
-
| Export & Code | 12 | React + Tailwind, HTML, Vue, Svelte, SVG, PNG, design specs, stylesheets, palettes |
|
|
59
|
-
| Accessibility & Lint | 12 | WCAG audit, contrast, touch targets, font sizes, color blindness, design lint, compliance reports |
|
|
60
|
-
| Batch Operations | 17 | Rename patterns, bulk style, find/replace text/color, clean hidden layers, round values, set fonts |
|
|
61
|
-
| Design System | 10 | Scan, extract, normalize, lint, style guide, palette, type scale, import/export |
|
|
62
|
-
| Responsive | 5 | Mobile/tablet/desktop variants, breakpoints, stacking, responsive conversion |
|
|
63
|
-
| Typography | 10 | Type scale, audit, hierarchy, measure, normalize, font replace, pairing, styles |
|
|
64
|
-
| Color | 10 | Palette generation, harmonies, dark/light mode, contrast check, semantic systems |
|
|
65
|
-
| Prototype | 10 | Links, transitions, overlays, scroll, hover states, flows, fixed position |
|
|
66
|
-
| Page Management | 8 | Create, switch, duplicate, delete, rename, sort, merge, overview |
|
|
67
|
-
| Library | 8 | Search, swap, detach, audit, batch swap, publish |
|
|
68
|
-
| Annotation & Handoff | 10 | Spacing redlines, color swatches, typography specs, spec sheets, changelogs |
|
|
69
|
-
| Effects & Styles | 8 | Glassmorphism, neumorphism, noise, gradients, shadow systems, border gradients |
|
|
155
|
+
Every tool queries the intelligence engine before touching Figma:
|
|
70
156
|
|
|
71
|
-
|
|
157
|
+
- **8px Grid** — All spacing values snapped. snap(13) = 16.
|
|
158
|
+
- **Type Scale** — 7 ratio presets: Minor Second through Golden Ratio.
|
|
159
|
+
- **Semantic Colors** — Full palette from one brand hex. Dark + light modes.
|
|
160
|
+
- **Component Defaults** — 18 component types with size variants.
|
|
161
|
+
- **Accessibility** — WCAG AA/AAA contrast, 44px touch targets, font minimums.
|
|
162
|
+
- **Font Weights** — Auto-resolves "bold" → "Bold", "600" → "Semi Bold".
|
|
163
|
+
- **Layout Intelligence** — 13 layout presets: row, column, center, spread, sidebar, grid, form.
|
|
72
164
|
|
|
73
|
-
|
|
165
|
+
## Troubleshooting
|
|
74
166
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
- **Semantic Colors**: Full palette from one brand color (dark + light modes)
|
|
78
|
-
- **Component Defaults**: 18 component types with size variants (button, input, card, avatar, badge, chip, switch, checkbox, radio, toast, tooltip, modal, dropdown, tabs, table, progress, skeleton, divider)
|
|
79
|
-
- **Accessibility**: WCAG AA/AAA contrast, 44px touch targets, font minimums, color blindness
|
|
80
|
-
- **Font Weights**: Auto-resolves "bold" → "Bold", "600" → "Semi Bold"
|
|
81
|
-
- **Layout Intelligence**: 13 layout presets (row, column, center, spread, grid, sidebar, form)
|
|
167
|
+
**Plugin says "Disconnected"**
|
|
168
|
+
The MCP server isn't running. Make sure Cursor is open and conductor is configured in mcp.json. Try sending any @conductor message in Cursor chat — that triggers the server to start.
|
|
82
169
|
|
|
83
|
-
|
|
170
|
+
**Port 3055 already in use**
|
|
171
|
+
Kill the old process: `kill $(lsof -t -i :3055) 2>/dev/null` then restart Cursor.
|
|
84
172
|
|
|
85
|
-
|
|
173
|
+
**Cursor shows "Loading tools" forever**
|
|
174
|
+
Make sure you have the latest version. Run: `npx conductor-figma@latest`
|
|
175
|
+
Or use the local path method for faster startup.
|
|
86
176
|
|
|
87
177
|
## Disclaimer
|
|
88
178
|
|
|
@@ -96,4 +186,4 @@ MIT. Built by [0xDragoon](https://github.com/dragoon0x).
|
|
|
96
186
|
- Users are solely responsible for ensuring their use of this software complies with all applicable laws, regulations, terms of service, and licensing agreements — including Figma's Terms of Service and API usage policies.
|
|
97
187
|
- **Use at your own risk.** Always back up your Figma files before running any automated operations. The author is not responsible for any unintended modifications, deletions, or corruption of design files.
|
|
98
188
|
|
|
99
|
-
MIT License · Copyright
|
|
189
|
+
MIT License · Copyright 2025 0xDragoon
|
package/figma-plugin/code.js
CHANGED
|
@@ -281,8 +281,8 @@ async function executeCommand(cmd, data) {
|
|
|
281
281
|
const s = data.shadow
|
|
282
282
|
effects.push({
|
|
283
283
|
type: 'DROP_SHADOW', visible: true,
|
|
284
|
-
color: {
|
|
285
|
-
offset: { x: s.offsetX || s.offset
|
|
284
|
+
color: (function(){ var c = hexToRGB(s.color || "#00000040"); return {r:c.r,g:c.g,b:c.b,a:0.25}; })(),
|
|
285
|
+
offset: { x: s.offsetX || (s.offset && s.offset.x) || 0, y: s.offsetY || (s.offset && s.offset.y) || 4 },
|
|
286
286
|
radius: s.blur || 8, spread: s.spread || 0,
|
|
287
287
|
})
|
|
288
288
|
}
|
|
@@ -427,7 +427,7 @@ async function executeCommand(cmd, data) {
|
|
|
427
427
|
const node = getNode(data.nodeId)
|
|
428
428
|
if (!node || node.type !== 'GROUP') throw new Error('Not a group')
|
|
429
429
|
const parent = node.parent
|
|
430
|
-
const children =
|
|
430
|
+
const children = Array.prototype.slice.call(node.children)
|
|
431
431
|
for (const child of children) parent.appendChild(child)
|
|
432
432
|
node.remove()
|
|
433
433
|
return { ungrouped: children.length }
|
|
@@ -521,7 +521,7 @@ async function executeCommand(cmd, data) {
|
|
|
521
521
|
|
|
522
522
|
case 'list_available_fonts': {
|
|
523
523
|
const fonts = await figma.listAvailableFontsAsync()
|
|
524
|
-
const families =
|
|
524
|
+
const families = Array.from(new Set(fonts.map(f => f.fontName.family))).sort()
|
|
525
525
|
return { count: families.length, families: families.slice(0, 100) }
|
|
526
526
|
}
|
|
527
527
|
|
|
@@ -532,7 +532,7 @@ async function executeCommand(cmd, data) {
|
|
|
532
532
|
node.fills.forEach(f => { if (f.type === 'SOLID') colors.add(rgbToHex(f.color)) })
|
|
533
533
|
}
|
|
534
534
|
}
|
|
535
|
-
return
|
|
535
|
+
return Array.from(colors)
|
|
536
536
|
}
|
|
537
537
|
|
|
538
538
|
case 'measure_distance': {
|
|
@@ -660,7 +660,7 @@ async function executeCommand(cmd, data) {
|
|
|
660
660
|
const newFills = n.fills.map(f => {
|
|
661
661
|
if (f.type === 'SOLID' && Math.abs(f.color.r - findRgb.r) < 0.02 && Math.abs(f.color.g - findRgb.g) < 0.02 && Math.abs(f.color.b - findRgb.b) < 0.02) {
|
|
662
662
|
count++
|
|
663
|
-
|
|
663
|
+
var nf = {type:f.type,color:hexToRGB(data.replace),opacity:f.opacity}; return nf
|
|
664
664
|
}
|
|
665
665
|
return f
|
|
666
666
|
})
|
|
@@ -717,10 +717,10 @@ async function executeCommand(cmd, data) {
|
|
|
717
717
|
return false
|
|
718
718
|
})
|
|
719
719
|
return {
|
|
720
|
-
colors:
|
|
721
|
-
fonts:
|
|
722
|
-
radii:
|
|
723
|
-
spacings:
|
|
720
|
+
colors: Array.from(colors).sort(),
|
|
721
|
+
fonts: Array.from(fonts).sort(),
|
|
722
|
+
radii: Array.from(radii).sort(function(a,b){return a-b}),
|
|
723
|
+
spacings: Array.from(spacings).sort(function(a,b){return a-b}),
|
|
724
724
|
}
|
|
725
725
|
}
|
|
726
726
|
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"enableProposedApi": false,
|
|
9
9
|
"editorType": ["figma"],
|
|
10
10
|
"networkAccess": {
|
|
11
|
-
"allowedDomains": ["
|
|
12
|
-
"reasoning": "
|
|
11
|
+
"allowedDomains": ["none"],
|
|
12
|
+
"reasoning": "Conductor connects to a local WebSocket server only"
|
|
13
13
|
}
|
|
14
14
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "conductor-figma",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.4",
|
|
4
4
|
"description": "Design-intelligent MCP server for Figma. 201 design-intelligent tools for Figma. Every tool knows typography, spacing, color, accessibility. Not a shape proxy — a design engine.",
|
|
5
5
|
"author": "0xDragoon",
|
|
6
6
|
"license": "MIT",
|
package/src/server.js
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
// ═══════════════════════════════════════════
|
|
2
|
-
// CONDUCTOR v3 — MCP Server (stdio)
|
|
3
|
-
// ═══════════════════════════════════════════
|
|
4
|
-
|
|
5
1
|
import { TOOL_LIST, TOOL_COUNT, getTool, CATEGORIES } from './tools/registry.js'
|
|
6
2
|
import { handleTool } from './tools/handlers.js'
|
|
7
3
|
import { createBridge } from './bridge.js'
|
|
8
4
|
|
|
9
|
-
var VERSION = '3.0.
|
|
5
|
+
var VERSION = '3.0.4'
|
|
10
6
|
var bridge = null
|
|
11
7
|
var bridgeStarted = false
|
|
12
8
|
|
|
@@ -21,34 +17,44 @@ function ensureBridge() {
|
|
|
21
17
|
return bridge
|
|
22
18
|
}
|
|
23
19
|
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
if (process.stdout._handle && process.stdout._handle.setBlocking) {
|
|
21
|
+
process.stdout._handle.setBlocking(true)
|
|
22
|
+
}
|
|
26
23
|
|
|
24
|
+
var buffer = ''
|
|
27
25
|
process.stdin.setEncoding('utf8')
|
|
28
26
|
process.stdin.on('data', function(chunk) {
|
|
29
27
|
buffer += chunk
|
|
28
|
+
processBuffer()
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
function processBuffer() {
|
|
30
32
|
while (true) {
|
|
31
|
-
var
|
|
32
|
-
if (
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
} catch (e) { log('Parse error:', e.message) }
|
|
33
|
+
var nlIdx = buffer.indexOf('\n')
|
|
34
|
+
if (nlIdx === -1) {
|
|
35
|
+
if (buffer.length > 0 && buffer[0] === '{') {
|
|
36
|
+
try { JSON.parse(buffer) } catch(e) { break }
|
|
37
|
+
tryParse(buffer)
|
|
38
|
+
buffer = ''
|
|
39
|
+
}
|
|
40
|
+
break
|
|
41
|
+
}
|
|
42
|
+
var line = buffer.slice(0, nlIdx).trim()
|
|
43
|
+
buffer = buffer.slice(nlIdx + 1)
|
|
44
|
+
if (line.length === 0) continue
|
|
45
|
+
if (line[0] === '{') tryParse(line)
|
|
45
46
|
}
|
|
46
|
-
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function tryParse(str) {
|
|
50
|
+
try {
|
|
51
|
+
var msg = JSON.parse(str)
|
|
52
|
+
handleMessage(msg)
|
|
53
|
+
} catch (e) { log('Parse error:', e.message) }
|
|
54
|
+
}
|
|
47
55
|
|
|
48
56
|
function send(msg) {
|
|
49
|
-
|
|
50
|
-
var out = 'Content-Length: ' + Buffer.byteLength(json) + '\r\n\r\n' + json
|
|
51
|
-
process.stdout.write(out)
|
|
57
|
+
process.stdout.write(JSON.stringify(msg) + '\n')
|
|
52
58
|
}
|
|
53
59
|
|
|
54
60
|
function respond(id, result) { send({ jsonrpc: '2.0', id: id, result: result }) }
|
|
@@ -57,21 +63,23 @@ function respondError(id, code, message) { send({ jsonrpc: '2.0', id: id, error:
|
|
|
57
63
|
function handleMessage(msg) {
|
|
58
64
|
var id = msg.id
|
|
59
65
|
var method = msg.method
|
|
60
|
-
var params = msg.params
|
|
66
|
+
var params = msg.params || {}
|
|
67
|
+
|
|
68
|
+
log('<- ' + method + (id !== undefined ? ' #' + id : ''))
|
|
61
69
|
|
|
62
70
|
switch (method) {
|
|
63
71
|
case 'initialize':
|
|
64
|
-
// Start bridge in background, respond immediately
|
|
65
72
|
ensureBridge()
|
|
66
73
|
log('Conductor v' + VERSION + ' ready — ' + TOOL_COUNT + ' tools')
|
|
67
74
|
respond(id, {
|
|
68
|
-
protocolVersion: '2024-11-05',
|
|
75
|
+
protocolVersion: params.protocolVersion || '2024-11-05',
|
|
69
76
|
capabilities: { tools: { listChanged: false } },
|
|
70
77
|
serverInfo: { name: 'conductor-figma', version: VERSION },
|
|
71
78
|
})
|
|
72
79
|
return
|
|
73
80
|
|
|
74
81
|
case 'notifications/initialized':
|
|
82
|
+
case 'notifications/cancelled':
|
|
75
83
|
return
|
|
76
84
|
|
|
77
85
|
case 'tools/list':
|
|
@@ -107,7 +115,7 @@ function handleMessage(msg) {
|
|
|
107
115
|
return
|
|
108
116
|
|
|
109
117
|
default:
|
|
110
|
-
if (id) respondError(id, -32601, 'Unknown method: ' + method)
|
|
118
|
+
if (id !== undefined) respondError(id, -32601, 'Unknown method: ' + method)
|
|
111
119
|
}
|
|
112
120
|
}
|
|
113
121
|
|