@createlex/figma-swiftui-mcp 1.1.0 → 1.2.0
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/companion/bridge-server.cjs +58 -5
- package/package.json +1 -1
|
@@ -230,6 +230,55 @@ function startBridgeServer(options = {}) {
|
|
|
230
230
|
});
|
|
231
231
|
});
|
|
232
232
|
|
|
233
|
+
// GET /design-context — returns current selection's design context as JSON.
|
|
234
|
+
// Lets any AI tool (Windsurf, a script, a browser) fetch the live Figma context
|
|
235
|
+
// via a simple HTTP GET without needing MCP protocol or copy-paste.
|
|
236
|
+
// Usage: GET http://localhost:7765/design-context?maxDepth=4
|
|
237
|
+
app.get('/design-context', async (req, res) => {
|
|
238
|
+
if (!pluginBridgeClient || pluginBridgeClient.readyState !== WebSocket.OPEN) {
|
|
239
|
+
return res.status(503).json({
|
|
240
|
+
ok: false,
|
|
241
|
+
error: 'No Figma plugin is connected to the bridge. Open the plugin in Figma first.',
|
|
242
|
+
hint: 'npx @createlex/figma-swiftui-mcp start --project ./MyApp',
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const maxDepth = Math.min(parseInt(req.query.maxDepth, 10) || 4, 8);
|
|
247
|
+
const requestId = `http-ctx-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
248
|
+
|
|
249
|
+
const response = await new Promise((resolve) => {
|
|
250
|
+
const timeout = setTimeout(() => {
|
|
251
|
+
pendingBridgeRequests.delete(requestId);
|
|
252
|
+
resolve({ ok: false, error: 'Timed out waiting for design context from plugin' });
|
|
253
|
+
}, 20000);
|
|
254
|
+
|
|
255
|
+
pendingBridgeRequests.set(requestId, {
|
|
256
|
+
origin: null,
|
|
257
|
+
action: 'get_design_context',
|
|
258
|
+
resolveCallback: (msg) => {
|
|
259
|
+
clearTimeout(timeout);
|
|
260
|
+
resolve(msg);
|
|
261
|
+
},
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
sendBridgeMessage(pluginBridgeClient, {
|
|
265
|
+
type: 'bridge-request',
|
|
266
|
+
requestId,
|
|
267
|
+
action: 'get_design_context',
|
|
268
|
+
params: { maxDepth, includeScreenshot: false },
|
|
269
|
+
protocolVersion: BRIDGE_PROTOCOL_VERSION,
|
|
270
|
+
timestamp: new Date().toISOString(),
|
|
271
|
+
});
|
|
272
|
+
broadcastBridgeStatus();
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
if (!response.ok) {
|
|
276
|
+
return res.status(502).json({ ok: false, error: response.error || 'Plugin returned an error' });
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
res.json({ ok: true, ...(response.data || {}) });
|
|
280
|
+
});
|
|
281
|
+
|
|
233
282
|
function sendBridgeMessage(ws, payload) {
|
|
234
283
|
if (!ws || ws.readyState !== WebSocket.OPEN) {
|
|
235
284
|
return false;
|
|
@@ -497,11 +546,15 @@ function startBridgeServer(options = {}) {
|
|
|
497
546
|
}
|
|
498
547
|
|
|
499
548
|
pendingBridgeRequests.delete(message.requestId);
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
549
|
+
if (typeof pending.resolveCallback === 'function') {
|
|
550
|
+
pending.resolveCallback(message);
|
|
551
|
+
} else {
|
|
552
|
+
sendBridgeMessage(pending.origin, {
|
|
553
|
+
...message,
|
|
554
|
+
protocolVersion: BRIDGE_PROTOCOL_VERSION,
|
|
555
|
+
timestamp: new Date().toISOString(),
|
|
556
|
+
});
|
|
557
|
+
}
|
|
505
558
|
broadcastBridgeStatus();
|
|
506
559
|
return;
|
|
507
560
|
}
|
package/package.json
CHANGED