devlens-mcp 0.3.3 → 0.4.1

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 (121) hide show
  1. package/README.md +48 -38
  2. package/RELEASE_NOTES.md +253 -0
  3. package/dist/bin/cli.js +2 -0
  4. package/dist/bin/cli.js.map +1 -1
  5. package/dist/src/figma/figma-properties.d.ts +88 -0
  6. package/dist/src/figma/figma-properties.d.ts.map +1 -0
  7. package/dist/src/figma/figma-properties.js +121 -0
  8. package/dist/src/figma/figma-properties.js.map +1 -0
  9. package/dist/src/figma/figma-structure.d.ts +43 -0
  10. package/dist/src/figma/figma-structure.d.ts.map +1 -0
  11. package/dist/src/figma/figma-structure.js +74 -0
  12. package/dist/src/figma/figma-structure.js.map +1 -0
  13. package/dist/src/figma/figma-url.d.ts +37 -0
  14. package/dist/src/figma/figma-url.d.ts.map +1 -0
  15. package/dist/src/figma/figma-url.js +68 -0
  16. package/dist/src/figma/figma-url.js.map +1 -0
  17. package/dist/src/jds-tokens/resolve-token.d.ts +2 -0
  18. package/dist/src/jds-tokens/resolve-token.d.ts.map +1 -0
  19. package/dist/src/jds-tokens/resolve-token.js +24 -0
  20. package/dist/src/jds-tokens/resolve-token.js.map +1 -0
  21. package/dist/src/jds-tokens/tokens.d.ts +2 -0
  22. package/dist/src/jds-tokens/tokens.d.ts.map +1 -0
  23. package/dist/src/jds-tokens/tokens.js +12 -0
  24. package/dist/src/jds-tokens/tokens.js.map +1 -0
  25. package/dist/src/platform/ios/ios-device.d.ts +2 -0
  26. package/dist/src/platform/ios/ios-device.d.ts.map +1 -1
  27. package/dist/src/platform/ios/ios-device.js +18 -8
  28. package/dist/src/platform/ios/ios-device.js.map +1 -1
  29. package/dist/src/platform/ios/scale-resolver.d.ts +29 -0
  30. package/dist/src/platform/ios/scale-resolver.d.ts.map +1 -0
  31. package/dist/src/platform/ios/scale-resolver.js +114 -0
  32. package/dist/src/platform/ios/scale-resolver.js.map +1 -0
  33. package/dist/src/platform/ios/simctl.d.ts +5 -0
  34. package/dist/src/platform/ios/simctl.d.ts.map +1 -1
  35. package/dist/src/platform/ios/simctl.js +4 -0
  36. package/dist/src/platform/ios/simctl.js.map +1 -1
  37. package/dist/src/server.d.ts.map +1 -1
  38. package/dist/src/server.js +9 -1
  39. package/dist/src/server.js.map +1 -1
  40. package/dist/src/setup/config-patcher.d.ts +2 -0
  41. package/dist/src/setup/config-patcher.d.ts.map +1 -0
  42. package/dist/src/setup/config-patcher.js +128 -0
  43. package/dist/src/setup/config-patcher.js.map +1 -0
  44. package/dist/src/setup/shell-detector.d.ts +10 -0
  45. package/dist/src/setup/shell-detector.d.ts.map +1 -0
  46. package/dist/src/setup/shell-detector.js +72 -0
  47. package/dist/src/setup/shell-detector.js.map +1 -0
  48. package/dist/src/snapshot/device-properties.d.ts +53 -0
  49. package/dist/src/snapshot/device-properties.d.ts.map +1 -0
  50. package/dist/src/snapshot/device-properties.js +94 -0
  51. package/dist/src/snapshot/device-properties.js.map +1 -0
  52. package/dist/src/snapshot/formatter.d.ts +13 -5
  53. package/dist/src/snapshot/formatter.d.ts.map +1 -1
  54. package/dist/src/snapshot/formatter.js +28 -19
  55. package/dist/src/snapshot/formatter.js.map +1 -1
  56. package/dist/src/snapshot/layout-inference.d.ts +44 -0
  57. package/dist/src/snapshot/layout-inference.d.ts.map +1 -0
  58. package/dist/src/snapshot/layout-inference.js +138 -0
  59. package/dist/src/snapshot/layout-inference.js.map +1 -0
  60. package/dist/src/tools/analyze-tools.d.ts +60 -0
  61. package/dist/src/tools/analyze-tools.d.ts.map +1 -0
  62. package/dist/src/tools/analyze-tools.js +196 -0
  63. package/dist/src/tools/analyze-tools.js.map +1 -0
  64. package/dist/src/tools/interaction-tools.d.ts +6 -6
  65. package/dist/src/tools/interaction-tools.d.ts.map +1 -1
  66. package/dist/src/tools/interaction-tools.js +12 -2
  67. package/dist/src/tools/interaction-tools.js.map +1 -1
  68. package/dist/src/tools/metro-tools.d.ts +2 -2
  69. package/dist/src/tools/navigation-tools.d.ts.map +1 -1
  70. package/dist/src/tools/navigation-tools.js +6 -1
  71. package/dist/src/tools/navigation-tools.js.map +1 -1
  72. package/dist/src/tools/screenshot-tools.d.ts +75 -0
  73. package/dist/src/tools/screenshot-tools.d.ts.map +1 -1
  74. package/dist/src/tools/screenshot-tools.js +238 -8
  75. package/dist/src/tools/screenshot-tools.js.map +1 -1
  76. package/dist/src/tools/snapshot-tools.d.ts +15 -0
  77. package/dist/src/tools/snapshot-tools.d.ts.map +1 -1
  78. package/dist/src/tools/snapshot-tools.js +32 -1
  79. package/dist/src/tools/snapshot-tools.js.map +1 -1
  80. package/dist/src/tools/vqa-tools.d.ts +62 -0
  81. package/dist/src/tools/vqa-tools.d.ts.map +1 -0
  82. package/dist/src/tools/vqa-tools.js +204 -0
  83. package/dist/src/tools/vqa-tools.js.map +1 -0
  84. package/dist/src/utils/image-preprocess.d.ts +1 -1
  85. package/dist/src/utils/image-preprocess.d.ts.map +1 -1
  86. package/dist/src/utils/image-preprocess.js +79 -0
  87. package/dist/src/utils/image-preprocess.js.map +1 -1
  88. package/dist/src/visual/color-extractor.d.ts +37 -0
  89. package/dist/src/visual/color-extractor.d.ts.map +1 -0
  90. package/dist/src/visual/color-extractor.js +116 -0
  91. package/dist/src/visual/color-extractor.js.map +1 -0
  92. package/dist/src/visual/comparator.d.ts +21 -0
  93. package/dist/src/visual/comparator.d.ts.map +1 -1
  94. package/dist/src/visual/comparator.js +110 -13
  95. package/dist/src/visual/comparator.js.map +1 -1
  96. package/dist/src/visual/layout-analyzer.d.ts.map +1 -1
  97. package/dist/src/visual/layout-analyzer.js +17 -7
  98. package/dist/src/visual/layout-analyzer.js.map +1 -1
  99. package/dist/src/visual/node-matcher.d.ts +43 -0
  100. package/dist/src/visual/node-matcher.d.ts.map +1 -0
  101. package/dist/src/visual/node-matcher.js +190 -0
  102. package/dist/src/visual/node-matcher.js.map +1 -0
  103. package/dist/src/visual/property-comparator.d.ts +49 -0
  104. package/dist/src/visual/property-comparator.d.ts.map +1 -0
  105. package/dist/src/visual/property-comparator.js +246 -0
  106. package/dist/src/visual/property-comparator.js.map +1 -0
  107. package/dist/src/visual/structural-comparator.d.ts +46 -0
  108. package/dist/src/visual/structural-comparator.d.ts.map +1 -0
  109. package/dist/src/visual/structural-comparator.js +293 -0
  110. package/dist/src/visual/structural-comparator.js.map +1 -0
  111. package/dist/src/visual/vqa-analyzer.d.ts +30 -0
  112. package/dist/src/visual/vqa-analyzer.d.ts.map +1 -0
  113. package/dist/src/visual/vqa-analyzer.js +271 -0
  114. package/dist/src/visual/vqa-analyzer.js.map +1 -0
  115. package/docs/figma-workflow.md +210 -40
  116. package/docs/setup-guide.md +104 -40
  117. package/docs/tool-reference.md +137 -11
  118. package/package.json +1 -1
  119. package/tsconfig.json +1 -1
  120. package/INSTALLATION_GUIDE.md +0 -3
  121. package/QUICK_START.md +0 -3
package/README.md CHANGED
@@ -5,9 +5,9 @@
5
5
  DevLens gives AI agents the ability to **see, interact with, and verify** your mobile app running on a simulator or emulator. It bridges the gap between "AI writes code" and "AI confirms the code works" — enabling a fully automated **design-to-code-to-verification loop**.
6
6
 
7
7
  ```
8
- Figma Design ──► AI Agent ──► Code Changes ──► Hot Reload ──► Screenshot ──► Compare
9
-
10
- └───────────────── Fix & repeat until > 95% match ──────────────────┘
8
+ Figma Design ──► AI Agent ──► Code Changes ──► Hot Reload ──► Screenshot ──► Compare ──► VQA Validate
9
+
10
+ └──────────────────── Fix & repeat until 100% match (zero VQA) ────────────────────┘
11
11
  ```
12
12
 
13
13
  ---
@@ -19,31 +19,14 @@ Figma Design ──► AI Agent ──► Code Changes ──► Hot Reloa
19
19
  claude mcp add devlens -- npx devlens-mcp@latest
20
20
  ```
21
21
 
22
- ### Cursor IDE
23
- Add to `~/.cursor/mcp.json`:
22
+ ### Cursor IDE / Claude Desktop
23
+ Add to `~/.cursor/mcp.json` (Cursor) or `~/Library/Application Support/Claude/claude_desktop_config.json` (Desktop):
24
24
  ```json
25
25
  {
26
26
  "mcpServers": {
27
27
  "devlens": {
28
- "command": "npx",
29
- "args": ["devlens-mcp@latest"],
30
- "env": {
31
- "METRO_PORT": "8081",
32
- "FIGMA_TOKEN": "figd_xxxxx"
33
- }
34
- }
35
- }
36
- }
37
- ```
38
-
39
- ### Claude Desktop
40
- Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
41
- ```json
42
- {
43
- "mcpServers": {
44
- "devlens": {
45
- "command": "npx",
46
- "args": ["devlens-mcp@latest"],
28
+ "command": "/bin/zsh",
29
+ "args": ["-l", "-c", "npx devlens-mcp@latest"],
47
30
  "env": {
48
31
  "METRO_PORT": "8081",
49
32
  "FIGMA_TOKEN": "figd_xxxxx"
@@ -55,6 +38,8 @@ Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
55
38
 
56
39
  Restart your AI client after editing the config.
57
40
 
41
+ > **v0.4.0+**: DevLens now auto-detects your shell and `node` path on startup. It will patch MCP config files automatically if it detects a misconfigured shell or node path. See [setup guide](./docs/setup-guide.md) for details.
42
+
58
43
  ---
59
44
 
60
45
  ## What Problems Does It Solve?
@@ -75,6 +60,19 @@ Without DevLens, AI agents resort to manual, error-prone workflows:
75
60
 
76
61
  ---
77
62
 
63
+ ## New in v0.4.0
64
+
65
+ - **Auto-Detect Shell & Node Path** — DevLens now auto-detects your shell (bash/zsh/fish), finds the correct `node`/`npx` path, and auto-patches MCP config files if they are misconfigured. No more "node not found" errors.
66
+ - **VQA Validator** — new `devlens_vqa_validate` tool runs comprehensive Visual Quality Assurance against Figma designs. Checks spacing, colors, alignment, sizing, and missing/extra elements. Returns a structured VQA report with fix suggestions. Goal: zero VQA tickets from designer team.
67
+ - **Smart Analysis Depth** — new `devlens_analyze` tool with configurable scope: `minimal` (quick diff, no layout report), `targeted` (compare specific elements only), `full` (complete analysis). `devlens_compare_with_figma` now has a `depth` parameter (`quick`/`standard`/`thorough`).
68
+ - **Status Bar & Nav Bar Exclusion** — comparisons now auto-exclude volatile status bar (time, battery) and navigation bar regions. Reduces false-positive diffs by 3-5%.
69
+ - **Perceptual Comparison Mode** — new SSIM-inspired block-based comparison tolerates anti-aliasing and sub-pixel font rendering differences. Enable with `perceptual: true` or use `depth: "thorough"`.
70
+ - **Smart Figma Preprocessing** — new `"smart"` strategy combines rounded corner masking, histogram-guided artifact removal, and residual border trimming for cleaner Figma exports.
71
+ - **Scoped Snapshots** — `devlens_snapshot` now supports `scope: "component"` to capture only a subtree of a specific ref, reducing token usage for targeted checks.
72
+ - **Improved Verdict Thresholds** — layout analyzer thresholds tuned: "excellent" raised to 95%, sub-pixel alignment padding added to reduce off-by-one edge mismatches.
73
+
74
+ ---
75
+
78
76
  ## New in v0.3.1
79
77
 
80
78
  - **Layout-Aware Comparison** — `devlens_compare_with_figma` now reports per-element similarity scores using the accessibility tree. Instead of a single misleading global pixel-diff number, you get `"Header: 94%, ChatInput: 61%, ToolsGrid: 44% ← investigate"`. Set `layoutReport: false` to disable.
@@ -102,7 +100,7 @@ Without DevLens, AI agents resort to manual, error-prone workflows:
102
100
 
103
101
  ---
104
102
 
105
- ## Tools (34)
103
+ ## Tools (37)
106
104
 
107
105
  ### Device Management (3)
108
106
  | Tool | Description |
@@ -140,7 +138,7 @@ Without DevLens, AI agents resort to manual, error-prone workflows:
140
138
  | `devlens_fill_form` | Fill multiple fields at once |
141
139
  | `devlens_capture_flow` | Batch execute actions + capture labeled screenshots |
142
140
 
143
- ### Screenshots & Visual (5)
141
+ ### Screenshots & Visual (6)
144
142
  | Tool | Description |
145
143
  |------|-------------|
146
144
  | `devlens_screenshot` | Take screenshot (base64 + file) |
@@ -148,6 +146,7 @@ Without DevLens, AI agents resort to manual, error-prone workflows:
148
146
  | `devlens_element_screenshot` | Screenshot a specific element |
149
147
  | `devlens_compare_images` | A/B compare two saved screenshots |
150
148
  | `devlens_compare_with_figma` | Compare device screen against Figma design with per-element layout report |
149
+ | `devlens_compare_properties` | Compare ALL design properties (text sizes, colors, spacing, dimensions) per component against Figma |
151
150
 
152
151
  ### React Native / Metro (6)
153
152
  | Tool | Description |
@@ -170,6 +169,12 @@ Without DevLens, AI agents resort to manual, error-prone workflows:
170
169
  |------|-------------|
171
170
  | `devlens_ds_context` | Load design tokens, component interfaces, and usage patterns from your codebase |
172
171
 
172
+ ### Analysis & VQA (2)
173
+ | Tool | Description |
174
+ |------|-------------|
175
+ | `devlens_analyze` | Smart analysis with configurable depth (minimal/targeted/full). Respects scope of request — minimal changes get minimal analysis. |
176
+ | `devlens_vqa_validate` | Run VQA validation against Figma. Checks spacing, color, alignment, sizing, missing elements. Returns issues + fix suggestions. |
177
+
173
178
  ---
174
179
 
175
180
  ## The Figma Verification Workflow
@@ -177,17 +182,17 @@ Without DevLens, AI agents resort to manual, error-prone workflows:
177
182
  DevLens integrates with Figma to create an automated design verification loop:
178
183
 
179
184
  ```
180
- ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
181
- │ Figma │────►│ AI │────►│ Code │────►│ Device │
182
- │ Design │ │ Agent │ │ Editor │ │ Screen │
183
- └──────────┘ └──────┬───┘ └──────────┘ └────┬─────┘
184
-
185
- │◄─── devlens_compare ───────────┘
186
- │ (similarity < 95%?)
185
+ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
186
+ │ Figma │────►│ AI │────►│ Code │────►│ Device │────►│ VQA
187
+ │ Design │ │ Agent │ │ Editor │ │ Screen │ │ Validate │
188
+ └──────────┘ └──────┬───┘ └──────────┘ └──────────┘ └────┬─────┘
189
+
190
+ │◄─── devlens_vqa_validate ──────────────────────┘
191
+ │ (issues found?)
187
192
  │ │
188
193
  ▼ ▼
189
- Fix Code ◄─── Layout Report
190
- (per-element scores)
194
+ Fix Code ◄─── VQA Report
195
+ (spacing, color, alignment issues + fix suggestions)
191
196
  ```
192
197
 
193
198
  ### Step-by-step:
@@ -199,9 +204,11 @@ DevLens integrates with Figma to create an automated design verification loop:
199
204
  5. **Hot reload** — `devlens_hot_reload` triggers Metro fast refresh
200
205
  6. **Wait for stability** — `devlens_wait_for_screen` waits until UI stops changing
201
206
  7. **Validate elements** — `devlens_snapshot(validate: true)` catches invisible/zero-size elements
202
- 8. **Compare with Figma** — `devlens_compare_with_figma(figmaUrl: "...")` returns device screenshot, Figma reference, diff image, and per-element layout scores
203
- 9. **Analyze diff** — AI reads which elements are `poor`/`partial` and fixes those specifically
204
- 10. **Fix & repeat** — Adjust code until overall similarity > 95%
207
+ 8. **Quick check** — `devlens_compare_with_figma(figmaUrl: "...", depth: "quick")` for fast iteration
208
+ 9. **Property comparison** — `devlens_compare_properties(figmaUrl: "...")` for per-component mismatches (font size, color, spacing, dimensions)
209
+ 10. **VQA validation** — `devlens_vqa_validate(figmaUrl: "...")` runs full VQA: spacing, colors, alignment, sizing, missing elements
210
+ 11. **Fix issues** — AI reads VQA/property reports with fix suggestions and applies fixes
211
+ 12. **Repeat** — Run VQA again until status is `PASS` (zero VQA issues for designers)
205
212
 
206
213
  ---
207
214
 
@@ -325,6 +332,9 @@ Configure via `devlens.config.json` in your app root (see [Setup Guide](./docs/s
325
332
  | "File not exportable" on Figma compare | Disable "Prevent viewers from copying and exporting" in Figma share settings |
326
333
  | `devlens_ds_context` returns empty | Set `DEVLENS_CONFIG` env var to your `devlens.config.json` path |
327
334
  | Comparison similarity always low | Run `devlens_snapshot` first so layout report has element bounds to work with |
335
+ | Status bar causing false diffs | Use `excludeSystemBars: "auto"` (default in v0.4.0) or `"ios"`/`"android"` |
336
+ | VQA report empty | Run `devlens_snapshot` first to populate element refs before `devlens_vqa_validate` |
337
+ | Shell/node path wrong in MCP config | v0.4.0 auto-patches on startup; check logs for `[devlens] Patched` messages |
328
338
 
329
339
  ---
330
340
 
@@ -0,0 +1,253 @@
1
+ # DevLens v0.4.0 — Release Notes
2
+
3
+ **Release Date:** March 2026
4
+ **Previous Version:** v0.3.3
5
+ **npm:** `npx devlens-mcp@latest`
6
+
7
+ ---
8
+
9
+ ## Headline
10
+
11
+ DevLens v0.4.0 introduces **VQA validation**, **auto-config detection**, **smart analysis depth**, and **enhanced visual matching** — enabling a workflow where designers receive builds with **zero VQA tickets**.
12
+
13
+ ---
14
+
15
+ ## What's New
16
+
17
+ ### 1. Auto-Detect Shell & Node Path
18
+
19
+ **Problem:** Developers manually configured `/bin/zsh`, `/bin/bash`, and `node`/`npx` paths in MCP server JSON. Wrong path = silent failure.
20
+
21
+ **Now:** DevLens auto-detects on every startup:
22
+ - Reads `$SHELL` to find your shell (bash, zsh, fish)
23
+ - Runs `which node` / `which npx` inside your login shell profile
24
+ - Falls back to common paths: nvm, volta, fnm, homebrew, nodenv, asdf
25
+ - Scans all MCP config files (Cursor, Claude Desktop, Claude Code)
26
+ - If a mismatch is found, **auto-patches** the JSON (with `.bak` backup)
27
+
28
+ **Result:** "node not found" errors are gone. New developers just paste the default config and it works.
29
+
30
+ **Common misconfiguration auto-fixed:**
31
+ If you had a config like this (using `node` with shell flags — broken):
32
+ ```json
33
+ {
34
+ "command": "/opt/homebrew/bin/node",
35
+ "args": ["-l", "-c", "npx devlens-mcp@latest"]
36
+ }
37
+ ```
38
+ DevLens v0.4.0 detects that `node` doesn't understand `-l` / `-c` (those are shell flags) and auto-patches to:
39
+ ```json
40
+ {
41
+ "command": "/bin/zsh",
42
+ "args": ["-l", "-c", "npx devlens-mcp@latest"]
43
+ }
44
+ ```
45
+ A `.bak` backup is created before any patch.
46
+
47
+ **Do developers need to change their config?** **No.** The recommended config is the same as always:
48
+ ```json
49
+ {
50
+ "mcpServers": {
51
+ "devlens": {
52
+ "command": "/bin/zsh",
53
+ "args": ["-l", "-c", "npx devlens-mcp@latest"],
54
+ "env": {
55
+ "METRO_PORT": "8081",
56
+ "FIGMA_TOKEN": "figd_xxxxx"
57
+ }
58
+ }
59
+ }
60
+ }
61
+ ```
62
+ If your existing config has incorrect paths, DevLens fixes it on startup. No action needed.
63
+
64
+ **New files:**
65
+ - `src/setup/shell-detector.ts` — shell & node path detection
66
+ - `src/setup/config-patcher.ts` — MCP config auto-patcher
67
+
68
+ ---
69
+
70
+ ### 2. VQA Validator — Zero Designer Tickets
71
+
72
+ **Problem:** Traditional workflow wastes 2-3 days: Dev builds → Designer reviews → 15 VQA tickets → Dev fixes → More tickets → Repeat.
73
+
74
+ **Now:** `devlens_vqa_validate` runs comprehensive Visual QA against Figma before the designer ever sees the build.
75
+
76
+ **What it checks:**
77
+ | Category | What it validates |
78
+ |----------|-------------------|
79
+ | Spacing | Gaps between elements vs Figma specs |
80
+ | Colors | Dominant colors per region (CIE76 Delta-E) |
81
+ | Alignment | Element center/edge positions |
82
+ | Sizing | Width/height within 5% tolerance |
83
+ | Missing | Regions with <60% match (content probably missing) |
84
+ | Extra | Elements on device not in Figma |
85
+ | Typography | Font sizes/weights via accessibility tree |
86
+
87
+ **VQA Report format:**
88
+ ```
89
+ === VQA Report: WARNING ===
90
+ Overall Score: 91.3%
91
+ Issues: 3 (0 critical, 2 major, 1 minor)
92
+
93
+ --- Issues ---
94
+ 1. [MAJOR] [spacing] Gap between [e3] and [e5]: expected 12px, actual 20px
95
+ 2. [MAJOR] [color] Color mismatch on [e7]: expected #1A73E8, actual #2196F3
96
+ 3. [minor] [alignment] Element [e2] off by (3, 2)px
97
+
98
+ --- Suggested Fixes ---
99
+ 1. [high] Adjust margin/padding on [e3] to 12px gap.
100
+ 2. [high] Update color for [e7] to #1A73E8. Check design token mapping.
101
+ 3. [medium] Fix alignment of [e2] — adjust flex alignment.
102
+ ```
103
+
104
+ **Developer workflow — just paste this prompt in Cursor:**
105
+ ```
106
+ Build the HomeScreen from this Figma and make sure VQA passes with zero issues:
107
+ https://figma.com/design/ABC123/MyApp?node-id=10-200
108
+
109
+ Run VQA after building. Fix all issues. Re-run until PASS.
110
+ ```
111
+
112
+ **New files:**
113
+ - `src/tools/vqa-tools.ts` — `devlens_vqa_validate` tool
114
+ - `src/visual/vqa-analyzer.ts` — VQA analysis engine (spacing, sizing, alignment, color, missing/extra)
115
+ - `src/visual/color-extractor.ts` — dominant color extraction & CIE76 Delta-E comparison
116
+
117
+ ---
118
+
119
+ ### 3. Smart Analysis Depth
120
+
121
+ **Problem:** DevLens always ran full analysis — full snapshot + full layout report + full comparison. For a small padding change, this was overkill and slow.
122
+
123
+ **Now:** Analysis respects the scope of the request:
124
+
125
+ | Tool / Param | When to use | What it does |
126
+ |--------------|-------------|--------------|
127
+ | `devlens_analyze(scope: "minimal")` | Small CSS tweak | Quick pixel diff, no layout report |
128
+ | `devlens_analyze(scope: "targeted", targetRefs: ["e5"])` | Check one component | Inspects only specified elements |
129
+ | `devlens_analyze(scope: "full")` | Full screen build | Complete snapshot + layout + comparison |
130
+ | `devlens_compare_with_figma(depth: "quick")` | Fast iteration | Skip layout report, loose threshold |
131
+ | `devlens_compare_with_figma(depth: "standard")` | Normal compare | Current v0.3 behavior |
132
+ | `devlens_compare_with_figma(depth: "thorough")` | Final check | Per-element + perceptual + VQA hints |
133
+ | `devlens_snapshot(scope: "component", componentRef: "e3")` | Reduce tokens | Capture only a subtree |
134
+
135
+ **New file:** `src/tools/analyze-tools.ts`
136
+
137
+ ---
138
+
139
+ ### 4. Enhanced Visual Matching (95% → 100%)
140
+
141
+ Four improvements that eliminate the 5% false-positive gap:
142
+
143
+ #### 4a. Status Bar & Nav Bar Exclusion
144
+ - Auto-detects iOS or Android from image dimensions
145
+ - Masks status bar (time, battery, signal) and nav bar (home indicator)
146
+ - Enabled by default: `excludeSystemBars: "auto"`
147
+ - Eliminates 3-5% false diffs from volatile system UI
148
+
149
+ #### 4b. Perceptual Comparison Mode
150
+ - SSIM-inspired 8x8 block averaging
151
+ - Tolerates anti-aliasing and sub-pixel font rendering differences
152
+ - Enable with `perceptual: true` or `depth: "thorough"`
153
+ - New verdict: 99%+ = "Pixel-perfect match. No VQA issues expected."
154
+
155
+ #### 4c. Smart Figma Preprocessing
156
+ - New `"smart"` strategy for `preprocessReference`
157
+ - Masks rounded corners (detects corner radius, fills with inner color)
158
+ - Content-based cropping + residual border trimming
159
+ - Handles dark bars, light borders, transparent padding
160
+
161
+ #### 4d. Sub-pixel Alignment
162
+ - Layout analyzer adds 1px padding to scaled bounds
163
+ - Prevents off-by-one edge mismatches between device and Figma
164
+ - Verdict thresholds tuned: "excellent" = 95%+, "good" = 82%+
165
+
166
+ ---
167
+
168
+ ## New Tools (3)
169
+
170
+ | Tool | Description |
171
+ |------|-------------|
172
+ | `devlens_analyze` | Smart analysis with configurable scope (minimal/targeted/full) |
173
+ | `devlens_vqa_validate` | VQA validator — checks spacing, color, alignment, sizing, missing elements against Figma |
174
+ | `devlens_compare_properties` | Per-component property comparison — text sizes, colors, spacing, dimensions, layout direction with exact expected vs actual values and configurable tolerances |
175
+
176
+ **Total tools: 37** (up from 34 in v0.3.3)
177
+
178
+ ---
179
+
180
+ ## Enhanced Tools
181
+
182
+ | Tool | What changed |
183
+ |------|-------------|
184
+ | `devlens_compare_with_figma` | New `depth` param (quick/standard/thorough), `excludeSystemBars` param |
185
+ | `devlens_snapshot` | New `scope` param (screen/component), `componentRef` for subtree capture |
186
+ | `devlens_compare_screenshot` | Inherits status bar exclusion and perceptual mode from comparator |
187
+
188
+ ---
189
+
190
+ ## Files Changed
191
+
192
+ ### New (9 files)
193
+ | File | Purpose |
194
+ |------|---------|
195
+ | `src/setup/shell-detector.ts` | Shell type & node path detection |
196
+ | `src/setup/config-patcher.ts` | MCP config JSON auto-patcher |
197
+ | `src/tools/analyze-tools.ts` | `devlens_analyze` tool |
198
+ | `src/tools/vqa-tools.ts` | `devlens_vqa_validate` tool |
199
+ | `src/visual/vqa-analyzer.ts` | VQA engine: spacing, sizing, alignment, color, missing checks |
200
+ | `src/visual/color-extractor.ts` | Dominant color extraction & Delta-E comparison |
201
+ | `src/figma/figma-properties.ts` | Extract all comparable design properties from Figma REST API |
202
+ | `src/snapshot/device-properties.ts` | Extract comparable properties from device snapshot + screenshot |
203
+ | `src/visual/property-comparator.ts` | Per-property comparison engine with tolerances and severity |
204
+
205
+ ### Modified (11 files)
206
+ | File | What changed |
207
+ |------|-------------|
208
+ | `bin/cli.ts` | Calls `detectAndPatchConfig()` on startup |
209
+ | `src/server.ts` | Registers analyze + VQA tools, version bumped to 0.4.0 |
210
+ | `src/visual/comparator.ts` | Status bar exclusion, perceptual mode, updated verdicts |
211
+ | `src/visual/layout-analyzer.ts` | Sub-pixel alignment padding, tuned verdict thresholds |
212
+ | `src/utils/image-preprocess.ts` | `"smart"` strategy, `maskRoundedCorners()` |
213
+ | `src/tools/screenshot-tools.ts` | `depth` and `excludeSystemBars` params on compare_with_figma |
214
+ | `src/tools/snapshot-tools.ts` | `scope` and `componentRef` params on snapshot |
215
+ | `package.json` | Version 0.3.3 → 0.4.0 |
216
+ | `README.md` | v0.4.0 changelog, updated tool count, VQA workflow |
217
+ | `docs/setup-guide.md` | Auto-detect docs, VQA prompts, updated tool count |
218
+ | `docs/figma-workflow.md` | Full VQA workflow section with prompts |
219
+ | `docs/tool-reference.md` | analyze + vqa_validate reference entries |
220
+
221
+ ---
222
+
223
+ ## Breaking Changes
224
+
225
+ None. All existing tool parameters and behaviors are backward-compatible. New parameters have sensible defaults:
226
+ - `excludeSystemBars` defaults to `"auto"`
227
+ - `depth` defaults to `"standard"` (same as v0.3 behavior)
228
+ - `scope` defaults to `"screen"` / `"full"` (same as v0.3 behavior)
229
+
230
+ ---
231
+
232
+ ## Upgrade
233
+
234
+ ```bash
235
+ # If using npx (recommended) — automatic, just restart your AI client
236
+ # npx devlens-mcp@latest always fetches the latest
237
+
238
+ # If installed locally
239
+ npm install devlens-mcp@latest
240
+
241
+ # Clear stale npx cache if needed
242
+ rm -rf ~/.npm/_npx/*devlens*
243
+ ```
244
+
245
+ ---
246
+
247
+ ## What's Next (v0.5.0 roadmap)
248
+
249
+ - Figma node-level comparison (compare Figma component tree against accessibility tree)
250
+ - Auto-fix integration (VQA suggestions applied directly to source code)
251
+ - CI/CD integration (run VQA as a build step, fail on critical issues)
252
+ - Multi-screen VQA batch (validate entire flow in one call)
253
+ - Design token drift detection (flag tokens in code that don't match Figma)
package/dist/bin/cli.js CHANGED
@@ -2,7 +2,9 @@
2
2
  "use strict";
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  const index_js_1 = require("../src/index.js");
5
+ const config_patcher_js_1 = require("../src/setup/config-patcher.js");
5
6
  async function main() {
7
+ await (0, config_patcher_js_1.detectAndPatchConfig)();
6
8
  const server = await (0, index_js_1.createServer)();
7
9
  process.on("SIGINT", async () => {
8
10
  await server.close();
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../bin/cli.ts"],"names":[],"mappings":";;;AAEA,8CAA+C;AAE/C,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,MAAM,IAAA,uBAAY,GAAE,CAAC;IAEpC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;QAC9B,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,IAAI,EAAE;QAC/B,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,KAAK,CAAC,CAAC;IACjD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../bin/cli.ts"],"names":[],"mappings":";;;AAEA,8CAA+C;AAC/C,sEAAsE;AAEtE,KAAK,UAAU,IAAI;IACjB,MAAM,IAAA,wCAAoB,GAAE,CAAC;IAE7B,MAAM,MAAM,GAAG,MAAM,IAAA,uBAAY,GAAE,CAAC;IAEpC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;QAC9B,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,IAAI,EAAE;QAC/B,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,KAAK,CAAC,CAAC;IACjD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Extract all comparable design properties from a Figma node tree.
3
+ * Uses the REST API JSON response (not pixel exports).
4
+ *
5
+ * Builds on figma-structure.ts which fetches the raw node tree.
6
+ * This module walks that tree and normalizes every measurable property
7
+ * into a flat, comparable format.
8
+ */
9
+ export interface FigmaComponentProps {
10
+ nodeId: string;
11
+ name: string;
12
+ type: string;
13
+ width: number;
14
+ height: number;
15
+ x: number;
16
+ y: number;
17
+ text?: {
18
+ content: string;
19
+ fontSize: number;
20
+ fontFamily: string;
21
+ fontWeight: number;
22
+ lineHeight: number;
23
+ letterSpacing: number;
24
+ textAlign: string;
25
+ };
26
+ fills: Array<{
27
+ type: "SOLID" | "GRADIENT" | "IMAGE";
28
+ color?: {
29
+ r: number;
30
+ g: number;
31
+ b: number;
32
+ a: number;
33
+ };
34
+ opacity?: number;
35
+ }>;
36
+ cornerRadius?: number;
37
+ opacity: number;
38
+ visible: boolean;
39
+ stroke?: {
40
+ color: {
41
+ r: number;
42
+ g: number;
43
+ b: number;
44
+ a: number;
45
+ };
46
+ weight: number;
47
+ };
48
+ effects: Array<{
49
+ type: string;
50
+ color?: {
51
+ r: number;
52
+ g: number;
53
+ b: number;
54
+ a: number;
55
+ };
56
+ offset?: {
57
+ x: number;
58
+ y: number;
59
+ };
60
+ radius: number;
61
+ }>;
62
+ layout?: {
63
+ mode: "HORIZONTAL" | "VERTICAL" | "NONE";
64
+ itemSpacing: number;
65
+ padding: {
66
+ top: number;
67
+ right: number;
68
+ bottom: number;
69
+ left: number;
70
+ };
71
+ primaryAlign: string;
72
+ counterAlign: string;
73
+ sizingH: string;
74
+ sizingV: string;
75
+ };
76
+ children: FigmaComponentProps[];
77
+ }
78
+ /**
79
+ * Walk a raw Figma REST API node and extract all comparable properties.
80
+ */
81
+ export declare function extractFigmaProperties(raw: any): FigmaComponentProps;
82
+ /**
83
+ * Flatten a FigmaComponentProps tree into a list of all nodes.
84
+ */
85
+ export declare function flattenFigmaTree(root: FigmaComponentProps, parentPath?: string): Array<FigmaComponentProps & {
86
+ path: string;
87
+ }>;
88
+ //# sourceMappingURL=figma-properties.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"figma-properties.d.ts","sourceRoot":"","sources":["../../../src/figma/figma-properties.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,mBAAmB;IAElC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IAGb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IAGV,IAAI,CAAC,EAAE;QACL,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,aAAa,EAAE,MAAM,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IAGF,KAAK,EAAE,KAAK,CAAC;QACX,IAAI,EAAE,OAAO,GAAG,UAAU,GAAG,OAAO,CAAC;QACrC,KAAK,CAAC,EAAE;YAAE,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QACvD,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC,CAAC;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IAGjB,MAAM,CAAC,EAAE;QACP,KAAK,EAAE;YAAE,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QACtD,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IAGF,OAAO,EAAE,KAAK,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE;YAAE,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QACvD,MAAM,CAAC,EAAE;YAAE,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QAClC,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC,CAAC;IAGH,MAAM,CAAC,EAAE;QACP,IAAI,EAAE,YAAY,GAAG,UAAU,GAAG,MAAM,CAAC;QACzC,WAAW,EAAE,MAAM,CAAC;QACpB,OAAO,EAAE;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC;QACtE,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,MAAM,CAAC;QACrB,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IAEF,QAAQ,EAAE,mBAAmB,EAAE,CAAC;CACjC;AAmBD;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,GAAG,GAAG,mBAAmB,CAqFpE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,mBAAmB,EACzB,UAAU,SAAK,GACd,KAAK,CAAC,mBAAmB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAY/C"}
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+ /**
3
+ * Extract all comparable design properties from a Figma node tree.
4
+ * Uses the REST API JSON response (not pixel exports).
5
+ *
6
+ * Builds on figma-structure.ts which fetches the raw node tree.
7
+ * This module walks that tree and normalizes every measurable property
8
+ * into a flat, comparable format.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.extractFigmaProperties = extractFigmaProperties;
12
+ exports.flattenFigmaTree = flattenFigmaTree;
13
+ /**
14
+ * Convert Figma's 0-1 RGBA to 0-255.
15
+ */
16
+ function toRgb255(c) {
17
+ return {
18
+ r: Math.round((c.r ?? 0) * 255),
19
+ g: Math.round((c.g ?? 0) * 255),
20
+ b: Math.round((c.b ?? 0) * 255),
21
+ a: Math.round((c.a ?? 1) * 255),
22
+ };
23
+ }
24
+ /**
25
+ * Walk a raw Figma REST API node and extract all comparable properties.
26
+ */
27
+ function extractFigmaProperties(raw) {
28
+ const bbox = raw.absoluteBoundingBox ?? { x: 0, y: 0, width: 0, height: 0 };
29
+ // Text properties
30
+ let text;
31
+ if (raw.type === "TEXT" && raw.characters) {
32
+ const style = raw.style ?? {};
33
+ text = {
34
+ content: raw.characters,
35
+ fontSize: style.fontSize ?? 0,
36
+ fontFamily: style.fontFamily ?? "",
37
+ fontWeight: style.fontWeight ?? 400,
38
+ lineHeight: style.lineHeightPx ?? 0,
39
+ letterSpacing: style.letterSpacing ?? 0,
40
+ textAlign: style.textAlignHorizontal ?? "LEFT",
41
+ };
42
+ }
43
+ // Fills
44
+ const fills = (raw.fills ?? [])
45
+ .filter((f) => f.visible !== false)
46
+ .map((f) => ({
47
+ type: f.type ?? "SOLID",
48
+ color: f.color ? toRgb255(f.color) : undefined,
49
+ opacity: f.opacity,
50
+ }));
51
+ // Stroke
52
+ let stroke;
53
+ if (raw.strokes?.length > 0 && raw.strokes[0].color) {
54
+ stroke = {
55
+ color: toRgb255(raw.strokes[0].color),
56
+ weight: raw.strokeWeight ?? 0,
57
+ };
58
+ }
59
+ // Effects
60
+ const effects = (raw.effects ?? [])
61
+ .filter((e) => e.visible !== false)
62
+ .map((e) => ({
63
+ type: e.type ?? "UNKNOWN",
64
+ color: e.color ? toRgb255(e.color) : undefined,
65
+ offset: e.offset,
66
+ radius: e.radius ?? 0,
67
+ }));
68
+ // Layout
69
+ let layout;
70
+ if (raw.layoutMode && raw.layoutMode !== "NONE") {
71
+ layout = {
72
+ mode: raw.layoutMode,
73
+ itemSpacing: raw.itemSpacing ?? 0,
74
+ padding: {
75
+ top: raw.paddingTop ?? 0,
76
+ right: raw.paddingRight ?? 0,
77
+ bottom: raw.paddingBottom ?? 0,
78
+ left: raw.paddingLeft ?? 0,
79
+ },
80
+ primaryAlign: raw.primaryAxisAlignItems ?? "MIN",
81
+ counterAlign: raw.counterAxisAlignItems ?? "MIN",
82
+ sizingH: raw.layoutSizingHorizontal ?? "FIXED",
83
+ sizingV: raw.layoutSizingVertical ?? "FIXED",
84
+ };
85
+ }
86
+ return {
87
+ nodeId: raw.id ?? "",
88
+ name: raw.name ?? "",
89
+ type: raw.type ?? "UNKNOWN",
90
+ width: bbox.width ?? 0,
91
+ height: bbox.height ?? 0,
92
+ x: bbox.x ?? 0,
93
+ y: bbox.y ?? 0,
94
+ text,
95
+ fills,
96
+ cornerRadius: raw.cornerRadius ?? undefined,
97
+ opacity: raw.opacity ?? 1,
98
+ visible: raw.visible !== false,
99
+ stroke,
100
+ effects,
101
+ layout,
102
+ children: Array.isArray(raw.children)
103
+ ? raw.children.map(extractFigmaProperties)
104
+ : [],
105
+ };
106
+ }
107
+ /**
108
+ * Flatten a FigmaComponentProps tree into a list of all nodes.
109
+ */
110
+ function flattenFigmaTree(root, parentPath = "") {
111
+ const path = parentPath ? `${parentPath} > ${root.name}` : root.name;
112
+ const result = [];
113
+ if (root.width > 0 && root.height > 0) {
114
+ result.push({ ...root, path });
115
+ }
116
+ for (const child of root.children) {
117
+ result.push(...flattenFigmaTree(child, path));
118
+ }
119
+ return result;
120
+ }
121
+ //# sourceMappingURL=figma-properties.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"figma-properties.js","sourceRoot":"","sources":["../../../src/figma/figma-properties.ts"],"names":[],"mappings":"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"}