devlens-mcp 0.1.0 → 0.1.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.
- package/SKILL.md +2 -2
- package/dist/index.js +16 -6
- package/package.json +16 -4
package/SKILL.md
CHANGED
|
@@ -16,12 +16,12 @@ You have access to four visual inspection tools: `dl_warmup`, `dl_capture`, `dl_
|
|
|
16
16
|
## Rules — follow these automatically, no user prompting needed
|
|
17
17
|
|
|
18
18
|
### Rule 1: Warmup at session start
|
|
19
|
-
The first time you are about to edit any file
|
|
19
|
+
The first time you are about to edit any frontend file (`.tsx`, `.ts`, `.css`, `.vue`, `.svelte`), call `dl_warmup` first.
|
|
20
20
|
This pre-warms the browser so subsequent captures cost ~50ms instead of ~500ms.
|
|
21
21
|
Only call it once per session.
|
|
22
22
|
|
|
23
23
|
### Rule 2: Capture after every frontend file write
|
|
24
|
-
After every `Edit` or `Write` to a file matching
|
|
24
|
+
After every `Edit` or `Write` to a file matching `**/*.tsx`, `**/*.vue`, `**/*.svelte`, or `**/*.css`:
|
|
25
25
|
1. Call `dl_capture` with either `route` (if you know it) or `filePath` (auto-resolved from devlens.config.ts)
|
|
26
26
|
2. Add `selector` if you only changed a specific component (keeps the image small and fast)
|
|
27
27
|
3. Look at the returned image — does it look right?
|
package/dist/index.js
CHANGED
|
@@ -414,16 +414,24 @@ async function startServer() {
|
|
|
414
414
|
]
|
|
415
415
|
}));
|
|
416
416
|
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
417
|
-
const { name
|
|
417
|
+
const { name } = req.params;
|
|
418
|
+
const args = req.params.arguments ?? {};
|
|
419
|
+
const str = (v) => typeof v === "string" ? v : void 0;
|
|
420
|
+
const num = (v) => typeof v === "number" ? v : void 0;
|
|
418
421
|
try {
|
|
419
422
|
if (name === "dl_warmup") {
|
|
420
|
-
const result = await warmup(args.devServerUrl, config);
|
|
423
|
+
const result = await warmup(str(args.devServerUrl), config);
|
|
421
424
|
return {
|
|
422
425
|
content: [{ type: "text", text: `Warmed up in ${result.durationMs}ms \u2014 ${result.url}` }]
|
|
423
426
|
};
|
|
424
427
|
}
|
|
425
428
|
if (name === "dl_capture") {
|
|
426
|
-
const input =
|
|
429
|
+
const input = {
|
|
430
|
+
route: str(args.route),
|
|
431
|
+
filePath: str(args.filePath),
|
|
432
|
+
selector: str(args.selector),
|
|
433
|
+
waitMs: num(args.waitMs)
|
|
434
|
+
};
|
|
427
435
|
const result = await capture(input, config);
|
|
428
436
|
if ("error" in result) {
|
|
429
437
|
return { content: [{ type: "text", text: `Error: ${result.error}` }] };
|
|
@@ -437,11 +445,12 @@ async function startServer() {
|
|
|
437
445
|
return { content };
|
|
438
446
|
}
|
|
439
447
|
if (name === "dl_diff") {
|
|
440
|
-
const
|
|
448
|
+
const route = str(args.route) ?? "";
|
|
449
|
+
const selector = str(args.selector);
|
|
441
450
|
const result = await diff(route, selector, diffStore, config);
|
|
442
451
|
if ("error" in result) return { content: [{ type: "text", text: `Error: ${result.error}` }] };
|
|
443
452
|
const content = [
|
|
444
|
-
{ type: "text", text: result.diff ? `Changed: ${result.diff.changedPercent}% (${result.diff.changedPixels} pixels)` : result.message
|
|
453
|
+
{ type: "text", text: result.diff ? `Changed: ${result.diff.changedPercent}% (${result.diff.changedPixels} pixels)` : "message" in result && typeof result.message === "string" ? result.message : "Baseline set." }
|
|
445
454
|
];
|
|
446
455
|
if (result.diff?.diffImageBase64) {
|
|
447
456
|
content.push({ type: "image", data: result.diff.diffImageBase64, mimeType: "image/png" });
|
|
@@ -449,7 +458,8 @@ async function startServer() {
|
|
|
449
458
|
return { content };
|
|
450
459
|
}
|
|
451
460
|
if (name === "dl_snapshot") {
|
|
452
|
-
const
|
|
461
|
+
const route = str(args.route) ?? "";
|
|
462
|
+
const selector = str(args.selector);
|
|
453
463
|
const result = await snapshot(route, selector, config);
|
|
454
464
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
455
465
|
}
|
package/package.json
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "devlens-mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Real-time visual feedback plugin for Claude Code frontend development",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": "./dist/index.js",
|
|
10
|
+
"default": "./dist/index.js"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
7
13
|
"bin": {
|
|
8
14
|
"devlens-mcp": "dist/index.js"
|
|
9
15
|
},
|
|
@@ -26,19 +32,25 @@
|
|
|
26
32
|
"dev": "tsup --watch",
|
|
27
33
|
"test": "vitest run",
|
|
28
34
|
"test:watch": "vitest",
|
|
29
|
-
"start": "node dist/index.js"
|
|
35
|
+
"start": "node dist/index.js",
|
|
36
|
+
"lint": "eslint src --ext .ts",
|
|
37
|
+
"format": "prettier --write src"
|
|
30
38
|
},
|
|
31
39
|
"dependencies": {
|
|
32
40
|
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
33
41
|
"minimatch": "^10.2.5",
|
|
34
42
|
"pixelmatch": "^6.0.0",
|
|
35
43
|
"playwright": "^1.45.0",
|
|
36
|
-
"pngjs": "^7.0.0"
|
|
37
|
-
"zod": "^3.22.0"
|
|
44
|
+
"pngjs": "^7.0.0"
|
|
38
45
|
},
|
|
39
46
|
"devDependencies": {
|
|
40
47
|
"@types/node": "^20.0.0",
|
|
41
48
|
"@types/pngjs": "^6.0.0",
|
|
49
|
+
"@typescript-eslint/eslint-plugin": "^7.0.0",
|
|
50
|
+
"@typescript-eslint/parser": "^7.0.0",
|
|
51
|
+
"eslint": "^8.57.0",
|
|
52
|
+
"eslint-config-prettier": "^9.0.0",
|
|
53
|
+
"prettier": "^3.0.0",
|
|
42
54
|
"tsup": "^8.0.0",
|
|
43
55
|
"typescript": "^5.4.0",
|
|
44
56
|
"vitest": "^1.6.0"
|