@muloka/figma-console-mcp 0.5.0 → 0.5.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.
Files changed (111) hide show
  1. package/README.md +3 -1
  2. package/dist/core/port-discovery.d.ts +9 -0
  3. package/dist/core/port-discovery.d.ts.map +1 -1
  4. package/dist/core/port-discovery.js +40 -14
  5. package/dist/core/port-discovery.js.map +1 -1
  6. package/dist/core/websocket-connector.d.ts +2 -1
  7. package/dist/core/websocket-connector.d.ts.map +1 -1
  8. package/dist/core/websocket-connector.js +17 -2
  9. package/dist/core/websocket-connector.js.map +1 -1
  10. package/dist/core/websocket-server.d.ts +8 -1
  11. package/dist/core/websocket-server.d.ts.map +1 -1
  12. package/dist/core/websocket-server.js +18 -2
  13. package/dist/core/websocket-server.js.map +1 -1
  14. package/dist/core/write-tools.d.ts +3 -1
  15. package/dist/core/write-tools.d.ts.map +1 -1
  16. package/dist/core/write-tools.js +34 -14
  17. package/dist/core/write-tools.js.map +1 -1
  18. package/dist/local.d.ts +2 -1
  19. package/dist/local.d.ts.map +1 -1
  20. package/dist/local.js +10 -14
  21. package/dist/local.js.map +1 -1
  22. package/package.json +1 -1
  23. package/dist/apps/design-system-dashboard/mcp-app.html +0 -521
  24. package/dist/apps/token-browser/mcp-app.html +0 -410
  25. package/dist/cloudflare/apps/design-system-dashboard/scoring/accessibility.js +0 -277
  26. package/dist/cloudflare/apps/design-system-dashboard/scoring/component-metadata.js +0 -357
  27. package/dist/cloudflare/apps/design-system-dashboard/scoring/consistency.js +0 -341
  28. package/dist/cloudflare/apps/design-system-dashboard/scoring/coverage.js +0 -230
  29. package/dist/cloudflare/apps/design-system-dashboard/scoring/engine.js +0 -92
  30. package/dist/cloudflare/apps/design-system-dashboard/scoring/naming-semantics.js +0 -308
  31. package/dist/cloudflare/apps/design-system-dashboard/scoring/token-architecture.js +0 -349
  32. package/dist/cloudflare/apps/design-system-dashboard/scoring/types.js +0 -40
  33. package/dist/cloudflare/apps/design-system-dashboard/server.js +0 -159
  34. package/dist/cloudflare/apps/token-browser/server.js +0 -136
  35. package/dist/cloudflare/browser-manager.js +0 -157
  36. package/dist/cloudflare/core/accessibility-tools.js +0 -361
  37. package/dist/cloudflare/core/annotation-tools.js +0 -230
  38. package/dist/cloudflare/core/cloud-websocket-connector.js +0 -419
  39. package/dist/cloudflare/core/cloud-websocket-relay.js +0 -198
  40. package/dist/cloudflare/core/comment-tools.js +0 -292
  41. package/dist/cloudflare/core/config.js +0 -153
  42. package/dist/cloudflare/core/console-monitor.js +0 -427
  43. package/dist/cloudflare/core/deep-component-tools.js +0 -128
  44. package/dist/cloudflare/core/design-code-tools.js +0 -2793
  45. package/dist/cloudflare/core/design-system-manifest.js +0 -265
  46. package/dist/cloudflare/core/design-system-tools.js +0 -882
  47. package/dist/cloudflare/core/diagnose-tool.js +0 -100
  48. package/dist/cloudflare/core/diff/changelog-formatter.js +0 -275
  49. package/dist/cloudflare/core/diff/diff-engine.js +0 -334
  50. package/dist/cloudflare/core/diff/property-compare.js +0 -36
  51. package/dist/cloudflare/core/diff/version-cache.js +0 -74
  52. package/dist/cloudflare/core/enrichment/enrichment-service.js +0 -374
  53. package/dist/cloudflare/core/enrichment/index.js +0 -7
  54. package/dist/cloudflare/core/enrichment/relationship-mapper.js +0 -351
  55. package/dist/cloudflare/core/enrichment/style-resolver.js +0 -346
  56. package/dist/cloudflare/core/figjam-tools.js +0 -547
  57. package/dist/cloudflare/core/figma-api.js +0 -509
  58. package/dist/cloudflare/core/figma-connector.js +0 -7
  59. package/dist/cloudflare/core/figma-reconstruction-spec.js +0 -402
  60. package/dist/cloudflare/core/figma-style-extractor.js +0 -311
  61. package/dist/cloudflare/core/figma-tools.js +0 -3353
  62. package/dist/cloudflare/core/identity.js +0 -96
  63. package/dist/cloudflare/core/library-tools.js +0 -580
  64. package/dist/cloudflare/core/logger.js +0 -53
  65. package/dist/cloudflare/core/port-discovery.js +0 -935
  66. package/dist/cloudflare/core/resolve-package-root.js +0 -11
  67. package/dist/cloudflare/core/slides-tools.js +0 -714
  68. package/dist/cloudflare/core/slot-tools.js +0 -334
  69. package/dist/cloudflare/core/snippet-injector.js +0 -96
  70. package/dist/cloudflare/core/tokens/alias-resolver.js +0 -205
  71. package/dist/cloudflare/core/tokens/config.js +0 -294
  72. package/dist/cloudflare/core/tokens/dialect.js +0 -232
  73. package/dist/cloudflare/core/tokens/figma-converter.js +0 -323
  74. package/dist/cloudflare/core/tokens/formatters/css-vars.js +0 -338
  75. package/dist/cloudflare/core/tokens/formatters/dtcg.js +0 -376
  76. package/dist/cloudflare/core/tokens/formatters/index.js +0 -45
  77. package/dist/cloudflare/core/tokens/formatters/json.js +0 -205
  78. package/dist/cloudflare/core/tokens/formatters/less.js +0 -4
  79. package/dist/cloudflare/core/tokens/formatters/scss.js +0 -258
  80. package/dist/cloudflare/core/tokens/formatters/stubs.js +0 -13
  81. package/dist/cloudflare/core/tokens/formatters/style-dictionary-v3.js +0 -213
  82. package/dist/cloudflare/core/tokens/formatters/tailwind-v3.js +0 -237
  83. package/dist/cloudflare/core/tokens/formatters/tailwind-v4.js +0 -335
  84. package/dist/cloudflare/core/tokens/formatters/tokens-studio.js +0 -256
  85. package/dist/cloudflare/core/tokens/formatters/ts-module.js +0 -198
  86. package/dist/cloudflare/core/tokens/index.js +0 -16
  87. package/dist/cloudflare/core/tokens/parsers/css-vars.js +0 -4
  88. package/dist/cloudflare/core/tokens/parsers/dtcg.js +0 -280
  89. package/dist/cloudflare/core/tokens/parsers/index.js +0 -138
  90. package/dist/cloudflare/core/tokens/parsers/json.js +0 -7
  91. package/dist/cloudflare/core/tokens/parsers/scss.js +0 -4
  92. package/dist/cloudflare/core/tokens/parsers/stubs.js +0 -20
  93. package/dist/cloudflare/core/tokens/parsers/style-dictionary-v3.js +0 -4
  94. package/dist/cloudflare/core/tokens/parsers/tailwind-v3.js +0 -4
  95. package/dist/cloudflare/core/tokens/parsers/tailwind-v4.js +0 -4
  96. package/dist/cloudflare/core/tokens/parsers/tokens-studio.js +0 -4
  97. package/dist/cloudflare/core/tokens/schemas.js +0 -152
  98. package/dist/cloudflare/core/tokens/transforms/color.js +0 -12
  99. package/dist/cloudflare/core/tokens/transforms/index.js +0 -29
  100. package/dist/cloudflare/core/tokens/transforms/size.js +0 -7
  101. package/dist/cloudflare/core/tokens/types.js +0 -18
  102. package/dist/cloudflare/core/tokens-tools.js +0 -1788
  103. package/dist/cloudflare/core/types/design-code.js +0 -4
  104. package/dist/cloudflare/core/types/enriched.js +0 -5
  105. package/dist/cloudflare/core/types/index.js +0 -4
  106. package/dist/cloudflare/core/variable-resolver.js +0 -85
  107. package/dist/cloudflare/core/version-tools.js +0 -1199
  108. package/dist/cloudflare/core/websocket-connector.js +0 -436
  109. package/dist/cloudflare/core/websocket-server.js +0 -1009
  110. package/dist/cloudflare/core/write-tools.js +0 -2506
  111. package/dist/cloudflare/index.js +0 -3010
@@ -1,159 +0,0 @@
1
- /**
2
- * Design System Dashboard MCP App - Server Registration
3
- *
4
- * Registers tools and resource for the Design System Dashboard MCP App.
5
- * Uses the official @modelcontextprotocol/ext-apps helpers for proper
6
- * MCP Apps protocol compatibility with Claude Desktop.
7
- *
8
- * Data flow:
9
- * 1. LLM calls figma_audit_design_system → server fetches + scores data,
10
- * returns SHORT summary to LLM (avoids context exhaustion)
11
- * 2. UI opens, connects, calls ds_dashboard_refresh (app-only visibility)
12
- * 3. ds_dashboard_refresh returns full JSON → UI renders
13
- */
14
- import { readFile } from "node:fs/promises";
15
- import { dirname, resolve } from "node:path";
16
- import { fileURLToPath } from "node:url";
17
- import { RESOURCE_MIME_TYPE, registerAppResource, registerAppTool, } from "@modelcontextprotocol/ext-apps/server";
18
- import { z } from "zod";
19
- import { scoreDesignSystem } from "./scoring/engine.js";
20
- const DASHBOARD_URI = "ui://figma-console/design-system-dashboard";
21
- const __filename = fileURLToPath(import.meta.url);
22
- const __dirname = dirname(__filename);
23
- // Shared state
24
- let lastFileUrl;
25
- /**
26
- * Register the Design System Dashboard MCP App with the server.
27
- *
28
- * @param server - The MCP server instance
29
- * @param getDesignSystemData - Function to fetch raw design system data from Figma
30
- * @param getCurrentUrl - Optional function to get the current browser URL (for lastFileUrl tracking)
31
- */
32
- export function registerDesignSystemDashboardApp(server, getDesignSystemData, getCurrentUrl) {
33
- // Tool: fetches + scores data, returns SHORT summary to LLM
34
- registerAppTool(server, "figma_audit_design_system", {
35
- title: "Audit Design System Health",
36
- description: "Analyze the health and AI-readiness of a Figma file's design system. Produces a scored dashboard evaluating naming conventions, token architecture, component metadata, accessibility, consistency, and coverage. Results are displayed in the dashboard UI.",
37
- inputSchema: {
38
- fileUrl: z
39
- .string()
40
- .url()
41
- .optional()
42
- .describe("Figma file URL. If not provided, uses the currently active file."),
43
- },
44
- _meta: {
45
- ui: { resourceUri: DASHBOARD_URI },
46
- },
47
- }, async ({ fileUrl }) => {
48
- try {
49
- // Track the actual URL used (explicit or current browser URL)
50
- // This ensures ds_dashboard_refresh uses the correct file
51
- lastFileUrl = fileUrl || getCurrentUrl?.() || undefined;
52
- const data = await getDesignSystemData(fileUrl);
53
- const scored = scoreDesignSystem(data);
54
- const categorySummaries = scored.categories
55
- .map((c) => `${c.label}: ${c.score}/100`)
56
- .join(", ");
57
- const fileName = scored.fileInfo?.name || "Unknown file";
58
- const unavailableNote = scored.dataAvailability && !scored.dataAvailability.variables
59
- ? " Note: Variable/token data was unavailable (requires Enterprise plan or Desktop Bridge). Token Architecture scores reflect missing data, not actual quality."
60
- : "";
61
- return {
62
- content: [
63
- {
64
- type: "text",
65
- text: `Design System: ${fileName}. Health: ${scored.overall}/100 — ${scored.status}. ${categorySummaries}.${unavailableNote} The dashboard UI is now showing detailed results.`,
66
- },
67
- ],
68
- };
69
- }
70
- catch (error) {
71
- const errorMessage = error instanceof Error ? error.message : String(error);
72
- return {
73
- content: [
74
- {
75
- type: "text",
76
- text: `Design System Dashboard error: ${errorMessage}`,
77
- },
78
- ],
79
- isError: true,
80
- };
81
- }
82
- });
83
- // Tool: returns full JSON data (app-only, hidden from LLM)
84
- registerAppTool(server, "ds_dashboard_refresh", {
85
- title: "Dashboard Refresh",
86
- description: "Refresh dashboard data (called from MCP App UI)",
87
- inputSchema: {
88
- fileUrl: z
89
- .string()
90
- .url()
91
- .optional()
92
- .describe("Figma file URL to refresh data for."),
93
- },
94
- _meta: {
95
- ui: {
96
- resourceUri: DASHBOARD_URI,
97
- visibility: ["app"],
98
- },
99
- },
100
- }, async ({ fileUrl }) => {
101
- try {
102
- const url = fileUrl || lastFileUrl;
103
- const data = await getDesignSystemData(url);
104
- const scored = scoreDesignSystem(data);
105
- return {
106
- content: [
107
- {
108
- type: "text",
109
- text: JSON.stringify(scored),
110
- },
111
- ],
112
- };
113
- }
114
- catch (error) {
115
- const errorMessage = error instanceof Error ? error.message : String(error);
116
- return {
117
- content: [
118
- {
119
- type: "text",
120
- text: JSON.stringify({
121
- error: errorMessage,
122
- overall: 0,
123
- status: "poor",
124
- categories: [],
125
- summary: [],
126
- meta: {
127
- componentCount: 0,
128
- variableCount: 0,
129
- collectionCount: 0,
130
- styleCount: 0,
131
- componentSetCount: 0,
132
- standaloneCount: 0,
133
- variantCount: 0,
134
- timestamp: Date.now(),
135
- },
136
- }),
137
- },
138
- ],
139
- isError: true,
140
- };
141
- }
142
- });
143
- // Resource: serves the Vite-built HTML
144
- registerAppResource(server, "Design System Dashboard App", DASHBOARD_URI, {
145
- description: "Interactive dashboard for evaluating design system health and AI-readiness",
146
- }, async () => {
147
- const htmlPath = resolve(__dirname, "mcp-app.html");
148
- const html = await readFile(htmlPath, "utf-8");
149
- return {
150
- contents: [
151
- {
152
- uri: DASHBOARD_URI,
153
- mimeType: RESOURCE_MIME_TYPE,
154
- text: html,
155
- },
156
- ],
157
- };
158
- });
159
- }
@@ -1,136 +0,0 @@
1
- /**
2
- * Token Browser MCP App - Server Registration
3
- *
4
- * Registers tools and resource for the Token Browser MCP App.
5
- * Uses the official @modelcontextprotocol/ext-apps helpers for proper
6
- * MCP Apps protocol compatibility with Claude Desktop.
7
- *
8
- * Data flow:
9
- * 1. LLM calls figma_browse_tokens → server fetches + caches data,
10
- * returns SHORT summary to LLM (avoids context exhaustion)
11
- * 2. UI opens, connects, calls token_browser_refresh (app-only visibility)
12
- * 3. token_browser_refresh returns full JSON → UI renders
13
- */
14
- import { readFile } from "node:fs/promises";
15
- import { dirname, resolve } from "node:path";
16
- import { fileURLToPath } from "node:url";
17
- import { RESOURCE_MIME_TYPE, registerAppResource, registerAppTool, } from "@modelcontextprotocol/ext-apps/server";
18
- import { z } from "zod";
19
- const TOKEN_BROWSER_URI = "ui://figma-console/token-browser";
20
- const __filename = fileURLToPath(import.meta.url);
21
- const __dirname = dirname(__filename);
22
- /**
23
- * Register the Token Browser MCP App with the server.
24
- *
25
- * @param server - The MCP server instance
26
- * @param getVariablesHandler - Function to fetch variables data
27
- */
28
- export function registerTokenBrowserApp(server, getVariablesHandler) {
29
- // Shared state: remember last URL so refresh tool can reuse it
30
- let lastFileUrl;
31
- // Tool: fetches + caches data, returns SHORT summary to LLM
32
- registerAppTool(server, "figma_browse_tokens", {
33
- title: "Browse Design Tokens",
34
- description: "Open an interactive browser to explore design tokens (variables) from a Figma file. Shows tokens organized by collection with search, filtering, and mode switching. Data is displayed in the UI — do not attempt to list or describe the tokens in chat.",
35
- inputSchema: {
36
- fileUrl: z
37
- .string()
38
- .url()
39
- .optional()
40
- .describe("Figma file URL. If not provided, uses the currently active file."),
41
- },
42
- _meta: {
43
- ui: { resourceUri: TOKEN_BROWSER_URI },
44
- },
45
- }, async ({ fileUrl }) => {
46
- try {
47
- lastFileUrl = fileUrl;
48
- const result = await getVariablesHandler(fileUrl);
49
- const varCount = result.variables?.length || 0;
50
- const colCount = result.collections?.length || 0;
51
- // Count by type
52
- const colors = result.variables?.filter((v) => v.resolvedType === "COLOR")
53
- .length || 0;
54
- const numbers = result.variables?.filter((v) => v.resolvedType === "FLOAT")
55
- .length || 0;
56
- return {
57
- content: [
58
- {
59
- type: "text",
60
- text: `Token Browser opened: ${varCount} tokens across ${colCount} collections (${colors} colors, ${numbers} numbers). The interactive UI is now displaying the results — users can search, filter by type, and browse by collection.`,
61
- },
62
- ],
63
- };
64
- }
65
- catch (error) {
66
- const errorMessage = error instanceof Error ? error.message : String(error);
67
- return {
68
- content: [
69
- {
70
- type: "text",
71
- text: `Token Browser error: ${errorMessage}`,
72
- },
73
- ],
74
- isError: true,
75
- };
76
- }
77
- });
78
- // Tool: returns full JSON data (app-only, hidden from LLM)
79
- registerAppTool(server, "token_browser_refresh", {
80
- title: "Token Browser Refresh",
81
- description: "Refresh token data (called from MCP App UI)",
82
- inputSchema: {
83
- fileUrl: z
84
- .string()
85
- .url()
86
- .optional()
87
- .describe("Figma file URL to refresh data for."),
88
- },
89
- _meta: {
90
- ui: {
91
- resourceUri: TOKEN_BROWSER_URI,
92
- visibility: ["app"],
93
- },
94
- },
95
- }, async ({ fileUrl }) => {
96
- try {
97
- const url = fileUrl || lastFileUrl;
98
- const result = await getVariablesHandler(url);
99
- return {
100
- content: [{ type: "text", text: JSON.stringify(result) }],
101
- };
102
- }
103
- catch (error) {
104
- const errorMessage = error instanceof Error ? error.message : String(error);
105
- return {
106
- content: [
107
- {
108
- type: "text",
109
- text: JSON.stringify({
110
- error: errorMessage,
111
- variables: [],
112
- collections: [],
113
- }),
114
- },
115
- ],
116
- isError: true,
117
- };
118
- }
119
- });
120
- // Resource: serves the Vite-built HTML
121
- registerAppResource(server, "Token Browser App", TOKEN_BROWSER_URI, {
122
- description: "Interactive browser for exploring Figma design tokens and variables",
123
- }, async () => {
124
- const htmlPath = resolve(__dirname, "mcp-app.html");
125
- const html = await readFile(htmlPath, "utf-8");
126
- return {
127
- contents: [
128
- {
129
- uri: TOKEN_BROWSER_URI,
130
- mimeType: RESOURCE_MIME_TYPE,
131
- text: html,
132
- },
133
- ],
134
- };
135
- });
136
- }
@@ -1,157 +0,0 @@
1
- /**
2
- * Browser Manager
3
- * Manages Puppeteer browser instance lifecycle for Cloudflare Browser Rendering API
4
- */
5
- import puppeteer from '@cloudflare/puppeteer';
6
- import { createChildLogger } from './core/logger.js';
7
- const logger = createChildLogger({ component: 'browser-manager' });
8
- /**
9
- * Browser Manager
10
- * Handles browser instance creation, page management, and navigation
11
- */
12
- export class BrowserManager {
13
- constructor(env, config) {
14
- this.browser = null;
15
- this.page = null;
16
- this.env = env;
17
- this.config = config;
18
- }
19
- /**
20
- * Launch browser instance
21
- */
22
- async launch() {
23
- if (this.browser) {
24
- logger.info('Browser already running, reusing instance');
25
- return this.browser;
26
- }
27
- logger.info('Launching browser with Cloudflare Browser Rendering API');
28
- try {
29
- this.browser = await puppeteer.launch(this.env.BROWSER, {
30
- keep_alive: 600000, // Keep alive for 10 minutes
31
- });
32
- logger.info('Browser launched successfully');
33
- return this.browser;
34
- }
35
- catch (error) {
36
- logger.error({ error }, 'Failed to launch browser');
37
- throw new Error(`Browser launch failed: ${error}`);
38
- }
39
- }
40
- /**
41
- * Get or create a page instance
42
- */
43
- async getPage() {
44
- if (!this.browser) {
45
- await this.launch();
46
- }
47
- if (this.page && !this.page.isClosed()) {
48
- return this.page;
49
- }
50
- logger.info('Creating new browser page');
51
- this.page = await this.browser.newPage();
52
- // Set viewport size
53
- await this.page.setViewport({
54
- width: 1920,
55
- height: 1080,
56
- deviceScaleFactor: 1,
57
- });
58
- logger.info('Browser page created');
59
- return this.page;
60
- }
61
- /**
62
- * Navigate to Figma URL
63
- */
64
- async navigateToFigma(figmaUrl) {
65
- const page = await this.getPage();
66
- // Default to Figma homepage if no URL provided
67
- const url = figmaUrl || 'https://www.figma.com';
68
- logger.info({ url }, 'Navigating to Figma');
69
- try {
70
- await page.goto(url, {
71
- waitUntil: 'networkidle2',
72
- timeout: 30000,
73
- });
74
- logger.info({ url }, 'Navigation successful');
75
- return { page, action: 'navigated', url };
76
- }
77
- catch (error) {
78
- logger.error({ error, url }, 'Navigation failed');
79
- throw new Error(`Failed to navigate to ${url}: ${error}`);
80
- }
81
- }
82
- /**
83
- * Reload current page
84
- */
85
- async reload(hardReload = false) {
86
- if (!this.page || this.page.isClosed()) {
87
- throw new Error('No active page to reload');
88
- }
89
- logger.info({ hardReload }, 'Reloading page');
90
- try {
91
- await this.page.reload({
92
- waitUntil: 'networkidle2',
93
- timeout: 30000,
94
- });
95
- logger.info('Page reloaded successfully');
96
- }
97
- catch (error) {
98
- logger.error({ error }, 'Page reload failed');
99
- throw new Error(`Page reload failed: ${error}`);
100
- }
101
- }
102
- /**
103
- * Execute JavaScript in page context
104
- */
105
- async evaluate(fn) {
106
- const page = await this.getPage();
107
- return page.evaluate(fn);
108
- }
109
- // Screenshot functionality removed - use Figma REST API's getImages() instead
110
- // See: figma_take_screenshot and figma_get_component_image tools
111
- /**
112
- * Check if browser is running
113
- */
114
- isRunning() {
115
- return this.browser !== null && this.browser.isConnected();
116
- }
117
- /**
118
- * Close browser instance
119
- */
120
- async close() {
121
- if (!this.browser) {
122
- return;
123
- }
124
- logger.info('Closing browser');
125
- try {
126
- await this.browser.close();
127
- this.browser = null;
128
- this.page = null;
129
- logger.info('Browser closed successfully');
130
- }
131
- catch (error) {
132
- logger.error({ error }, 'Failed to close browser');
133
- throw error;
134
- }
135
- }
136
- /**
137
- * Get current page URL
138
- */
139
- getCurrentUrl() {
140
- if (!this.page || this.page.isClosed()) {
141
- return null;
142
- }
143
- return this.page.url();
144
- }
145
- /**
146
- * Wait for navigation
147
- */
148
- async waitForNavigation(timeout = 30000) {
149
- if (!this.page || this.page.isClosed()) {
150
- throw new Error('No active page');
151
- }
152
- await this.page.waitForNavigation({
153
- waitUntil: 'networkidle2',
154
- timeout,
155
- });
156
- }
157
- }