@mcpc-tech/unplugin-dev-inspector-mcp 0.0.18 → 0.0.20
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 +61 -18
- package/client/dist/inspector.iife.js +1 -1
- package/dist/cli.cjs +472 -8
- package/dist/cli.js +470 -8
- package/dist/config-updater.js +105 -105
- package/dist/index.cjs +87 -1
- package/dist/index.js +85 -1
- package/dist/vue-transform.cjs +1 -1
- package/dist/vue-transform.js +1 -1
- package/package.json +4 -2
package/dist/index.cjs
CHANGED
|
@@ -1,10 +1,87 @@
|
|
|
1
1
|
const require_chunk = require('./chunk.cjs');
|
|
2
2
|
const require_config_updater = require('./config-updater.cjs');
|
|
3
3
|
const require_vue_transform = require('./vue-transform.cjs');
|
|
4
|
+
let node_path = require("node:path");
|
|
5
|
+
node_path = require_chunk.__toESM(node_path);
|
|
4
6
|
let __modelcontextprotocol_sdk_client_index_js = require("@modelcontextprotocol/sdk/client/index.js");
|
|
5
7
|
let __modelcontextprotocol_sdk_client_sse_js = require("@modelcontextprotocol/sdk/client/sse.js");
|
|
8
|
+
let magic_string = require("magic-string");
|
|
9
|
+
magic_string = require_chunk.__toESM(magic_string);
|
|
6
10
|
let unplugin = require("unplugin");
|
|
11
|
+
let svelte_compiler = require("svelte/compiler");
|
|
7
12
|
|
|
13
|
+
//#region src/compiler/svelte-transform.ts
|
|
14
|
+
function normalizePath(id) {
|
|
15
|
+
return id.split(node_path.default.sep).join("/");
|
|
16
|
+
}
|
|
17
|
+
const DATA_SOURCE_ATTR = "data-source";
|
|
18
|
+
/**
|
|
19
|
+
* Transform Svelte code to inject data-source attributes for dev inspection.
|
|
20
|
+
*
|
|
21
|
+
* Handles:
|
|
22
|
+
* - Regular elements: <div>, <button>
|
|
23
|
+
* - Components: <Counter>, <MyComponent>
|
|
24
|
+
* - Svelte special elements: <svelte:window>, <svelte:head>, etc.
|
|
25
|
+
*
|
|
26
|
+
* Skips:
|
|
27
|
+
* - Fragments and elements that cannot have attributes
|
|
28
|
+
* - Elements that already have data-source
|
|
29
|
+
* - Parse errors (returns null gracefully)
|
|
30
|
+
*/
|
|
31
|
+
function compileSvelte({ code, id }) {
|
|
32
|
+
if (!code.includes("<")) return null;
|
|
33
|
+
let ast;
|
|
34
|
+
try {
|
|
35
|
+
ast = (0, svelte_compiler.parse)(code, {
|
|
36
|
+
filename: id,
|
|
37
|
+
modern: true
|
|
38
|
+
});
|
|
39
|
+
} catch {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
const relativePath = normalizePath(node_path.default.relative(process.cwd(), id));
|
|
43
|
+
const s = new magic_string.default(code);
|
|
44
|
+
let hasModifications = false;
|
|
45
|
+
function traverse(node) {
|
|
46
|
+
if ("nodes" in node && Array.isArray(node.nodes)) {
|
|
47
|
+
for (const childNode of node.nodes) traverse(childNode);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if ("type" in node && node.type !== "Fragment" && isElementLike(node)) {
|
|
51
|
+
const element = node;
|
|
52
|
+
if (!element.start || !element.end) return;
|
|
53
|
+
if (!element.attributes?.some((attr) => attr.type === "Attribute" && attr.name === DATA_SOURCE_ATTR)) {
|
|
54
|
+
const lines = code.substring(0, element.start).split("\n");
|
|
55
|
+
const sourceValue = `${relativePath}:${lines.length}:${lines[lines.length - 1].length + 1}`;
|
|
56
|
+
const tagMatch = code.substring(element.start).match(/^<([^\s/>]+)/);
|
|
57
|
+
if (tagMatch) {
|
|
58
|
+
const insertPos = element.start + tagMatch[0].length;
|
|
59
|
+
s.appendLeft(insertPos, ` ${DATA_SOURCE_ATTR}="${sourceValue}"`);
|
|
60
|
+
hasModifications = true;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if ("fragment" in node && node.fragment) traverse(node.fragment);
|
|
65
|
+
if ("consequent" in node && node.consequent) traverse(node.consequent);
|
|
66
|
+
if ("alternate" in node && node.alternate) traverse(node.alternate);
|
|
67
|
+
if ("body" in node && node.body) traverse(node.body);
|
|
68
|
+
if ("pending" in node && node.pending) traverse(node.pending);
|
|
69
|
+
if ("then" in node && node.then) traverse(node.then);
|
|
70
|
+
if ("catch" in node && node.catch) traverse(node.catch);
|
|
71
|
+
if ("fallback" in node && node.fallback) traverse(node.fallback);
|
|
72
|
+
}
|
|
73
|
+
function isElementLike(node) {
|
|
74
|
+
return node.type === "RegularElement" || node.type === "Component" || node.type === "SlotElement" || node.type === "TitleElement" || node.type === "SvelteBody" || node.type === "SvelteComponent" || node.type === "SvelteDocument" || node.type === "SvelteElement" || node.type === "SvelteHead" || node.type === "SvelteSelf" || node.type === "SvelteWindow" || node.type === "SvelteBoundary";
|
|
75
|
+
}
|
|
76
|
+
traverse(ast.fragment);
|
|
77
|
+
if (!hasModifications) return null;
|
|
78
|
+
return {
|
|
79
|
+
code: s.toString(),
|
|
80
|
+
map: s.generateMap({ hires: true })
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
//#endregion
|
|
8
85
|
//#region src/utils/browser-launcher.ts
|
|
9
86
|
/**
|
|
10
87
|
* Launch browser via Chrome DevTools MCP
|
|
@@ -103,6 +180,15 @@ if (typeof window !== 'undefined' && typeof document !== 'undefined') {
|
|
|
103
180
|
console.error(`[dev-inspector] Failed to transform ${id}:`, error);
|
|
104
181
|
return null;
|
|
105
182
|
}
|
|
183
|
+
if (id.match(/\.svelte$/)) try {
|
|
184
|
+
return await compileSvelte({
|
|
185
|
+
code,
|
|
186
|
+
id
|
|
187
|
+
});
|
|
188
|
+
} catch (error) {
|
|
189
|
+
console.error(`[dev-inspector] Failed to transform ${id}:`, error);
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
106
192
|
return null;
|
|
107
193
|
},
|
|
108
194
|
vite: {
|
|
@@ -182,7 +268,7 @@ if (typeof window !== 'undefined' && typeof document !== 'undefined') {
|
|
|
182
268
|
}, 1e3);
|
|
183
269
|
} else {
|
|
184
270
|
console.log(`[dev-inspector] ⚠️ autoOpenBrowser: false - Console/Network context unavailable`);
|
|
185
|
-
console.log(`[dev-inspector] 💡 Use "launch_chrome_devtools" prompt to
|
|
271
|
+
console.log(`[dev-inspector] 💡 Use "launch_chrome_devtools" prompt or "chrome_devtools" tool to open browser manually.\n`);
|
|
186
272
|
}
|
|
187
273
|
require_config_updater.setupInspectorMiddleware(server.middlewares, {
|
|
188
274
|
agents: options.agents,
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,84 @@
|
|
|
1
1
|
import { i as setupMcpMiddleware, n as setupAcpMiddleware, r as setupInspectorMiddleware, t as updateMcpConfigs } from "./config-updater.js";
|
|
2
2
|
import { n as transformJSX, t as compileVue } from "./vue-transform.js";
|
|
3
|
+
import path from "node:path";
|
|
3
4
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
4
5
|
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
|
|
6
|
+
import MagicString from "magic-string";
|
|
5
7
|
import { createUnplugin } from "unplugin";
|
|
8
|
+
import { parse } from "svelte/compiler";
|
|
6
9
|
|
|
10
|
+
//#region src/compiler/svelte-transform.ts
|
|
11
|
+
function normalizePath(id) {
|
|
12
|
+
return id.split(path.sep).join("/");
|
|
13
|
+
}
|
|
14
|
+
const DATA_SOURCE_ATTR = "data-source";
|
|
15
|
+
/**
|
|
16
|
+
* Transform Svelte code to inject data-source attributes for dev inspection.
|
|
17
|
+
*
|
|
18
|
+
* Handles:
|
|
19
|
+
* - Regular elements: <div>, <button>
|
|
20
|
+
* - Components: <Counter>, <MyComponent>
|
|
21
|
+
* - Svelte special elements: <svelte:window>, <svelte:head>, etc.
|
|
22
|
+
*
|
|
23
|
+
* Skips:
|
|
24
|
+
* - Fragments and elements that cannot have attributes
|
|
25
|
+
* - Elements that already have data-source
|
|
26
|
+
* - Parse errors (returns null gracefully)
|
|
27
|
+
*/
|
|
28
|
+
function compileSvelte({ code, id }) {
|
|
29
|
+
if (!code.includes("<")) return null;
|
|
30
|
+
let ast;
|
|
31
|
+
try {
|
|
32
|
+
ast = parse(code, {
|
|
33
|
+
filename: id,
|
|
34
|
+
modern: true
|
|
35
|
+
});
|
|
36
|
+
} catch {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
const relativePath = normalizePath(path.relative(process.cwd(), id));
|
|
40
|
+
const s = new MagicString(code);
|
|
41
|
+
let hasModifications = false;
|
|
42
|
+
function traverse(node) {
|
|
43
|
+
if ("nodes" in node && Array.isArray(node.nodes)) {
|
|
44
|
+
for (const childNode of node.nodes) traverse(childNode);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if ("type" in node && node.type !== "Fragment" && isElementLike(node)) {
|
|
48
|
+
const element = node;
|
|
49
|
+
if (!element.start || !element.end) return;
|
|
50
|
+
if (!element.attributes?.some((attr) => attr.type === "Attribute" && attr.name === DATA_SOURCE_ATTR)) {
|
|
51
|
+
const lines = code.substring(0, element.start).split("\n");
|
|
52
|
+
const sourceValue = `${relativePath}:${lines.length}:${lines[lines.length - 1].length + 1}`;
|
|
53
|
+
const tagMatch = code.substring(element.start).match(/^<([^\s/>]+)/);
|
|
54
|
+
if (tagMatch) {
|
|
55
|
+
const insertPos = element.start + tagMatch[0].length;
|
|
56
|
+
s.appendLeft(insertPos, ` ${DATA_SOURCE_ATTR}="${sourceValue}"`);
|
|
57
|
+
hasModifications = true;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if ("fragment" in node && node.fragment) traverse(node.fragment);
|
|
62
|
+
if ("consequent" in node && node.consequent) traverse(node.consequent);
|
|
63
|
+
if ("alternate" in node && node.alternate) traverse(node.alternate);
|
|
64
|
+
if ("body" in node && node.body) traverse(node.body);
|
|
65
|
+
if ("pending" in node && node.pending) traverse(node.pending);
|
|
66
|
+
if ("then" in node && node.then) traverse(node.then);
|
|
67
|
+
if ("catch" in node && node.catch) traverse(node.catch);
|
|
68
|
+
if ("fallback" in node && node.fallback) traverse(node.fallback);
|
|
69
|
+
}
|
|
70
|
+
function isElementLike(node) {
|
|
71
|
+
return node.type === "RegularElement" || node.type === "Component" || node.type === "SlotElement" || node.type === "TitleElement" || node.type === "SvelteBody" || node.type === "SvelteComponent" || node.type === "SvelteDocument" || node.type === "SvelteElement" || node.type === "SvelteHead" || node.type === "SvelteSelf" || node.type === "SvelteWindow" || node.type === "SvelteBoundary";
|
|
72
|
+
}
|
|
73
|
+
traverse(ast.fragment);
|
|
74
|
+
if (!hasModifications) return null;
|
|
75
|
+
return {
|
|
76
|
+
code: s.toString(),
|
|
77
|
+
map: s.generateMap({ hires: true })
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
//#endregion
|
|
7
82
|
//#region src/utils/browser-launcher.ts
|
|
8
83
|
/**
|
|
9
84
|
* Launch browser via Chrome DevTools MCP
|
|
@@ -102,6 +177,15 @@ if (typeof window !== 'undefined' && typeof document !== 'undefined') {
|
|
|
102
177
|
console.error(`[dev-inspector] Failed to transform ${id}:`, error);
|
|
103
178
|
return null;
|
|
104
179
|
}
|
|
180
|
+
if (id.match(/\.svelte$/)) try {
|
|
181
|
+
return await compileSvelte({
|
|
182
|
+
code,
|
|
183
|
+
id
|
|
184
|
+
});
|
|
185
|
+
} catch (error) {
|
|
186
|
+
console.error(`[dev-inspector] Failed to transform ${id}:`, error);
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
105
189
|
return null;
|
|
106
190
|
},
|
|
107
191
|
vite: {
|
|
@@ -181,7 +265,7 @@ if (typeof window !== 'undefined' && typeof document !== 'undefined') {
|
|
|
181
265
|
}, 1e3);
|
|
182
266
|
} else {
|
|
183
267
|
console.log(`[dev-inspector] ⚠️ autoOpenBrowser: false - Console/Network context unavailable`);
|
|
184
|
-
console.log(`[dev-inspector] 💡 Use "launch_chrome_devtools" prompt to
|
|
268
|
+
console.log(`[dev-inspector] 💡 Use "launch_chrome_devtools" prompt or "chrome_devtools" tool to open browser manually.\n`);
|
|
185
269
|
}
|
|
186
270
|
setupInspectorMiddleware(server.middlewares, {
|
|
187
271
|
agents: options.agents,
|
package/dist/vue-transform.cjs
CHANGED
|
@@ -2,9 +2,9 @@ const require_chunk = require('./chunk.cjs');
|
|
|
2
2
|
let node_module = require("node:module");
|
|
3
3
|
let node_path = require("node:path");
|
|
4
4
|
node_path = require_chunk.__toESM(node_path);
|
|
5
|
+
let __babel_parser = require("@babel/parser");
|
|
5
6
|
let magic_string = require("magic-string");
|
|
6
7
|
magic_string = require_chunk.__toESM(magic_string);
|
|
7
|
-
let __babel_parser = require("@babel/parser");
|
|
8
8
|
let __vue_compiler_sfc = require("@vue/compiler-sfc");
|
|
9
9
|
|
|
10
10
|
//#region src/compiler/jsx-transform.ts
|
package/dist/vue-transform.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import MagicString from "magic-string";
|
|
4
3
|
import { parse } from "@babel/parser";
|
|
4
|
+
import MagicString from "magic-string";
|
|
5
5
|
import { parse as parse$1 } from "@vue/compiler-sfc";
|
|
6
6
|
|
|
7
7
|
//#region src/compiler/jsx-transform.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mcpc-tech/unplugin-dev-inspector-mcp",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.20",
|
|
4
4
|
"description": "Universal dev inspector plugin for React/Vue - inspect component sources and API calls in any bundler",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -28,7 +28,8 @@
|
|
|
28
28
|
"unplugin"
|
|
29
29
|
],
|
|
30
30
|
"bin": {
|
|
31
|
-
"dev-inspector-server": "./dist/cli.js"
|
|
31
|
+
"dev-inspector-server": "./dist/cli.js",
|
|
32
|
+
"dev-inspector": "./dist/cli.js"
|
|
32
33
|
},
|
|
33
34
|
"files": [
|
|
34
35
|
"dist",
|
|
@@ -155,6 +156,7 @@
|
|
|
155
156
|
"shiki": "^3.15.0",
|
|
156
157
|
"sonner": "^2.0.7",
|
|
157
158
|
"streamdown": "^1.5.1",
|
|
159
|
+
"svelte": "^5.0.0",
|
|
158
160
|
"tailwind-merge": "^3.3.1",
|
|
159
161
|
"tokenlens": "^1.3.1",
|
|
160
162
|
"unplugin": "^2.3.10",
|