@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/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 enable.\n`);
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 enable.\n`);
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,
@@ -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
@@ -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.18",
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",