@mcpc-tech/unplugin-dev-inspector-mcp 0.0.1 → 0.0.2-beta.2

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.js CHANGED
@@ -8,13 +8,15 @@ import { z } from "zod";
8
8
  import "@modelcontextprotocol/sdk/server/index.js";
9
9
  import { mcpc } from "@mcpc-tech/core";
10
10
  import path, { dirname, resolve } from "node:path";
11
+ import { fileURLToPath } from "node:url";
11
12
  import fs from "fs";
12
13
  import path$1, { dirname as dirname$1 } from "path";
13
- import { fileURLToPath } from "url";
14
+ import { fileURLToPath as fileURLToPath$1 } from "url";
14
15
  import { convertToModelMessages, streamText } from "ai";
15
16
  import { createACPProvider } from "@mcpc-tech/acp-ai-provider";
16
17
  import { planEntrySchema } from "@agentclientprotocol/sdk";
17
18
  import { existsSync, readFileSync } from "node:fs";
19
+ import { parse } from "@vue/compiler-sfc";
18
20
 
19
21
  //#region rolldown:runtime
20
22
  var __getOwnPropNames = Object.getOwnPropertyNames;
@@ -386,6 +388,49 @@ function bindPuppet(transport, puppet, methods = [...DEFAULT_FORWARDED]) {
386
388
  }
387
389
  var encoder = new TextEncoder();
388
390
 
391
+ //#endregion
392
+ //#region src/prompt-schemas.ts
393
+ /**
394
+ * Shared prompt schemas for MCP inspector prompts
395
+ * Used by both server and client implementations
396
+ */
397
+ const PROMPT_SCHEMAS = {
398
+ capture_element: {
399
+ name: "capture_element",
400
+ title: "Capture Element Context",
401
+ description: "Capture context about a UI element for troubleshooting and investigation.",
402
+ arguments: []
403
+ },
404
+ view_inspections: {
405
+ name: "view_inspections",
406
+ title: "View All Inspections",
407
+ description: "View all element inspections in the queue with their status.",
408
+ arguments: []
409
+ },
410
+ launch_chrome_devtools: {
411
+ name: "launch_chrome_devtools",
412
+ title: "Launch Chrome DevTools",
413
+ description: "Launch Chrome DevTools and navigate to a specified URL for debugging and inspection.",
414
+ arguments: [{
415
+ name: "url",
416
+ description: "The URL to navigate to (e.g., http://localhost:3000)",
417
+ required: true
418
+ }]
419
+ },
420
+ refresh_chrome_state: {
421
+ name: "refresh_chrome_state",
422
+ title: "Refresh Chrome State",
423
+ description: "Refresh the state of the Chrome DevTools for the specified URL.",
424
+ arguments: []
425
+ },
426
+ get_network_requests: {
427
+ name: "get_network_requests",
428
+ title: "Get Network Requests",
429
+ description: "Get all network requests for the specified URL.",
430
+ arguments: []
431
+ }
432
+ };
433
+
389
434
  //#endregion
390
435
  //#region src/tool-schemas.ts
391
436
  /**
@@ -393,31 +438,31 @@ var encoder = new TextEncoder();
393
438
  * Used by both server and client implementations
394
439
  */
395
440
  const TOOL_SCHEMAS = {
396
- inspect_element: {
397
- name: "inspect_element",
398
- description: "Activate the visual element inspector to let the user select a UI element on the page. The user will click an element and provide feedback about what they want to change. Returns the source code location and user feedback.",
441
+ capture_element_context: {
442
+ name: "capture_element_context",
443
+ description: "Capture element context for troubleshooting. Activates visual selector, user clicks element and provides notes, returns source location, DOM hierarchy, computed styles, dimensions, and user notes. Combine with chrome_devtools MCP for deeper diagnostics (Network, Console, Performance, DOM tools).",
399
444
  inputSchema: {
400
445
  type: "object",
401
446
  properties: {}
402
447
  }
403
448
  },
404
- get_all_feedbacks: {
405
- name: "get_all_feedbacks",
406
- description: "Get a list of all current feedback items in the queue, including their status (pending/loading/success/error) and progress. Use this to see what tasks are already being worked on.",
449
+ list_inspections: {
450
+ name: "list_inspections",
451
+ description: "List all captured inspections with ID, element details, source location, notes, and status (pending/in-progress/completed/failed). Use with chrome_devtools for additional context (Console.getMessages, Network.getHAR, Performance.getMetrics).",
407
452
  inputSchema: {
408
453
  type: "object",
409
454
  properties: {}
410
455
  }
411
456
  },
412
- update_feedback_status: {
413
- name: "update_feedback_status",
414
- description: "Update the status of the current feedback item in the user's queue. Use this to show progress or mark completion.",
457
+ update_inspection_status: {
458
+ name: "update_inspection_status",
459
+ description: "Update inspection status with optional progress tracking.\n\n**Parameters**:\n- inspectionId: Optional (auto-detects if omitted)\n- status: 'in-progress' | 'completed' | 'failed'\n- progress: Optional steps array [{id, title, status}]\n- message: REQUIRED for 'completed'/'failed' status\n\n**Example**:\n```javascript\nupdate_inspection_status({\n status: 'completed',\n message: 'Fixed: pointer-events: none blocking clicks'\n});\n```",
415
460
  inputSchema: {
416
461
  type: "object",
417
462
  properties: {
418
- feedbackId: {
463
+ inspectionId: {
419
464
  type: "string",
420
- description: "Optional feedback ID. If not provided, will use the most recent loading feedback or the one from session."
465
+ description: "Optional inspection ID. If not provided, uses the current active inspection."
421
466
  },
422
467
  status: {
423
468
  type: "string",
@@ -426,7 +471,7 @@ const TOOL_SCHEMAS = {
426
471
  "completed",
427
472
  "failed"
428
473
  ],
429
- description: "Current status: 'in-progress' for updates, 'completed' when done, 'failed' on error"
474
+ description: "Current status: 'in-progress' for updates, 'completed' when resolved, 'failed' if unresolvable"
430
475
  },
431
476
  progress: {
432
477
  type: "object",
@@ -454,21 +499,43 @@ const TOOL_SCHEMAS = {
454
499
  ]
455
500
  }
456
501
  } },
457
- description: "Optional progress info with step-by-step details"
502
+ description: "Optional step-by-step progress tracking"
458
503
  },
459
504
  message: {
460
505
  type: "string",
461
- description: "Status message or completion summary. REQUIRED when status is 'completed' or 'failed'"
506
+ description: "Summary of findings or resolution. REQUIRED when status is 'completed' or 'failed'"
462
507
  }
463
508
  },
464
509
  required: ["status"]
465
510
  }
511
+ },
512
+ execute_page_script: {
513
+ name: "execute_page_script",
514
+ description: "Execute JavaScript in browser context (synchronous only, must return value). Access: window, document, DOM APIs, React/Vue instances, localStorage. For deeper diagnostics, use chrome_devtools MCP (Network.getHAR, Console.getMessages, Performance.getMetrics, Debugger, HeapProfiler).",
515
+ inputSchema: {
516
+ type: "object",
517
+ properties: { code: {
518
+ type: "string",
519
+ description: "JavaScript code to execute in page context. Must return a value for diagnostic output."
520
+ } },
521
+ required: ["code"]
522
+ }
466
523
  }
467
524
  };
468
525
 
469
526
  //#endregion
470
527
  //#region src/mcp.ts
471
528
  /**
529
+ * Get Chrome DevTools binary path from npm package, then use node to run it, faster/stabler than npx
530
+ */
531
+ function getChromeDevToolsBinPath() {
532
+ const resolver = import.meta.resolve;
533
+ if (!resolver) throw new Error("Cannot resolve chrome-devtools-mcp package");
534
+ const pkgUrl = resolver("chrome-devtools-mcp/package.json");
535
+ const chromeDevTools = path.dirname(fileURLToPath(pkgUrl));
536
+ return path.join(chromeDevTools, "./build/src/index.js");
537
+ }
538
+ /**
472
539
  * Call MCP server method and wait for response
473
540
  * @param mcpServer - The MCP server instance
474
541
  * @param method - The method name to call
@@ -501,51 +568,178 @@ function callMcpMethod(mcpServer, method, params) {
501
568
  /**
502
569
  * Create and configure the MCP server for source inspection
503
570
  */
504
- async function createInspectorMcpServer() {
571
+ async function createInspectorMcpServer(serverContext) {
505
572
  const mcpServer = await mcpc([{
506
573
  name: "dev-inspector",
507
574
  version: "1.0.0",
508
575
  title: "A tool for inspecting and interacting with the development environment."
509
576
  }, { capabilities: {
510
- tools: {},
577
+ tools: { listChanged: true },
511
578
  sampling: {},
512
- prompts: {}
513
- } }], []);
579
+ prompts: { listChanged: true }
580
+ } }], [{
581
+ name: "chrome_devtools",
582
+ description: `Access Chrome DevTools for browser diagnostics.
583
+
584
+ Provides tools for inspecting network requests, console logs, and performance metrics.
585
+
586
+ IMPORTANT: Must first call chrome_navigate_page to launch Chrome before using these capabilities.
587
+ Default dev server URL: http://${serverContext?.host || "localhost"}:${serverContext?.port || 5173}
588
+
589
+ You MUST ask the user for confirmation before navigating to any URL.`,
590
+ options: { refs: ["<tool name=\"chrome.__ALL__\"/>"] },
591
+ deps: { mcpServers: { chrome: {
592
+ transportType: "stdio",
593
+ command: "node",
594
+ args: [getChromeDevToolsBinPath()]
595
+ } } }
596
+ }]);
514
597
  const mcpClientExecServer = createClientExecServer(mcpServer, "inspector");
515
598
  mcpClientExecServer.registerClientToolSchemas([
516
- { ...TOOL_SCHEMAS.inspect_element },
517
- { ...TOOL_SCHEMAS.get_all_feedbacks },
518
- { ...TOOL_SCHEMAS.update_feedback_status }
599
+ { ...TOOL_SCHEMAS.capture_element_context },
600
+ { ...TOOL_SCHEMAS.list_inspections },
601
+ { ...TOOL_SCHEMAS.update_inspection_status },
602
+ { ...TOOL_SCHEMAS.execute_page_script }
519
603
  ]);
520
604
  mcpServer.setRequestHandler(ListPromptsRequestSchema, async (request) => {
521
- return { prompts: [{
522
- name: "grab-element",
523
- title: "Inspect Element",
524
- description: "Inspect a UI element and get user feedback for modifications.",
525
- arguments: []
526
- }, {
527
- name: "view-feedbacks",
528
- title: "View All Feedbacks",
529
- description: "View all current feedback items in the queue with their status.",
530
- arguments: []
531
- }] };
605
+ const defaultUrl = `http://${serverContext?.host || "localhost"}:${serverContext?.port || 5173}`;
606
+ return { prompts: [
607
+ { ...PROMPT_SCHEMAS.capture_element },
608
+ { ...PROMPT_SCHEMAS.view_inspections },
609
+ {
610
+ ...PROMPT_SCHEMAS.launch_chrome_devtools,
611
+ description: `Launch Chrome DevTools and navigate to the dev server for debugging and inspection. Default URL: ${defaultUrl}. You can use this default URL or provide a custom one.`,
612
+ arguments: [{
613
+ name: "url",
614
+ description: `The URL to navigate to. Press Enter to use default: ${defaultUrl}`,
615
+ required: false
616
+ }]
617
+ },
618
+ { ...PROMPT_SCHEMAS.refresh_chrome_state }
619
+ ] };
532
620
  });
533
621
  mcpServer.setRequestHandler(GetPromptRequestSchema, async (request) => {
534
- if (request.params.name === "grab-element") return { messages: (await callMcpMethod(mcpServer, "tools/call", {
535
- name: "inspect_element",
536
- arguments: {}
537
- }))?.content.map((item) => ({
538
- role: "user",
539
- content: item
540
- })) || [] };
541
- else if (request.params.name === "view-feedbacks") return { messages: (await callMcpMethod(mcpServer, "tools/call", {
542
- name: "get_all_feedbacks",
543
- arguments: {}
544
- }))?.content.map((item) => ({
545
- role: "user",
546
- content: item
547
- })) || [] };
548
- else throw new Error(`Unknown promptId: ${request.params.name}`);
622
+ const promptName = request.params.name;
623
+ switch (promptName) {
624
+ case "capture_element": return { messages: (await callMcpMethod(mcpServer, "tools/call", {
625
+ name: "capture_element_context",
626
+ arguments: {}
627
+ }))?.content.map((item) => ({
628
+ role: "user",
629
+ content: item
630
+ })) || [] };
631
+ case "view_inspections": return { messages: (await callMcpMethod(mcpServer, "tools/call", {
632
+ name: "list_inspections",
633
+ arguments: {}
634
+ }))?.content.map((item) => ({
635
+ role: "user",
636
+ content: item
637
+ })) || [] };
638
+ case "launch_chrome_devtools": {
639
+ const defaultUrl = `http://${serverContext?.host || "localhost"}:${serverContext?.port || 5173}`;
640
+ const url = request.params.arguments?.url || defaultUrl;
641
+ try {
642
+ new URL(url);
643
+ } catch (error) {
644
+ return { messages: [{
645
+ role: "user",
646
+ content: {
647
+ type: "text",
648
+ text: `Error: Invalid URL format: "${url}". Please provide a valid URL (e.g., http://localhost:5173)`
649
+ }
650
+ }] };
651
+ }
652
+ try {
653
+ return { messages: [...((await callMcpMethod(mcpServer, "tools/call", {
654
+ name: "chrome_devtools",
655
+ arguments: {
656
+ useTool: "chrome_navigate_page",
657
+ hasDefinitions: ["chrome_navigate_page"],
658
+ chrome_navigate_page: { url }
659
+ }
660
+ }))?.content || []).map((item) => ({
661
+ role: "user",
662
+ content: item
663
+ }))] };
664
+ } catch (error) {
665
+ return { messages: [{
666
+ role: "user",
667
+ content: {
668
+ type: "text",
669
+ text: `Error launching Chrome DevTools: ${error instanceof Error ? error.message : String(error)}`
670
+ }
671
+ }] };
672
+ }
673
+ }
674
+ case "refresh_chrome_state": try {
675
+ const result = await callMcpMethod(mcpServer, "tools/call", {
676
+ name: "chrome_devtools",
677
+ arguments: {
678
+ useTool: "chrome_list_network_requests",
679
+ hasDefinitions: ["chrome_list_network_requests"],
680
+ chrome_list_network_requests: {}
681
+ }
682
+ });
683
+ const reqIdMatches = (result?.content?.map((item) => item.text).join("\n") || "").matchAll(/reqid=(\d+)\s+(GET|POST|PUT|DELETE|PATCH)\s+([^\s]+)\s+\[([^\]]+)\]/g);
684
+ const requestOptions = Array.from(reqIdMatches).map((match) => {
685
+ const [, reqId, method, url, status] = match;
686
+ return ` ${reqId}: ${method} ${url.length > 60 ? url.substring(0, 57) + "..." : url} [${status}]`;
687
+ }).reverse().join("\n");
688
+ mcpServer.setRequestHandler(ListPromptsRequestSchema, async (request$1) => {
689
+ return { prompts: [
690
+ { ...PROMPT_SCHEMAS.capture_element },
691
+ { ...PROMPT_SCHEMAS.view_inspections },
692
+ { ...PROMPT_SCHEMAS.launch_chrome_devtools },
693
+ { ...PROMPT_SCHEMAS.refresh_chrome_state },
694
+ {
695
+ ...PROMPT_SCHEMAS.get_network_requests,
696
+ arguments: [{
697
+ name: "reqid",
698
+ description: `The request ID to get details for. Available requests:\n\n${requestOptions || "No requests available"}`,
699
+ required: true
700
+ }]
701
+ }
702
+ ] };
703
+ });
704
+ await mcpServer.sendPromptListChanged();
705
+ return { messages: [...(result?.content || []).map((item) => ({
706
+ role: "user",
707
+ content: item
708
+ }))] };
709
+ } catch (error) {
710
+ return { messages: [{
711
+ role: "user",
712
+ content: {
713
+ type: "text",
714
+ text: `Error launching Chrome DevTools: ${error instanceof Error ? error.message : String(error)}`
715
+ }
716
+ }] };
717
+ }
718
+ case "get_network_requests":
719
+ const reqid = parseInt(request.params.arguments?.reqid);
720
+ try {
721
+ return { messages: [...((await callMcpMethod(mcpServer, "tools/call", {
722
+ name: "chrome_devtools",
723
+ arguments: {
724
+ useTool: "chrome_get_network_request",
725
+ hasDefinitions: ["chrome_get_network_request"],
726
+ chrome_get_network_request: { reqid }
727
+ }
728
+ }))?.content || []).map((item) => ({
729
+ role: "user",
730
+ content: item
731
+ }))] };
732
+ } catch (error) {
733
+ return { messages: [{
734
+ role: "user",
735
+ content: {
736
+ type: "text",
737
+ text: `Error launching Chrome DevTools: ${error instanceof Error ? error.message : String(error)}`
738
+ }
739
+ }] };
740
+ }
741
+ default: throw new Error(`Unknown promptId: ${promptName}`);
742
+ }
549
743
  });
550
744
  return mcpClientExecServer;
551
745
  }
@@ -555,11 +749,11 @@ async function createInspectorMcpServer() {
555
749
  /**
556
750
  * Setup MCP server endpoints in Vite dev server
557
751
  */
558
- async function setupMcpMiddleware(middlewares) {
752
+ async function setupMcpMiddleware(middlewares, serverContext) {
559
753
  const transports = {};
560
754
  middlewares.use(async (req, res, next) => {
561
755
  const url = req.url || "";
562
- const mcpServer = await createInspectorMcpServer();
756
+ const mcpServer = await createInspectorMcpServer(serverContext);
563
757
  if (url.startsWith("/__mcp__") && !url.startsWith("/__mcp__/sse") && !url.startsWith("/__mcp__/messages")) {
564
758
  if (req.method === "POST") await handleStreamableHttpPost(req, res, mcpServer, transports);
565
759
  else if (req.method === "GET") await handleStreamableHttpGet(req, res, transports);
@@ -747,7 +941,7 @@ function isInitializeRequest(body) {
747
941
 
748
942
  //#endregion
749
943
  //#region src/middleware/inspector-middleware.ts
750
- const __dirname = dirname$1(fileURLToPath(import.meta.url));
944
+ const __dirname = dirname$1(fileURLToPath$1(import.meta.url));
751
945
  /**
752
946
  * Get the inspector client script content
753
947
  * Tries multiple paths to locate the bundled inspector script
@@ -870,7 +1064,7 @@ function resolveMcpRemote(cwd = process.cwd()) {
870
1064
 
871
1065
  //#endregion
872
1066
  //#region src/middleware/acp-middleware.ts
873
- function setupAcpMiddleware(middlewares) {
1067
+ function setupAcpMiddleware(middlewares, serverContext) {
874
1068
  middlewares.use("/api/acp/chat", async (req, res) => {
875
1069
  if (req.method !== "POST") {
876
1070
  res.statusCode = 405;
@@ -882,11 +1076,6 @@ function setupAcpMiddleware(middlewares) {
882
1076
  const { messages, agent, envVars } = JSON.parse(body);
883
1077
  const cwd = process.cwd();
884
1078
  const mcpRemote = resolveMcpRemote(cwd);
885
- console.log("ACP Agent Command:", {
886
- agent,
887
- envVars,
888
- mcpRemote
889
- });
890
1079
  const provider = createACPProvider({
891
1080
  command: agent.command,
892
1081
  args: agent.args,
@@ -895,7 +1084,7 @@ function setupAcpMiddleware(middlewares) {
895
1084
  cwd,
896
1085
  mcpServers: [{
897
1086
  command: mcpRemote.command,
898
- args: [...mcpRemote.args, "http://localhost:5173/__mcp__/sse?puppetId=chrome"],
1087
+ args: [...mcpRemote.args, `http://${serverContext?.host || "localhost"}:${serverContext?.port || 5173}/__mcp__/sse?puppetId=chrome`],
899
1088
  env: [],
900
1089
  name: "inspect"
901
1090
  }]
@@ -5425,13 +5614,13 @@ var require_lib = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/@babel+
5425
5614
  super.checkParams(node, false, true);
5426
5615
  this.scope.exit();
5427
5616
  }
5428
- forwardNoArrowParamsConversionAt(node, parse$2) {
5617
+ forwardNoArrowParamsConversionAt(node, parse$3) {
5429
5618
  let result;
5430
5619
  if (this.state.noArrowParamsConversionAt.includes(this.offsetToSourcePos(node.start))) {
5431
5620
  this.state.noArrowParamsConversionAt.push(this.state.start);
5432
- result = parse$2();
5621
+ result = parse$3();
5433
5622
  this.state.noArrowParamsConversionAt.pop();
5434
- } else result = parse$2();
5623
+ } else result = parse$3();
5435
5624
  return result;
5436
5625
  }
5437
5626
  parseParenItem(node, startLoc) {
@@ -14478,7 +14667,7 @@ var require_lib = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/@babel+
14478
14667
  return result;
14479
14668
  }
14480
14669
  };
14481
- function parse$1(input, options) {
14670
+ function parse$2(input, options) {
14482
14671
  var _options;
14483
14672
  if (((_options = options) == null ? void 0 : _options.sourceType) === "unambiguous") {
14484
14673
  options = Object.assign({}, options);
@@ -14536,19 +14725,19 @@ var require_lib = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/@babel+
14536
14725
  }
14537
14726
  return cls;
14538
14727
  }
14539
- exports.parse = parse$1;
14728
+ exports.parse = parse$2;
14540
14729
  }) });
14541
14730
 
14542
14731
  //#endregion
14543
14732
  //#region src/compiler/jsx-transform.ts
14544
14733
  var import_lib = require_lib();
14545
14734
  const traverse = createRequire(import.meta.url)("@babel/traverse").default;
14546
- function normalizePath(id) {
14735
+ function normalizePath$1(id) {
14547
14736
  return id.split(path.sep).join("/");
14548
14737
  }
14549
- const DATA_SOURCE_ATTR = "data-source";
14738
+ const DATA_SOURCE_ATTR$1 = "data-source";
14550
14739
  async function transformJSX({ code: code$1, id }) {
14551
- const relativePath = normalizePath(path.relative(process.cwd(), id));
14740
+ const relativePath = normalizePath$1(path.relative(process.cwd(), id));
14552
14741
  const ast = (0, import_lib.parse)(code$1, {
14553
14742
  sourceType: "module",
14554
14743
  plugins: [
@@ -14563,7 +14752,7 @@ async function transformJSX({ code: code$1, id }) {
14563
14752
  let hasModifications = false;
14564
14753
  traverse(ast, { JSXOpeningElement(path$2) {
14565
14754
  const node = path$2.node;
14566
- if (node.attributes.some((attr) => attr.type === "JSXAttribute" && attr.name.name === DATA_SOURCE_ATTR)) return;
14755
+ if (node.attributes.some((attr) => attr.type === "JSXAttribute" && attr.name.name === DATA_SOURCE_ATTR$1)) return;
14567
14756
  const { line, column } = node.loc.start;
14568
14757
  const sourceValue = `${relativePath}:${line}:${column}`;
14569
14758
  let insertPos;
@@ -14572,7 +14761,7 @@ async function transformJSX({ code: code$1, id }) {
14572
14761
  const tagName = node.name.name || "";
14573
14762
  insertPos = node.start + tagName.length + 1;
14574
14763
  }
14575
- s.prependLeft(insertPos, ` ${DATA_SOURCE_ATTR}="${sourceValue}"`);
14764
+ s.prependLeft(insertPos, ` ${DATA_SOURCE_ATTR$1}="${sourceValue}"`);
14576
14765
  hasModifications = true;
14577
14766
  } });
14578
14767
  if (!hasModifications) return null;
@@ -14582,6 +14771,42 @@ async function transformJSX({ code: code$1, id }) {
14582
14771
  };
14583
14772
  }
14584
14773
 
14774
+ //#endregion
14775
+ //#region src/compiler/vue-transform.ts
14776
+ function normalizePath(id) {
14777
+ return id.split(path.sep).join("/");
14778
+ }
14779
+ const DATA_SOURCE_ATTR = "data-source";
14780
+ async function compileVue({ code: code$1, id }) {
14781
+ const relativePath = normalizePath(path.relative(process.cwd(), id));
14782
+ const { descriptor } = parse(code$1, {
14783
+ filename: id,
14784
+ sourceMap: true
14785
+ });
14786
+ if (!descriptor.template || !descriptor.template.ast) return null;
14787
+ const s = new MagicString(code$1);
14788
+ let hasModifications = false;
14789
+ function traverse$1(node) {
14790
+ if (node.type === 1) {
14791
+ if (!node.props.some((prop) => prop.type === 6 && prop.name === DATA_SOURCE_ATTR)) {
14792
+ const { line, column } = node.loc.start;
14793
+ const sourceValue = `${relativePath}:${line}:${column}`;
14794
+ const tagName = node.tag;
14795
+ const insertPos = node.loc.start.offset + 1 + tagName.length;
14796
+ s.prependLeft(insertPos, ` ${DATA_SOURCE_ATTR}="${sourceValue}"`);
14797
+ hasModifications = true;
14798
+ }
14799
+ }
14800
+ if (node.children) node.children.forEach(traverse$1);
14801
+ }
14802
+ traverse$1(descriptor.template.ast);
14803
+ if (!hasModifications) return null;
14804
+ return {
14805
+ code: s.toString(),
14806
+ map: s.generateMap({ hires: true })
14807
+ };
14808
+ }
14809
+
14585
14810
  //#endregion
14586
14811
  //#region src/core.ts
14587
14812
  const unplugin = createUnplugin((options = {}) => {
@@ -14592,9 +14817,8 @@ const unplugin = createUnplugin((options = {}) => {
14592
14817
  name: "unplugin-dev-inspector",
14593
14818
  enforce: "pre",
14594
14819
  async transform(code$1, id) {
14595
- if (!id.match(/\.(jsx|tsx)$/)) return null;
14596
14820
  if (id.includes("node_modules")) return null;
14597
- try {
14821
+ if (id.match(/\.(jsx|tsx)$/)) try {
14598
14822
  return await transformJSX({
14599
14823
  code: code$1,
14600
14824
  id
@@ -14603,6 +14827,16 @@ const unplugin = createUnplugin((options = {}) => {
14603
14827
  console.error(`[dev-inspector] Failed to transform ${id}:`, error);
14604
14828
  return null;
14605
14829
  }
14830
+ if (id.match(/\.vue$/)) try {
14831
+ return await compileVue({
14832
+ code: code$1,
14833
+ id
14834
+ });
14835
+ } catch (error) {
14836
+ console.error(`[dev-inspector] Failed to transform ${id}:`, error);
14837
+ return null;
14838
+ }
14839
+ return null;
14606
14840
  },
14607
14841
  vite: {
14608
14842
  apply: "serve",
@@ -14612,8 +14846,15 @@ const unplugin = createUnplugin((options = {}) => {
14612
14846
  async configureServer(server) {
14613
14847
  console.log("\n✨ Dev Inspector Plugin enabled!");
14614
14848
  if (enableMcp) {
14615
- await setupMcpMiddleware(server.middlewares);
14616
- setupAcpMiddleware(server.middlewares);
14849
+ const host = server.config.server.host;
14850
+ const serverContext = {
14851
+ host: typeof host === "string" ? host : host === true ? "0.0.0.0" : "localhost",
14852
+ port: server.config.server.port || 5173
14853
+ };
14854
+ const displayHost = serverContext.host === "0.0.0.0" ? "localhost" : serverContext.host;
14855
+ console.log(`šŸ“” MCP: http://${displayHost}:${serverContext.port}/__mcp__/sse?puppetId=chrome\n`);
14856
+ await setupMcpMiddleware(server.middlewares, serverContext);
14857
+ setupAcpMiddleware(server.middlewares, serverContext);
14617
14858
  }
14618
14859
  setupInspectorMiddleware(server.middlewares);
14619
14860
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcpc-tech/unplugin-dev-inspector-mcp",
3
- "version": "0.0.1",
3
+ "version": "0.0.2-beta.2",
4
4
  "description": "Universal dev inspector plugin for React - inspect component sources and API calls in any bundler",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -110,6 +110,7 @@
110
110
  "@types/node": "^24.7.2",
111
111
  "@types/react": "^19.2.2",
112
112
  "@types/react-dom": "^19.2.2",
113
+ "@vue/compiler-sfc": "^3.5.24",
113
114
  "esbuild": "^0.25.11",
114
115
  "magic-string": "^0.30.21",
115
116
  "postcss": "^8.5.6",