@mcpc-tech/unplugin-dev-inspector-mcp 0.0.36 → 0.0.38

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.
@@ -21,6 +21,7 @@ let _modelcontextprotocol_sdk_inMemory_js = require("@modelcontextprotocol/sdk/i
21
21
  let node_process = require("node:process");
22
22
  node_process = require_chunk.__toESM(node_process);
23
23
  let os = require("os");
24
+ let child_process = require("child_process");
24
25
  let fs = require("fs");
25
26
  fs = require_chunk.__toESM(fs);
26
27
  let http = require("http");
@@ -58015,9 +58016,9 @@ var require_utils$5 = /* @__PURE__ */ require_chunk.__commonJSMin(((exports) =>
58015
58016
  var require_execAsync$1 = /* @__PURE__ */ require_chunk.__commonJSMin(((exports) => {
58016
58017
  Object.defineProperty(exports, "__esModule", { value: true });
58017
58018
  exports.execAsync = void 0;
58018
- const child_process$1 = require("child_process");
58019
+ const child_process$2 = require("child_process");
58019
58020
  const util$1 = require("util");
58020
- exports.execAsync = util$1.promisify(child_process$1.exec);
58021
+ exports.execAsync = util$1.promisify(child_process$2.exec);
58021
58022
  }));
58022
58023
 
58023
58024
  //#endregion
@@ -66167,9 +66168,9 @@ var require_utils$1 = /* @__PURE__ */ require_chunk.__commonJSMin(((exports) =>
66167
66168
  var require_execAsync = /* @__PURE__ */ require_chunk.__commonJSMin(((exports) => {
66168
66169
  Object.defineProperty(exports, "__esModule", { value: true });
66169
66170
  exports.execAsync = void 0;
66170
- const child_process = require("child_process");
66171
+ const child_process$1 = require("child_process");
66171
66172
  const util = require("util");
66172
- exports.execAsync = util.promisify(child_process.exec);
66173
+ exports.execAsync = util.promisify(child_process$1.exec);
66173
66174
  }));
66174
66175
 
66175
66176
  //#endregion
@@ -83445,19 +83446,6 @@ async function getOrCreateMcpClient(defKey, def) {
83445
83446
  mcpClientConnecting.delete(defKey);
83446
83447
  }
83447
83448
  }
83448
- async function releaseMcpClient(defKey) {
83449
- const entry = mcpClientPool.get(defKey);
83450
- if (!entry) return;
83451
- entry.refCount -= 1;
83452
- if (entry.refCount <= 0) {
83453
- mcpClientPool.delete(defKey);
83454
- try {
83455
- await entry.client.close();
83456
- } catch (err) {
83457
- console.error("Error closing MCP client:", err);
83458
- }
83459
- }
83460
- }
83461
83449
  var cleanupAllPooledClients = async () => {
83462
83450
  const entries = Array.from(mcpClientPool.entries());
83463
83451
  mcpClientPool.clear();
@@ -83515,12 +83503,7 @@ async function composeMcpDepTools(mcpConfig, filterIn) {
83515
83503
  console.error(`Error creating MCP client for ${name}:`, error);
83516
83504
  }
83517
83505
  }
83518
- const cleanupClients = async () => {
83519
- await Promise.all(acquiredKeys.map((k) => releaseMcpClient(k)));
83520
- acquiredKeys.length = 0;
83521
- Object.keys(allTools).forEach((key) => delete allTools[key]);
83522
- Object.keys(allClients).forEach((key) => delete allClients[key]);
83523
- };
83506
+ const cleanupClients = async () => {};
83524
83507
  return {
83525
83508
  tools: allTools,
83526
83509
  clients: allClients,
@@ -86322,17 +86305,6 @@ var ComposableMCPServer = class extends _modelcontextprotocol_sdk_server_index_j
86322
86305
  server: this,
86323
86306
  toolNames: Object.keys(allTools)
86324
86307
  });
86325
- this.onclose = async () => {
86326
- await cleanupClients();
86327
- await this.disposePlugins();
86328
- await this.logger.info(`[${name}] Event: closed - cleaned up dependent clients and plugins`);
86329
- };
86330
- this.onerror = async (error) => {
86331
- await this.logger.error(`[${name}] Event: error - ${error?.stack ?? String(error)}`);
86332
- await cleanupClients();
86333
- await this.disposePlugins();
86334
- await this.logger.info(`[${name}] Action: cleaned up dependent clients and plugins`);
86335
- };
86336
86308
  const toolNameToDetailList = Object.entries(allTools);
86337
86309
  const publicToolNames = this.getPublicToolNames();
86338
86310
  const hiddenToolNames = this.getHiddenToolNames();
@@ -86845,6 +86817,7 @@ var ConnectionManager = class {
86845
86817
  transport.onclose = () => this.removeTransport(sessionId);
86846
86818
  }
86847
86819
  removeTransport(sessionId) {
86820
+ console.log(`[dev-inspector] [connection-manager] Removing transport: ${sessionId}`);
86848
86821
  delete this.transports[sessionId];
86849
86822
  for (const [_clientId, sessionIds] of this.watchersByClientId) if (sessionIds.has(sessionId)) {
86850
86823
  sessionIds.delete(sessionId);
@@ -86875,6 +86848,7 @@ var ConnectionManager = class {
86875
86848
  }
86876
86849
  sessionsToRemove.push(existingSessionId);
86877
86850
  }
86851
+ if (sessionsToRemove.length > 0) console.log(`[dev-inspector] [connection-manager] Cleaned up ${sessionsToRemove.length} previous sessions for clientId=${clientId} (new session=${newSessionId})`);
86878
86852
  for (const sessionId of sessionsToRemove) sessionIds.delete(sessionId);
86879
86853
  }
86880
86854
  handleInspectorConnection(sessionId) {
@@ -86894,11 +86868,14 @@ var ConnectionManager = class {
86894
86868
  }
86895
86869
  }
86896
86870
  /**
86897
- * Handle watcher connection.
86898
- * @param sessionId - unique session ID
86899
- * @param clientId - who is connecting (vscode, acp, cursor, etc.)
86900
- * @param puppetId - who to control (inspector)
86901
- * @param transport - the transport instance
86871
+ * Get the currently active Inspector (browser) transport
86872
+ */
86873
+ getInspectorTransport() {
86874
+ if (!this.latestInspectorSessionId) return null;
86875
+ return this.transports[this.latestInspectorSessionId] || null;
86876
+ }
86877
+ /**
86878
+ * Bind watcher (e.g. VS Code/ACP) to Inspector (browser)
86902
86879
  */
86903
86880
  handleWatcherConnection(sessionId, clientId, puppetId, transport) {
86904
86881
  this.cleanupPreviousWatchers(clientId, sessionId);
@@ -87082,11 +87059,17 @@ async function handleSseConnection(req, res, serverContext, connectionManager) {
87082
87059
  const url$1 = new URL(req.url ?? "", `http://${host}:${port}`);
87083
87060
  const transport = new _modelcontextprotocol_sdk_server_sse_js.SSEServerTransport("/__mcp__/messages", res);
87084
87061
  const sessionId = transport.sessionId;
87085
- const clientId = url$1.searchParams.get("clientId") || "agent";
87062
+ const clientId = url$1.searchParams.get("clientId") || `agent-${sessionId}`;
87086
87063
  const puppetId = url$1.searchParams.get("puppetId") || "inspector";
87064
+ console.log(`[dev-inspector] [sse] New connection request: clientId=${clientId}, puppetId=${puppetId}, sessionId=${sessionId}`);
87087
87065
  connectionManager.registerTransport(sessionId, transport);
87088
- if (clientId === "inspector") connectionManager.handleInspectorConnection(sessionId);
87089
- else connectionManager.handleWatcherConnection(sessionId, clientId, puppetId, transport);
87066
+ if (clientId === "inspector") {
87067
+ console.log(`[dev-inspector] [sse] Handling Inspector connection: ${sessionId}`);
87068
+ connectionManager.handleInspectorConnection(sessionId);
87069
+ } else {
87070
+ console.log(`[dev-inspector] [sse] Handling Watcher connection: ${sessionId} (binding to ${puppetId})`);
87071
+ connectionManager.handleWatcherConnection(sessionId, clientId, puppetId, transport);
87072
+ }
87090
87073
  await mcpServer.connect(transport);
87091
87074
  } catch (error) {
87092
87075
  console.error("Error establishing SSE connection:", error);
@@ -88100,6 +88083,7 @@ var ACPLanguageModel = class {
88100
88083
  try {
88101
88084
  await this.ensureConnected();
88102
88085
  const promptContent = convertAiSdkMessagesToAcp(options, this.isFreshSession);
88086
+ console.log(`###########`, promptContent);
88103
88087
  this.isFreshSession = false;
88104
88088
  let accumulatedText = "";
88105
88089
  const toolCalls = [];
@@ -88309,6 +88293,19 @@ function createACPProvider(config) {
88309
88293
  //#endregion
88310
88294
  //#region src/middleware/acp-middleware.ts
88311
88295
  /**
88296
+ * Check if a command exists in the system PATH
88297
+ * Skips check for npx since it always exists
88298
+ */
88299
+ function checkCommandExists(command) {
88300
+ if (command === "npx" || command === "node") return true;
88301
+ try {
88302
+ (0, child_process.execSync)(`which ${command}`, { stdio: "ignore" });
88303
+ return true;
88304
+ } catch {
88305
+ return false;
88306
+ }
88307
+ }
88308
+ /**
88312
88309
  * Provider manager - stores one provider per agent config
88313
88310
  * Key: agentKey (command:args), Value: ProviderEntry
88314
88311
  */
@@ -88372,14 +88369,33 @@ async function loadMcpToolsV5(transport) {
88372
88369
  return tools;
88373
88370
  }
88374
88371
  /**
88372
+ * Default system instructions for DevInspector - provides AI guidance
88373
+ */
88374
+ const DEFAULT_SYSTEM_INSTRUCTIONS = `# DevInspector Context
88375
+
88376
+ You are connected to a web app with DevInspector. Available tools:
88377
+
88378
+ - **list_inspections**: Check pending element inspections from user
88379
+ - **capture_element_context**: Activate visual selector to capture UI elements
88380
+ - **update_inspection_status**: Update inspection status with progress/results
88381
+ - **execute_page_script**: Run JavaScript in browser context
88382
+ - **chrome_devtools**: Access Chrome DevTools for network, console, performance
88383
+
88384
+ Workflow: Check \`list_inspections\` first. If there are pending items, help resolve them. Otherwise, assist with the user's request.`;
88385
+ /**
88375
88386
  * Get an active transport from the connection manager
88376
88387
  */
88377
88388
  function getActiveTransport() {
88378
88389
  const connectionManager = getConnectionManager();
88379
88390
  if (!connectionManager) return null;
88380
- const sessionIds = Object.keys(connectionManager.transports);
88381
- if (sessionIds.length === 0) return null;
88382
- return connectionManager.transports[sessionIds[0]];
88391
+ return connectionManager.getInspectorTransport() || connectionManager.transports[Object.keys(connectionManager.transports)[0]];
88392
+ }
88393
+ /**
88394
+ * Get specifically the inspector transport for context and tools
88395
+ */
88396
+ function getInspectorTransport() {
88397
+ const connectionManager = getConnectionManager();
88398
+ return connectionManager ? connectionManager.getInspectorTransport() : null;
88383
88399
  }
88384
88400
  function setupAcpMiddleware(middlewares, serverContext, acpOptions) {
88385
88401
  /**
@@ -88426,6 +88442,14 @@ function setupAcpMiddleware(middlewares, serverContext, acpOptions) {
88426
88442
  console.log(`[dev-inspector] [acp] Reusing existing provider for ${agent.name}`);
88427
88443
  provider = providerEntry.provider;
88428
88444
  } else {
88445
+ if (!checkCommandExists(agent.command)) {
88446
+ const hints = [`Agent "${agent.name}" command not found: "${agent.command}"`];
88447
+ if (agent.installCommand) hints.push(`Install with: ${agent.installCommand}`);
88448
+ if (agent.configHint) hints.push(agent.configHint);
88449
+ if (agent.configLink) hints.push(`Documentation: ${agent.configLink}`);
88450
+ console.error(`\n${hints.join("\n")}\n`);
88451
+ return;
88452
+ }
88429
88453
  console.log(`[dev-inspector] [acp] Creating new global provider for ${agent.name}`);
88430
88454
  provider = createACPProvider({
88431
88455
  command: agent.command,
@@ -88452,7 +88476,7 @@ function setupAcpMiddleware(middlewares, serverContext, acpOptions) {
88452
88476
  }
88453
88477
  console.log(`[dev-inspector] [acp] Spawning new process/session for ${agent.name}`);
88454
88478
  const initPromise = (async () => {
88455
- const transport = getActiveTransport();
88479
+ const transport = getInspectorTransport() || getActiveTransport();
88456
88480
  let initialTools = {};
88457
88481
  if (transport) try {
88458
88482
  const rawTools = await loadMcpToolsV5(transport);
@@ -88484,6 +88508,7 @@ function setupAcpMiddleware(middlewares, serverContext, acpOptions) {
88484
88508
  res.setHeader("Content-Type", "application/json");
88485
88509
  res.end(JSON.stringify({ sessionId }));
88486
88510
  } catch (error) {
88511
+ if (error instanceof Error && error.message.includes("command not found")) throw error;
88487
88512
  console.error("ACP Init Session Error:", error);
88488
88513
  if (!res.headersSent) {
88489
88514
  res.statusCode = 500;
@@ -88578,7 +88603,7 @@ function setupAcpMiddleware(middlewares, serverContext, acpOptions) {
88578
88603
  });
88579
88604
  await provider.initSession();
88580
88605
  }
88581
- const transport = getActiveTransport();
88606
+ const transport = getInspectorTransport() || getActiveTransport();
88582
88607
  let mcpTools = {};
88583
88608
  if (transport) mcpTools = await loadMcpToolsV5(transport);
88584
88609
  else console.warn("[dev-inspector] [acp] No active MCP transport available, tools will not be loaded");
@@ -88595,10 +88620,21 @@ function setupAcpMiddleware(middlewares, serverContext, acpOptions) {
88595
88620
  abortController.abort();
88596
88621
  if (shouldCleanupProvider) provider.cleanup();
88597
88622
  });
88623
+ const systemPrompt = agent.acpSystemPrompt ?? acpOptions?.acpSystemPrompt ?? DEFAULT_SYSTEM_INSTRUCTIONS;
88624
+ const enhancedMessages = (0, ai.convertToModelMessages)(messages).map((msg, index$1) => {
88625
+ if (index$1 === 0 && msg.role === "user" && Array.isArray(msg.content)) return {
88626
+ ...msg,
88627
+ content: [{
88628
+ type: "text",
88629
+ text: `<system_instructions>\n${systemPrompt}\n</system_instructions>\n\n`
88630
+ }, ...msg.content]
88631
+ };
88632
+ return msg;
88633
+ });
88598
88634
  const response = (0, ai.streamText)({
88599
88635
  model: provider.languageModel(model, mode),
88600
88636
  includeRawChunks: true,
88601
- messages: (0, ai.convertToModelMessages)(messages),
88637
+ messages: enhancedMessages,
88602
88638
  abortSignal: abortController.signal,
88603
88639
  tools: acpTools(mcpTools),
88604
88640
  onError: (error) => {
@@ -17,6 +17,7 @@ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/
17
17
  import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
18
18
  import process$1, { cwd } from "node:process";
19
19
  import { homedir } from "os";
20
+ import { execSync } from "child_process";
20
21
  import fs, { existsSync } from "fs";
21
22
  import * as http from "http";
22
23
  import * as https from "https";
@@ -83480,19 +83481,6 @@ async function getOrCreateMcpClient(defKey, def) {
83480
83481
  mcpClientConnecting.delete(defKey);
83481
83482
  }
83482
83483
  }
83483
- async function releaseMcpClient(defKey) {
83484
- const entry = mcpClientPool.get(defKey);
83485
- if (!entry) return;
83486
- entry.refCount -= 1;
83487
- if (entry.refCount <= 0) {
83488
- mcpClientPool.delete(defKey);
83489
- try {
83490
- await entry.client.close();
83491
- } catch (err) {
83492
- console.error("Error closing MCP client:", err);
83493
- }
83494
- }
83495
- }
83496
83484
  var cleanupAllPooledClients = async () => {
83497
83485
  const entries = Array.from(mcpClientPool.entries());
83498
83486
  mcpClientPool.clear();
@@ -83550,12 +83538,7 @@ async function composeMcpDepTools(mcpConfig, filterIn) {
83550
83538
  console.error(`Error creating MCP client for ${name}:`, error);
83551
83539
  }
83552
83540
  }
83553
- const cleanupClients = async () => {
83554
- await Promise.all(acquiredKeys.map((k) => releaseMcpClient(k)));
83555
- acquiredKeys.length = 0;
83556
- Object.keys(allTools).forEach((key) => delete allTools[key]);
83557
- Object.keys(allClients).forEach((key) => delete allClients[key]);
83558
- };
83541
+ const cleanupClients = async () => {};
83559
83542
  return {
83560
83543
  tools: allTools,
83561
83544
  clients: allClients,
@@ -86357,17 +86340,6 @@ var ComposableMCPServer = class extends Server {
86357
86340
  server: this,
86358
86341
  toolNames: Object.keys(allTools)
86359
86342
  });
86360
- this.onclose = async () => {
86361
- await cleanupClients();
86362
- await this.disposePlugins();
86363
- await this.logger.info(`[${name}] Event: closed - cleaned up dependent clients and plugins`);
86364
- };
86365
- this.onerror = async (error) => {
86366
- await this.logger.error(`[${name}] Event: error - ${error?.stack ?? String(error)}`);
86367
- await cleanupClients();
86368
- await this.disposePlugins();
86369
- await this.logger.info(`[${name}] Action: cleaned up dependent clients and plugins`);
86370
- };
86371
86343
  const toolNameToDetailList = Object.entries(allTools);
86372
86344
  const publicToolNames = this.getPublicToolNames();
86373
86345
  const hiddenToolNames = this.getHiddenToolNames();
@@ -86880,6 +86852,7 @@ var ConnectionManager = class {
86880
86852
  transport.onclose = () => this.removeTransport(sessionId);
86881
86853
  }
86882
86854
  removeTransport(sessionId) {
86855
+ console.log(`[dev-inspector] [connection-manager] Removing transport: ${sessionId}`);
86883
86856
  delete this.transports[sessionId];
86884
86857
  for (const [_clientId, sessionIds] of this.watchersByClientId) if (sessionIds.has(sessionId)) {
86885
86858
  sessionIds.delete(sessionId);
@@ -86910,6 +86883,7 @@ var ConnectionManager = class {
86910
86883
  }
86911
86884
  sessionsToRemove.push(existingSessionId);
86912
86885
  }
86886
+ if (sessionsToRemove.length > 0) console.log(`[dev-inspector] [connection-manager] Cleaned up ${sessionsToRemove.length} previous sessions for clientId=${clientId} (new session=${newSessionId})`);
86913
86887
  for (const sessionId of sessionsToRemove) sessionIds.delete(sessionId);
86914
86888
  }
86915
86889
  handleInspectorConnection(sessionId) {
@@ -86929,11 +86903,14 @@ var ConnectionManager = class {
86929
86903
  }
86930
86904
  }
86931
86905
  /**
86932
- * Handle watcher connection.
86933
- * @param sessionId - unique session ID
86934
- * @param clientId - who is connecting (vscode, acp, cursor, etc.)
86935
- * @param puppetId - who to control (inspector)
86936
- * @param transport - the transport instance
86906
+ * Get the currently active Inspector (browser) transport
86907
+ */
86908
+ getInspectorTransport() {
86909
+ if (!this.latestInspectorSessionId) return null;
86910
+ return this.transports[this.latestInspectorSessionId] || null;
86911
+ }
86912
+ /**
86913
+ * Bind watcher (e.g. VS Code/ACP) to Inspector (browser)
86937
86914
  */
86938
86915
  handleWatcherConnection(sessionId, clientId, puppetId, transport) {
86939
86916
  this.cleanupPreviousWatchers(clientId, sessionId);
@@ -87117,11 +87094,17 @@ async function handleSseConnection(req, res, serverContext, connectionManager) {
87117
87094
  const url = new URL(req.url ?? "", `http://${host}:${port}`);
87118
87095
  const transport = new SSEServerTransport("/__mcp__/messages", res);
87119
87096
  const sessionId = transport.sessionId;
87120
- const clientId = url.searchParams.get("clientId") || "agent";
87097
+ const clientId = url.searchParams.get("clientId") || `agent-${sessionId}`;
87121
87098
  const puppetId = url.searchParams.get("puppetId") || "inspector";
87099
+ console.log(`[dev-inspector] [sse] New connection request: clientId=${clientId}, puppetId=${puppetId}, sessionId=${sessionId}`);
87122
87100
  connectionManager.registerTransport(sessionId, transport);
87123
- if (clientId === "inspector") connectionManager.handleInspectorConnection(sessionId);
87124
- else connectionManager.handleWatcherConnection(sessionId, clientId, puppetId, transport);
87101
+ if (clientId === "inspector") {
87102
+ console.log(`[dev-inspector] [sse] Handling Inspector connection: ${sessionId}`);
87103
+ connectionManager.handleInspectorConnection(sessionId);
87104
+ } else {
87105
+ console.log(`[dev-inspector] [sse] Handling Watcher connection: ${sessionId} (binding to ${puppetId})`);
87106
+ connectionManager.handleWatcherConnection(sessionId, clientId, puppetId, transport);
87107
+ }
87125
87108
  await mcpServer.connect(transport);
87126
87109
  } catch (error) {
87127
87110
  console.error("Error establishing SSE connection:", error);
@@ -88135,6 +88118,7 @@ var ACPLanguageModel = class {
88135
88118
  try {
88136
88119
  await this.ensureConnected();
88137
88120
  const promptContent = convertAiSdkMessagesToAcp(options, this.isFreshSession);
88121
+ console.log(`###########`, promptContent);
88138
88122
  this.isFreshSession = false;
88139
88123
  let accumulatedText = "";
88140
88124
  const toolCalls = [];
@@ -88344,6 +88328,19 @@ function createACPProvider(config) {
88344
88328
  //#endregion
88345
88329
  //#region src/middleware/acp-middleware.ts
88346
88330
  /**
88331
+ * Check if a command exists in the system PATH
88332
+ * Skips check for npx since it always exists
88333
+ */
88334
+ function checkCommandExists(command) {
88335
+ if (command === "npx" || command === "node") return true;
88336
+ try {
88337
+ execSync(`which ${command}`, { stdio: "ignore" });
88338
+ return true;
88339
+ } catch {
88340
+ return false;
88341
+ }
88342
+ }
88343
+ /**
88347
88344
  * Provider manager - stores one provider per agent config
88348
88345
  * Key: agentKey (command:args), Value: ProviderEntry
88349
88346
  */
@@ -88407,14 +88404,33 @@ async function loadMcpToolsV5(transport) {
88407
88404
  return tools;
88408
88405
  }
88409
88406
  /**
88407
+ * Default system instructions for DevInspector - provides AI guidance
88408
+ */
88409
+ const DEFAULT_SYSTEM_INSTRUCTIONS = `# DevInspector Context
88410
+
88411
+ You are connected to a web app with DevInspector. Available tools:
88412
+
88413
+ - **list_inspections**: Check pending element inspections from user
88414
+ - **capture_element_context**: Activate visual selector to capture UI elements
88415
+ - **update_inspection_status**: Update inspection status with progress/results
88416
+ - **execute_page_script**: Run JavaScript in browser context
88417
+ - **chrome_devtools**: Access Chrome DevTools for network, console, performance
88418
+
88419
+ Workflow: Check \`list_inspections\` first. If there are pending items, help resolve them. Otherwise, assist with the user's request.`;
88420
+ /**
88410
88421
  * Get an active transport from the connection manager
88411
88422
  */
88412
88423
  function getActiveTransport() {
88413
88424
  const connectionManager = getConnectionManager();
88414
88425
  if (!connectionManager) return null;
88415
- const sessionIds = Object.keys(connectionManager.transports);
88416
- if (sessionIds.length === 0) return null;
88417
- return connectionManager.transports[sessionIds[0]];
88426
+ return connectionManager.getInspectorTransport() || connectionManager.transports[Object.keys(connectionManager.transports)[0]];
88427
+ }
88428
+ /**
88429
+ * Get specifically the inspector transport for context and tools
88430
+ */
88431
+ function getInspectorTransport() {
88432
+ const connectionManager = getConnectionManager();
88433
+ return connectionManager ? connectionManager.getInspectorTransport() : null;
88418
88434
  }
88419
88435
  function setupAcpMiddleware(middlewares, serverContext, acpOptions) {
88420
88436
  /**
@@ -88461,6 +88477,14 @@ function setupAcpMiddleware(middlewares, serverContext, acpOptions) {
88461
88477
  console.log(`[dev-inspector] [acp] Reusing existing provider for ${agent.name}`);
88462
88478
  provider = providerEntry.provider;
88463
88479
  } else {
88480
+ if (!checkCommandExists(agent.command)) {
88481
+ const hints = [`Agent "${agent.name}" command not found: "${agent.command}"`];
88482
+ if (agent.installCommand) hints.push(`Install with: ${agent.installCommand}`);
88483
+ if (agent.configHint) hints.push(agent.configHint);
88484
+ if (agent.configLink) hints.push(`Documentation: ${agent.configLink}`);
88485
+ console.error(`\n${hints.join("\n")}\n`);
88486
+ return;
88487
+ }
88464
88488
  console.log(`[dev-inspector] [acp] Creating new global provider for ${agent.name}`);
88465
88489
  provider = createACPProvider({
88466
88490
  command: agent.command,
@@ -88487,7 +88511,7 @@ function setupAcpMiddleware(middlewares, serverContext, acpOptions) {
88487
88511
  }
88488
88512
  console.log(`[dev-inspector] [acp] Spawning new process/session for ${agent.name}`);
88489
88513
  const initPromise = (async () => {
88490
- const transport = getActiveTransport();
88514
+ const transport = getInspectorTransport() || getActiveTransport();
88491
88515
  let initialTools = {};
88492
88516
  if (transport) try {
88493
88517
  const rawTools = await loadMcpToolsV5(transport);
@@ -88519,6 +88543,7 @@ function setupAcpMiddleware(middlewares, serverContext, acpOptions) {
88519
88543
  res.setHeader("Content-Type", "application/json");
88520
88544
  res.end(JSON.stringify({ sessionId }));
88521
88545
  } catch (error) {
88546
+ if (error instanceof Error && error.message.includes("command not found")) throw error;
88522
88547
  console.error("ACP Init Session Error:", error);
88523
88548
  if (!res.headersSent) {
88524
88549
  res.statusCode = 500;
@@ -88613,7 +88638,7 @@ function setupAcpMiddleware(middlewares, serverContext, acpOptions) {
88613
88638
  });
88614
88639
  await provider.initSession();
88615
88640
  }
88616
- const transport = getActiveTransport();
88641
+ const transport = getInspectorTransport() || getActiveTransport();
88617
88642
  let mcpTools = {};
88618
88643
  if (transport) mcpTools = await loadMcpToolsV5(transport);
88619
88644
  else console.warn("[dev-inspector] [acp] No active MCP transport available, tools will not be loaded");
@@ -88630,10 +88655,21 @@ function setupAcpMiddleware(middlewares, serverContext, acpOptions) {
88630
88655
  abortController.abort();
88631
88656
  if (shouldCleanupProvider) provider.cleanup();
88632
88657
  });
88658
+ const systemPrompt = agent.acpSystemPrompt ?? acpOptions?.acpSystemPrompt ?? DEFAULT_SYSTEM_INSTRUCTIONS;
88659
+ const enhancedMessages = convertToModelMessages(messages).map((msg, index$1) => {
88660
+ if (index$1 === 0 && msg.role === "user" && Array.isArray(msg.content)) return {
88661
+ ...msg,
88662
+ content: [{
88663
+ type: "text",
88664
+ text: `<system_instructions>\n${systemPrompt}\n</system_instructions>\n\n`
88665
+ }, ...msg.content]
88666
+ };
88667
+ return msg;
88668
+ });
88633
88669
  const response = streamText({
88634
88670
  model: provider.languageModel(model, mode),
88635
88671
  includeRawChunks: true,
88636
- messages: convertToModelMessages(messages),
88672
+ messages: enhancedMessages,
88637
88673
  abortSignal: abortController.signal,
88638
88674
  tools: acpTools(mcpTools),
88639
88675
  onError: (error) => {
package/dist/index.cjs CHANGED
@@ -23,7 +23,7 @@ var browser_launcher_exports = /* @__PURE__ */ require_chunk.__export({ launchBr
23
23
  */
24
24
  async function launchBrowserWithDevTools(options) {
25
25
  const { url, serverContext } = options;
26
- const sseUrl = `http://${serverContext.host === "0.0.0.0" ? "localhost" : serverContext.host || "localhost"}:${serverContext.port || 5173}/__mcp__/sse?clientId=auto-browser`;
26
+ const sseUrl = `http://${serverContext.host === "0.0.0.0" ? "localhost" : serverContext.host || "localhost"}:${serverContext.port || 5173}/__mcp__/sse?clientId=temp-browser-launcher`;
27
27
  let client = null;
28
28
  try {
29
29
  client = new _modelcontextprotocol_sdk_client_index_js.Client({
@@ -44,6 +44,8 @@ async function launchBrowserWithDevTools(options) {
44
44
  } catch (error) {
45
45
  console.error(`[dev-inspector] ⚠️ Failed to auto-open browser:`, error instanceof Error ? error.message : String(error));
46
46
  return false;
47
+ } finally {
48
+ await client?.close().catch(() => {});
47
49
  }
48
50
  }
49
51
  var init_browser_launcher = require_chunk.__esmMin((() => {}));
package/dist/index.d.cts CHANGED
@@ -52,6 +52,11 @@ interface AcpOptions {
52
52
  * @default undefined (skipped if not specified)
53
53
  */
54
54
  acpDelay?: number;
55
+ /**
56
+ * Custom system instructions to prepend to user messages
57
+ * @default undefined (uses built-in DevInspector context)
58
+ */
59
+ acpSystemPrompt?: string;
55
60
  }
56
61
  interface Agent extends AcpOptions {
57
62
  name: string;
@@ -65,6 +70,18 @@ interface Agent extends AcpOptions {
65
70
  meta?: {
66
71
  icon?: string;
67
72
  };
73
+ /**
74
+ * Configuration hint text to help users set up the agent
75
+ */
76
+ configHint?: string;
77
+ /**
78
+ * Link to configuration documentation or setup guide
79
+ */
80
+ configLink?: string;
81
+ /**
82
+ * Installation command for the agent (shown in error messages)
83
+ */
84
+ installCommand?: string;
68
85
  }
69
86
  //#endregion
70
87
  //#region src/utils/create-plugin.d.ts
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import * as unplugin0 from "unplugin";
1
+ import * as unplugin1 from "unplugin";
2
2
 
3
3
  //#region src/utils/config-updater.d.ts
4
4
  type EditorId = "cursor" | "vscode" | "windsurf" | "claude-code" | "antigravity";
@@ -52,6 +52,11 @@ interface AcpOptions {
52
52
  * @default undefined (skipped if not specified)
53
53
  */
54
54
  acpDelay?: number;
55
+ /**
56
+ * Custom system instructions to prepend to user messages
57
+ * @default undefined (uses built-in DevInspector context)
58
+ */
59
+ acpSystemPrompt?: string;
55
60
  }
56
61
  interface Agent extends AcpOptions {
57
62
  name: string;
@@ -65,6 +70,18 @@ interface Agent extends AcpOptions {
65
70
  meta?: {
66
71
  icon?: string;
67
72
  };
73
+ /**
74
+ * Configuration hint text to help users set up the agent
75
+ */
76
+ configHint?: string;
77
+ /**
78
+ * Link to configuration documentation or setup guide
79
+ */
80
+ configLink?: string;
81
+ /**
82
+ * Installation command for the agent (shown in error messages)
83
+ */
84
+ installCommand?: string;
68
85
  }
69
86
  //#endregion
70
87
  //#region src/utils/create-plugin.d.ts
@@ -134,10 +151,10 @@ interface DevInspectorOptions extends McpConfigOptions, AcpOptions {
134
151
  }
135
152
  //#endregion
136
153
  //#region src/core.d.ts
137
- declare const unplugin: unplugin0.UnpluginInstance<DevInspectorOptions | undefined, boolean>;
154
+ declare const unplugin: unplugin1.UnpluginInstance<DevInspectorOptions | undefined, boolean>;
138
155
  //#endregion
139
156
  //#region src/core-external.d.ts
140
- declare const unpluginExternal: unplugin0.UnpluginInstance<DevInspectorOptions | undefined, boolean>;
157
+ declare const unpluginExternal: unplugin1.UnpluginInstance<DevInspectorOptions | undefined, boolean>;
141
158
  //#endregion
142
159
  //#region src/turbopack.d.ts
143
160
  interface TurbopackDevInspectorOptions extends DevInspectorOptions {
@@ -162,7 +179,7 @@ interface TurbopackDevInspectorOptions extends DevInspectorOptions {
162
179
  declare function turbopackDevInspector(options?: TurbopackDevInspectorOptions): any;
163
180
  //#endregion
164
181
  //#region src/index.d.ts
165
- declare const external: unplugin0.UnpluginInstance<DevInspectorOptions | undefined, boolean>;
182
+ declare const external: unplugin1.UnpluginInstance<DevInspectorOptions | undefined, boolean>;
166
183
  declare module "virtual:dev-inspector-mcp" {}
167
184
  //#endregion
168
185
  export { type CustomEditorConfig, type DevInspectorOptions, type EditorId, type McpConfigOptions, type TurbopackDevInspectorOptions, unplugin as default, unplugin, external, turbopackDevInspector, unpluginExternal };
package/dist/index.js CHANGED
@@ -19,7 +19,7 @@ var browser_launcher_exports = /* @__PURE__ */ __export({ launchBrowserWithDevTo
19
19
  */
20
20
  async function launchBrowserWithDevTools(options) {
21
21
  const { url, serverContext } = options;
22
- const sseUrl = `http://${serverContext.host === "0.0.0.0" ? "localhost" : serverContext.host || "localhost"}:${serverContext.port || 5173}/__mcp__/sse?clientId=auto-browser`;
22
+ const sseUrl = `http://${serverContext.host === "0.0.0.0" ? "localhost" : serverContext.host || "localhost"}:${serverContext.port || 5173}/__mcp__/sse?clientId=temp-browser-launcher`;
23
23
  let client = null;
24
24
  try {
25
25
  client = new Client({
@@ -40,6 +40,8 @@ async function launchBrowserWithDevTools(options) {
40
40
  } catch (error) {
41
41
  console.error(`[dev-inspector] ⚠️ Failed to auto-open browser:`, error instanceof Error ? error.message : String(error));
42
42
  return false;
43
+ } finally {
44
+ await client?.close().catch(() => {});
43
45
  }
44
46
  }
45
47
  var init_browser_launcher = __esmMin((() => {}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcpc-tech/unplugin-dev-inspector-mcp",
3
- "version": "0.0.36",
3
+ "version": "0.0.38",
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",
@@ -186,4 +186,4 @@
186
186
  "publishConfig": {
187
187
  "access": "public"
188
188
  }
189
- }
189
+ }