@mp3wizard/figma-console-mcp 1.22.2 → 1.22.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 +1 -1
- package/dist/apps/design-system-dashboard/mcp-app.html +78 -78
- package/dist/apps/token-browser/mcp-app.html +59 -60
- package/dist/cloudflare/core/write-tools.js +4 -4
- package/dist/core/write-tools.js +4 -4
- package/dist/core/write-tools.js.map +1 -1
- package/dist/local.js +4 -4
- package/dist/local.js.map +1 -1
- package/figma-desktop-bridge/code.js +173 -18
- package/package.json +1 -102
|
@@ -3289,6 +3289,7 @@ figma.ui.onmessage = async (msg) => {
|
|
|
3289
3289
|
'wcag-non-text-contrast', 'wcag-color-only', 'wcag-focus-indicator',
|
|
3290
3290
|
'wcag-letter-spacing', 'wcag-paragraph-spacing', 'wcag-image-alt',
|
|
3291
3291
|
'wcag-heading-hierarchy', 'wcag-reflow', 'wcag-reading-order',
|
|
3292
|
+
'wcag-disabled-no-context', 'token-misuse',
|
|
3292
3293
|
'hardcoded-color', 'no-text-style', 'default-name', 'detached-component',
|
|
3293
3294
|
'no-autolayout', 'empty-container'
|
|
3294
3295
|
];
|
|
@@ -3299,9 +3300,10 @@ figma.ui.onmessage = async (msg) => {
|
|
|
3299
3300
|
'wcag-contrast', 'wcag-text-size', 'wcag-target-size', 'wcag-line-height',
|
|
3300
3301
|
'wcag-non-text-contrast', 'wcag-color-only', 'wcag-focus-indicator',
|
|
3301
3302
|
'wcag-letter-spacing', 'wcag-paragraph-spacing', 'wcag-image-alt',
|
|
3302
|
-
'wcag-heading-hierarchy', 'wcag-reflow', 'wcag-reading-order'
|
|
3303
|
+
'wcag-heading-hierarchy', 'wcag-reflow', 'wcag-reading-order',
|
|
3304
|
+
'wcag-disabled-no-context'
|
|
3303
3305
|
],
|
|
3304
|
-
'design-system': ['hardcoded-color', 'no-text-style', 'default-name', 'detached-component'],
|
|
3306
|
+
'design-system': ['hardcoded-color', 'no-text-style', 'default-name', 'detached-component', 'token-misuse'],
|
|
3305
3307
|
'layout': ['no-autolayout', 'empty-container']
|
|
3306
3308
|
};
|
|
3307
3309
|
|
|
@@ -3310,15 +3312,17 @@ figma.ui.onmessage = async (msg) => {
|
|
|
3310
3312
|
'wcag-target-size': 'critical',
|
|
3311
3313
|
'wcag-non-text-contrast': 'critical',
|
|
3312
3314
|
'wcag-color-only': 'critical',
|
|
3315
|
+
'wcag-focus-indicator': 'critical',
|
|
3313
3316
|
'wcag-text-size': 'warning',
|
|
3314
|
-
'wcag-line-height': 'warning',
|
|
3315
|
-
'wcag-focus-indicator': 'warning',
|
|
3316
3317
|
'wcag-letter-spacing': 'warning',
|
|
3317
|
-
'wcag-paragraph-spacing': 'warning',
|
|
3318
3318
|
'wcag-image-alt': 'warning',
|
|
3319
3319
|
'wcag-heading-hierarchy': 'warning',
|
|
3320
3320
|
'wcag-reflow': 'warning',
|
|
3321
3321
|
'wcag-reading-order': 'warning',
|
|
3322
|
+
'wcag-disabled-no-context': 'warning',
|
|
3323
|
+
'wcag-line-height': 'info',
|
|
3324
|
+
'wcag-paragraph-spacing': 'info',
|
|
3325
|
+
'token-misuse': 'warning',
|
|
3322
3326
|
'hardcoded-color': 'warning',
|
|
3323
3327
|
'no-text-style': 'warning',
|
|
3324
3328
|
'default-name': 'warning',
|
|
@@ -3327,20 +3331,47 @@ figma.ui.onmessage = async (msg) => {
|
|
|
3327
3331
|
'empty-container': 'info'
|
|
3328
3332
|
};
|
|
3329
3333
|
|
|
3334
|
+
// WCAG conformance level per rule — lets teams filter by target level (AA vs AAA)
|
|
3335
|
+
var wcagLevelMap = {
|
|
3336
|
+
'wcag-contrast': 'aa', // 1.4.3 Contrast (Minimum) — Level AA
|
|
3337
|
+
'wcag-target-size': 'aa', // 2.5.8 Target Size (Minimum) — Level AA
|
|
3338
|
+
'wcag-non-text-contrast': 'aa', // 1.4.11 Non-text Contrast — Level AA
|
|
3339
|
+
'wcag-color-only': 'a', // 1.4.1 Use of Color — Level A
|
|
3340
|
+
'wcag-focus-indicator': 'aa', // 2.4.7 Focus Visible — Level AA
|
|
3341
|
+
'wcag-text-size': 'best-practice', // Not actually 1.4.4; 12px minimum is a readability best practice
|
|
3342
|
+
'wcag-line-height': 'best-practice', // 1.4.12 is about supporting user overrides, not requiring specific values
|
|
3343
|
+
'wcag-letter-spacing': 'best-practice', // Negative spacing actively harms readability
|
|
3344
|
+
'wcag-paragraph-spacing': 'best-practice', // 1.4.12 is about supporting user overrides
|
|
3345
|
+
'wcag-image-alt': 'a', // 1.1.1 Non-text Content — Level A
|
|
3346
|
+
'wcag-heading-hierarchy': 'a', // 1.3.1 Info and Relationships — Level A
|
|
3347
|
+
'wcag-reflow': 'aa', // 1.4.10 Reflow — Level AA
|
|
3348
|
+
'wcag-reading-order': 'a', // 1.3.2 Meaningful Sequence — Level A
|
|
3349
|
+
'wcag-disabled-no-context': 'aa', // 4.1.2 Name, Role, Value — disabled elements need ARIA context
|
|
3350
|
+
'token-misuse': 'design-system',
|
|
3351
|
+
'hardcoded-color': 'design-system',
|
|
3352
|
+
'no-text-style': 'design-system',
|
|
3353
|
+
'default-name': 'design-system',
|
|
3354
|
+
'detached-component': 'design-system',
|
|
3355
|
+
'no-autolayout': 'design-system',
|
|
3356
|
+
'empty-container': 'design-system'
|
|
3357
|
+
};
|
|
3358
|
+
|
|
3330
3359
|
var ruleDescriptions = {
|
|
3331
|
-
'wcag-contrast': 'Text does not meet WCAG AA contrast ratio (4.5:1 normal, 3:1 large)',
|
|
3332
|
-
'wcag-text-size': 'Text size is below 12px minimum',
|
|
3333
|
-
'wcag-target-size': 'Interactive element is smaller than 24x24px minimum target size',
|
|
3334
|
-
'wcag-line-height': 'Line height is
|
|
3335
|
-
'wcag-non-text-contrast': 'UI component or graphical object does not meet 3:1 contrast ratio against adjacent color (WCAG 1.4.11)',
|
|
3336
|
-
'wcag-color-only': '
|
|
3337
|
-
'wcag-focus-indicator': 'Interactive component is missing a focus/focused variant or focus indicator is insufficient (WCAG 2.4.7)',
|
|
3338
|
-
'wcag-letter-spacing': 'Negative letter spacing harms readability
|
|
3339
|
-
'wcag-paragraph-spacing': 'Paragraph spacing is
|
|
3340
|
-
'wcag-image-alt': 'Image or image fill has no description annotation for alternative text (WCAG 1.1.1)',
|
|
3341
|
-
'wcag-heading-hierarchy': 'Heading levels skip a level (e.g., H1 followed by H3)
|
|
3342
|
-
'wcag-reflow': 'Frame uses fixed positioning without auto-layout
|
|
3343
|
-
'wcag-reading-order': 'Visual position of elements does not match layer order
|
|
3360
|
+
'wcag-contrast': 'Text does not meet WCAG AA contrast ratio (4.5:1 normal, 3:1 large text ≥24px or ≥18.5px bold). Best practice: always target 4.5:1, especially in dark mode.',
|
|
3361
|
+
'wcag-text-size': 'Text size is below 12px — readability best practice. Note: WCAG 1.4.4 requires supporting 200% text-only zoom (use rem/em units), not a specific minimum size.',
|
|
3362
|
+
'wcag-target-size': 'Interactive element is smaller than 24x24px minimum target size (WCAG 2.5.8)',
|
|
3363
|
+
'wcag-line-height': 'Line height is below 1.5x font size — best practice for readability. Note: WCAG 1.4.12 requires that content does not break when users override spacing to 1.5x, not that designs must use 1.5x by default.',
|
|
3364
|
+
'wcag-non-text-contrast': 'UI component or graphical object does not meet 3:1 contrast ratio against adjacent color. Also applies to borders and chart elements against adjacent elements (WCAG 1.4.11)',
|
|
3365
|
+
'wcag-color-only': 'Information is conveyed only through color change (e.g., error state uses red border without an error message or icon). Color can supplement but must not be the sole indicator (WCAG 1.4.1)',
|
|
3366
|
+
'wcag-focus-indicator': 'Interactive component is missing a focus/focused variant or the focus indicator is insufficient. A visible focus state is critical — without it, keyboard users cannot navigate the interface (WCAG 2.4.7)',
|
|
3367
|
+
'wcag-letter-spacing': 'Negative letter spacing actively harms readability. WCAG 1.4.12 requires content to support user-overridden spacing without breaking.',
|
|
3368
|
+
'wcag-paragraph-spacing': 'Paragraph spacing is below 2x font size — best practice. WCAG 1.4.12 requires content to support user-overridden spacing to 2x without loss of content, not that designs must use 2x by default.',
|
|
3369
|
+
'wcag-image-alt': 'Image or image fill has no description annotation for alternative text. All images need alt text; decorative images should be explicitly marked as decorative. Graphs and charts also need long descriptions (e.g., a data table) (WCAG 1.1.1)',
|
|
3370
|
+
'wcag-heading-hierarchy': 'Heading levels skip a level (e.g., H1 followed by H3). Use H1 through H6 sequentially without skipping levels (WCAG 1.3.1)',
|
|
3371
|
+
'wcag-reflow': 'Frame uses fixed positioning without auto-layout. Content must support 400% zoom on 1280px viewport (equivalent to 320px minimum width) without horizontal scrolling or loss of content (WCAG 1.4.10)',
|
|
3372
|
+
'wcag-reading-order': 'Visual position of elements does not match layer order. Keyboard navigation and screen reader order must follow a logical sequence (WCAG 1.3.2)',
|
|
3373
|
+
'wcag-disabled-no-context': 'Disabled variant has no tooltip, helper text, or annotation explaining why the element is disabled. Use aria-disabled (not HTML disabled) to keep the element focusable for screen readers, and add a tooltip so all users understand the disabled reason.',
|
|
3374
|
+
'token-misuse': 'Variable name prefix does not match its usage context (e.g., a bg/* token used as a text fill, or a text/* token used as a background). This may cause contrast issues and indicates a misbound token.',
|
|
3344
3375
|
'hardcoded-color': 'Fill color is not bound to a variable or style',
|
|
3345
3376
|
'no-text-style': 'Text node is not using a text style',
|
|
3346
3377
|
'default-name': 'Node has a default Figma name (e.g., "Frame 1")',
|
|
@@ -3995,8 +4026,131 @@ figma.ui.onmessage = async (msg) => {
|
|
|
3995
4026
|
} catch (e) { /* slot sublayer */ }
|
|
3996
4027
|
}
|
|
3997
4028
|
|
|
4029
|
+
// wcag-disabled-no-context: Disabled variant without tooltip/helper text (Isabella's pattern)
|
|
4030
|
+
if (activeRuleSet['wcag-disabled-no-context'] && nodeType === 'COMPONENT_SET' && !truncated) {
|
|
4031
|
+
try {
|
|
4032
|
+
var csChildren = node.children;
|
|
4033
|
+
if (csChildren) {
|
|
4034
|
+
for (var dci = 0; dci < csChildren.length && !truncated; dci++) {
|
|
4035
|
+
var dcVariant = csChildren[dci];
|
|
4036
|
+
try {
|
|
4037
|
+
var dcName = dcVariant.name || '';
|
|
4038
|
+
if (/(disabled|inactive)/i.test(dcName)) {
|
|
4039
|
+
// Check if disabled variant has tooltip, helper text, or descriptive child
|
|
4040
|
+
var hasContextChild = false;
|
|
4041
|
+
try {
|
|
4042
|
+
if (dcVariant.children) {
|
|
4043
|
+
for (var dcci = 0; dcci < dcVariant.children.length; dcci++) {
|
|
4044
|
+
var dcChild = dcVariant.children[dcci];
|
|
4045
|
+
try {
|
|
4046
|
+
var dcChildName = (dcChild.name || '').toLowerCase();
|
|
4047
|
+
// Look for tooltip, helper text, hint, description, or error message children
|
|
4048
|
+
if (/tooltip|helper|hint|description|message|caption|note|info|why|reason/i.test(dcChildName)) {
|
|
4049
|
+
hasContextChild = true;
|
|
4050
|
+
break;
|
|
4051
|
+
}
|
|
4052
|
+
// Recurse one level for nested tooltip/helper
|
|
4053
|
+
if (dcChild.children) {
|
|
4054
|
+
for (var dcgci = 0; dcgci < dcChild.children.length; dcgci++) {
|
|
4055
|
+
var dcGrandchild = dcChild.children[dcgci];
|
|
4056
|
+
try {
|
|
4057
|
+
if (/tooltip|helper|hint|description|message/i.test(dcGrandchild.name || '')) {
|
|
4058
|
+
hasContextChild = true;
|
|
4059
|
+
break;
|
|
4060
|
+
}
|
|
4061
|
+
} catch (e) { /* skip */ }
|
|
4062
|
+
}
|
|
4063
|
+
if (hasContextChild) break;
|
|
4064
|
+
}
|
|
4065
|
+
} catch (e) { /* skip */ }
|
|
4066
|
+
}
|
|
4067
|
+
}
|
|
4068
|
+
} catch (e) { /* skip */ }
|
|
4069
|
+
// Also check component description for disabled guidance
|
|
4070
|
+
var hasDisabledAnnotation = false;
|
|
4071
|
+
try {
|
|
4072
|
+
var csDesc = (node.description || '').toLowerCase();
|
|
4073
|
+
if (/disabled.*tooltip|disabled.*helper|disabled.*hint|aria-disabled|why.*disabled|disabled.*reason/i.test(csDesc)) {
|
|
4074
|
+
hasDisabledAnnotation = true;
|
|
4075
|
+
}
|
|
4076
|
+
} catch (e) { /* skip */ }
|
|
4077
|
+
if (!hasContextChild && !hasDisabledAnnotation) {
|
|
4078
|
+
if (totalFindings < maxFindings) {
|
|
4079
|
+
findings['wcag-disabled-no-context'].push({
|
|
4080
|
+
id: dcVariant.id,
|
|
4081
|
+
name: nodeName + ' / ' + dcVariant.name,
|
|
4082
|
+
suggestion: 'Disabled elements should remain focusable (use aria-disabled, not HTML disabled). Add a tooltip or helper text explaining why the element is disabled so screen reader users understand the context.'
|
|
4083
|
+
});
|
|
4084
|
+
totalFindings++;
|
|
4085
|
+
} else { truncated = true; }
|
|
4086
|
+
}
|
|
4087
|
+
}
|
|
4088
|
+
} catch (e) { /* skip variant */ }
|
|
4089
|
+
}
|
|
4090
|
+
}
|
|
4091
|
+
} catch (e) { /* slot sublayer */ }
|
|
4092
|
+
}
|
|
4093
|
+
|
|
3998
4094
|
// ---- Design System checks ----
|
|
3999
4095
|
|
|
4096
|
+
// token-misuse: Variable name prefix doesn't match usage context
|
|
4097
|
+
if (activeRuleSet['token-misuse'] && !isPage && !isSection && !truncated) {
|
|
4098
|
+
try {
|
|
4099
|
+
var tmFills = node.fills;
|
|
4100
|
+
if (tmFills && tmFills.length > 0) {
|
|
4101
|
+
for (var tmi = 0; tmi < tmFills.length; tmi++) {
|
|
4102
|
+
var tmFill = tmFills[tmi];
|
|
4103
|
+
if (tmFill.type === 'SOLID' && tmFill.visible !== false) {
|
|
4104
|
+
try {
|
|
4105
|
+
if (tmFill.boundVariables && tmFill.boundVariables.color) {
|
|
4106
|
+
var tmVarId = tmFill.boundVariables.color.id;
|
|
4107
|
+
// Resolve variable name
|
|
4108
|
+
try {
|
|
4109
|
+
var tmVar = figma.variables.getVariableById(tmVarId);
|
|
4110
|
+
if (tmVar) {
|
|
4111
|
+
var tmVarName = tmVar.name.toLowerCase();
|
|
4112
|
+
var isBgToken = /^(bg|background|surface|fill)[\/-]/.test(tmVarName);
|
|
4113
|
+
var isTextNode = nodeType === 'TEXT';
|
|
4114
|
+
// Flag: bg/surface token used as text fill
|
|
4115
|
+
if (isTextNode && isBgToken) {
|
|
4116
|
+
if (totalFindings < maxFindings) {
|
|
4117
|
+
findings['token-misuse'].push({
|
|
4118
|
+
id: nodeId,
|
|
4119
|
+
name: nodeName,
|
|
4120
|
+
variable: tmVar.name,
|
|
4121
|
+
usage: 'text fill',
|
|
4122
|
+
expectedPrefix: 'text/*, fg/*, foreground/*',
|
|
4123
|
+
suggestion: 'This text node uses a background/surface token ("' + tmVar.name + '") as its fill color. This is likely a misbound token — use a text/foreground token instead.'
|
|
4124
|
+
});
|
|
4125
|
+
totalFindings++;
|
|
4126
|
+
} else { truncated = true; }
|
|
4127
|
+
}
|
|
4128
|
+
// Flag: text/foreground token used as frame/shape background
|
|
4129
|
+
var isTextToken = /^(text|fg|foreground|font)[\/-]/.test(tmVarName);
|
|
4130
|
+
var isContainerNode = nodeType === 'FRAME' || nodeType === 'COMPONENT' || nodeType === 'INSTANCE' || nodeType === 'RECTANGLE';
|
|
4131
|
+
if (isContainerNode && isTextToken && !truncated) {
|
|
4132
|
+
if (totalFindings < maxFindings) {
|
|
4133
|
+
findings['token-misuse'].push({
|
|
4134
|
+
id: nodeId,
|
|
4135
|
+
name: nodeName,
|
|
4136
|
+
variable: tmVar.name,
|
|
4137
|
+
usage: 'background fill',
|
|
4138
|
+
expectedPrefix: 'bg/*, background/*, surface/*',
|
|
4139
|
+
suggestion: 'This container uses a text/foreground token ("' + tmVar.name + '") as its background fill. This is likely a misbound token — use a background/surface token instead.'
|
|
4140
|
+
});
|
|
4141
|
+
totalFindings++;
|
|
4142
|
+
} else { truncated = true; }
|
|
4143
|
+
}
|
|
4144
|
+
}
|
|
4145
|
+
} catch (e) { /* can't resolve variable */ }
|
|
4146
|
+
}
|
|
4147
|
+
} catch (e) { /* no bound vars */ }
|
|
4148
|
+
}
|
|
4149
|
+
}
|
|
4150
|
+
}
|
|
4151
|
+
} catch (e) { /* slot sublayer */ }
|
|
4152
|
+
}
|
|
4153
|
+
|
|
4000
4154
|
// hardcoded-color: Solid fills without variable binding or style
|
|
4001
4155
|
if (activeRuleSet['hardcoded-color'] && !isPage && !isSection && !truncated) {
|
|
4002
4156
|
try {
|
|
@@ -4190,6 +4344,7 @@ figma.ui.onmessage = async (msg) => {
|
|
|
4190
4344
|
categories.push({
|
|
4191
4345
|
rule: ruleId,
|
|
4192
4346
|
severity: sev,
|
|
4347
|
+
wcagLevel: wcagLevelMap[ruleId] || null,
|
|
4193
4348
|
count: findings[ruleId].length,
|
|
4194
4349
|
description: ruleDescriptions[ruleId],
|
|
4195
4350
|
nodes: findings[ruleId]
|
package/package.json
CHANGED
|
@@ -1,102 +1 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@mp3wizard/figma-console-mcp",
|
|
3
|
-
"version": "1.22.2",
|
|
4
|
-
"description": "MCP server for accessing Figma plugin console logs and screenshots via Cloudflare Workers or local mode",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "dist/local.js",
|
|
7
|
-
"types": "dist/local.d.ts",
|
|
8
|
-
"bin": {
|
|
9
|
-
"figma-console-mcp": "./dist/local.js"
|
|
10
|
-
},
|
|
11
|
-
"files": [
|
|
12
|
-
"dist",
|
|
13
|
-
"figma-desktop-bridge",
|
|
14
|
-
"README.md",
|
|
15
|
-
"LICENSE"
|
|
16
|
-
],
|
|
17
|
-
"scripts": {
|
|
18
|
-
"prepublishOnly": "npm run build",
|
|
19
|
-
"deploy": "wrangler deploy",
|
|
20
|
-
"dev": "wrangler dev",
|
|
21
|
-
"dev:local": "tsx src/local.ts",
|
|
22
|
-
"build": "npm run build:local && npm run build:cloudflare && npm run build:apps",
|
|
23
|
-
"build:apps": "cross-env APP_NAME=token-browser vite build && cross-env APP_NAME=design-system-dashboard vite build",
|
|
24
|
-
"dev:apps": "vite build --watch",
|
|
25
|
-
"build:local": "tsc -p tsconfig.local.json",
|
|
26
|
-
"build:cloudflare": "tsc -p tsconfig.cloudflare.json",
|
|
27
|
-
"start": "wrangler dev",
|
|
28
|
-
"test": "jest",
|
|
29
|
-
"test:watch": "jest --watch",
|
|
30
|
-
"test:coverage": "jest --coverage",
|
|
31
|
-
"format": "biome format --write",
|
|
32
|
-
"lint:fix": "biome lint --fix",
|
|
33
|
-
"cf-typegen": "wrangler types",
|
|
34
|
-
"type-check": "tsc --noEmit"
|
|
35
|
-
},
|
|
36
|
-
"keywords": [
|
|
37
|
-
"mcp",
|
|
38
|
-
"figma",
|
|
39
|
-
"plugin",
|
|
40
|
-
"console",
|
|
41
|
-
"debugging",
|
|
42
|
-
"ai",
|
|
43
|
-
"anthropic",
|
|
44
|
-
"claude",
|
|
45
|
-
"cloudflare",
|
|
46
|
-
"workers"
|
|
47
|
-
],
|
|
48
|
-
"author": "Your Name",
|
|
49
|
-
"license": "MIT",
|
|
50
|
-
"repository": {
|
|
51
|
-
"type": "git",
|
|
52
|
-
"url": "https://github.com/mp3wizard/figma-console-mcp.git"
|
|
53
|
-
},
|
|
54
|
-
"engines": {
|
|
55
|
-
"node": ">=18.0.0"
|
|
56
|
-
},
|
|
57
|
-
"overrides": {
|
|
58
|
-
"path-to-regexp": ">=8.4.1",
|
|
59
|
-
"vite": {
|
|
60
|
-
"picomatch": ">=4.0.4"
|
|
61
|
-
},
|
|
62
|
-
"miniflare": {
|
|
63
|
-
"undici": ">=7.24.0"
|
|
64
|
-
},
|
|
65
|
-
"handlebars": ">=4.7.9",
|
|
66
|
-
"brace-expansion": ">=1.1.13",
|
|
67
|
-
"lodash": ">=4.18.0",
|
|
68
|
-
"picomatch": ">=4.0.4"
|
|
69
|
-
},
|
|
70
|
-
"dependencies": {
|
|
71
|
-
"@cloudflare/puppeteer": "^1.0.4",
|
|
72
|
-
"@modelcontextprotocol/ext-apps": "^1.0.1",
|
|
73
|
-
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
74
|
-
"agents": "^0.7.1",
|
|
75
|
-
"axe-core": "^4.11.2",
|
|
76
|
-
"chrome-remote-interface": "^0.33.2",
|
|
77
|
-
"jsdom": "^29.0.1",
|
|
78
|
-
"pino": "^9.5.0",
|
|
79
|
-
"pino-pretty": "^13.0.0",
|
|
80
|
-
"puppeteer-core": "^23.11.1",
|
|
81
|
-
"uuid": "^11.0.3",
|
|
82
|
-
"ws": "^8.19.0",
|
|
83
|
-
"zod": "^3.25.76"
|
|
84
|
-
},
|
|
85
|
-
"devDependencies": {
|
|
86
|
-
"@biomejs/biome": "^2.2.5",
|
|
87
|
-
"@types/jest": "^29.5.14",
|
|
88
|
-
"@types/jsdom": "^28.0.1",
|
|
89
|
-
"@types/node": "^22.10.2",
|
|
90
|
-
"@types/uuid": "^10.0.0",
|
|
91
|
-
"@types/ws": "^8.18.1",
|
|
92
|
-
"cross-env": "^7.0.3",
|
|
93
|
-
"jest": "^29.7.0",
|
|
94
|
-
"ts-jest": "^29.2.5",
|
|
95
|
-
"tsx": "^4.19.2",
|
|
96
|
-
"typescript": "5.9.3",
|
|
97
|
-
"vite": ">=6.4.2",
|
|
98
|
-
"vite-plugin-singlefile": "^2.0.0",
|
|
99
|
-
"wrangler": "^4.42.0",
|
|
100
|
-
"zod-to-json-schema": "^3.25.1"
|
|
101
|
-
}
|
|
102
|
-
}
|
|
1
|
+
{"name":"@mp3wizard/figma-console-mcp","version":"1.22.4","description":"MCP server for accessing Figma plugin console logs and screenshots via Cloudflare Workers or local mode","type":"module","main":"dist/local.js","types":"dist/local.d.ts","bin":{"figma-console-mcp":"./dist/local.js"},"files":["dist","figma-desktop-bridge","README.md","LICENSE"],"scripts":{"prepublishOnly":"npm run build","deploy":"wrangler deploy","dev":"wrangler dev","dev:local":"tsx src/local.ts","build":"npm run build:local && npm run build:cloudflare && npm run build:apps","build:apps":"cross-env APP_NAME=token-browser vite build && cross-env APP_NAME=design-system-dashboard vite build","dev:apps":"vite build --watch","build:local":"tsc -p tsconfig.local.json","build:cloudflare":"tsc -p tsconfig.cloudflare.json","start":"wrangler dev","test":"jest","test:watch":"jest --watch","test:coverage":"jest --coverage","format":"biome format --write","lint:fix":"biome lint --fix","cf-typegen":"wrangler types","type-check":"tsc --noEmit"},"keywords":["mcp","figma","plugin","console","debugging","ai","anthropic","claude","cloudflare","workers"],"author":"Your Name","license":"MIT","repository":{"type":"git","url":"https://github.com/mp3wizard/figma-console-mcp.git"},"engines":{"node":">=18.0.0"},"overrides":{"path-to-regexp":">=8.4.1","vite":{"picomatch":">=4.0.4"},"miniflare":{"undici":">=7.24.0"},"handlebars":">=4.7.9","brace-expansion":">=1.1.13","lodash":">=4.18.0","picomatch":">=4.0.4","hono":">=4.12.12","@hono/node-server":">=1.19.13"},"dependencies":{"@cloudflare/puppeteer":"^1.0.4","@modelcontextprotocol/ext-apps":"^1.0.1","@modelcontextprotocol/sdk":"^1.26.0","agents":"^0.7.1","axe-core":"^4.11.2","chrome-remote-interface":"^0.33.2","jsdom":"^29.0.1","pino":"^9.5.0","pino-pretty":"^13.0.0","puppeteer-core":"^23.11.1","uuid":"^11.0.3","ws":"^8.19.0","zod":"^3.25.76"},"devDependencies":{"@biomejs/biome":"^2.2.5","@types/jest":"^29.5.14","@types/jsdom":"^28.0.1","@types/node":"^22.10.2","@types/uuid":"^10.0.0","@types/ws":"^8.18.1","cross-env":"^7.0.3","jest":"^29.7.0","ts-jest":"^29.2.5","tsx":"^4.19.2","typescript":"5.9.3","vite":">=6.4.2","vite-plugin-singlefile":"^2.0.0","wrangler":"^4.42.0","zod-to-json-schema":"^3.25.1"}}
|