@mcpc-tech/unplugin-dev-inspector-mcp 0.0.39 → 0.0.40

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 CHANGED
@@ -150,7 +150,23 @@ DevInspector.vite({
150
150
  import 'virtual:dev-inspector-mcp'; // ← Add this import
151
151
  ```
152
152
 
153
- **✅ Zero Production Impact:** This import is automatically removed in production builds via tree-shaking. The entire dev-inspector code is wrapped in `if (import.meta.env.DEV)` guards, which bundlers statically replace with `false` during production builds.
153
+ ##### TypeScript Types (Required for `virtual:dev-inspector-mcp`)
154
+
155
+ If you use TypeScript and import `virtual:dev-inspector-mcp`, make sure your TS config includes the plugin client types:
156
+
157
+ ```jsonc
158
+ // tsconfig.json / tsconfig.app.json
159
+ {
160
+ "compilerOptions": {
161
+ "types": [
162
+ "vite/client",
163
+ "@mcpc-tech/unplugin-dev-inspector-mcp/client"
164
+ ]
165
+ }
166
+ }
167
+ ```
168
+
169
+ **✅ Zero Production Impact:** In production builds, `virtual:dev-inspector-mcp` becomes a no-op module. The inspector runtime is guarded by `if (import.meta.env.DEV)`, which bundlers statically replace with `false` during production builds.
154
170
 
155
171
  ##### Custom Virtual Module Name
156
172
 
@@ -86926,14 +86926,20 @@ var ConnectionManager = class {
86926
86926
  //#endregion
86927
86927
  //#region src/utils/cors.ts
86928
86928
  /**
86929
- * Set CORS headers and handle preflight requests
86930
- * Returns true if request was handled (preflight), false otherwise
86929
+ * Set CORS headers and handle preflight requests.
86930
+ *
86931
+ * Uses the browser's requested headers (Access-Control-Request-Headers) when present
86932
+ * to avoid mismatches that can break CORS preflight (e.g. 'user-agent').
86933
+ *
86934
+ * Returns true if request was handled (preflight), false otherwise.
86931
86935
  */
86932
- function handleCors(res, method) {
86936
+ function handleCors(req, res) {
86933
86937
  res.setHeader("Access-Control-Allow-Origin", "*");
86934
86938
  res.setHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, OPTIONS");
86935
- res.setHeader("Access-Control-Allow-Headers", "Content-Type, mcp-session-id, mcp-protocol-version");
86936
- if (method === "OPTIONS") {
86939
+ const requested = req.headers["access-control-request-headers"];
86940
+ const requestedValue = Array.isArray(requested) ? requested.join(", ") : requested;
86941
+ res.setHeader("Access-Control-Allow-Headers", requestedValue ?? "Content-Type, mcp-session-id, mcp-protocol-version");
86942
+ if (req.method === "OPTIONS") {
86937
86943
  res.statusCode = 204;
86938
86944
  res.end();
86939
86945
  return true;
@@ -86959,7 +86965,7 @@ async function setupMcpMiddleware(middlewares, serverContext) {
86959
86965
  middlewares.use(async (req, res, next$1) => {
86960
86966
  const url$1 = req.url || "";
86961
86967
  if (url$1.startsWith("/__mcp__")) {
86962
- if (handleCors(res, req.method)) return;
86968
+ if (handleCors(req, res)) return;
86963
86969
  }
86964
86970
  if (url$1.startsWith("/__mcp__") && !url$1.startsWith("/__mcp__/sse") && !url$1.startsWith("/__mcp__/messages")) {
86965
86971
  if (req.method === "POST") await handleStreamableHttpPost(req, res, serverContext, connectionManager);
@@ -87196,7 +87202,7 @@ function setupInspectorMiddleware(middlewares, config) {
87196
87202
  let filesChecked = false;
87197
87203
  middlewares.use((req, res, next$1) => {
87198
87204
  if (req.url?.startsWith("/__inspector__")) {
87199
- if (handleCors(res, req.method)) return;
87205
+ if (handleCors(req, res)) return;
87200
87206
  }
87201
87207
  if (!filesChecked) {
87202
87208
  cachedScript = getInspectorScript();
@@ -88464,7 +88470,7 @@ function setupAcpMiddleware(middlewares, serverContext, acpOptions) {
88464
88470
  * Returns: { sessionId }
88465
88471
  */
88466
88472
  middlewares.use("/api/acp/init-session", async (req, res) => {
88467
- if (handleCors(res, req.method)) return;
88473
+ if (handleCors(req, res)) return;
88468
88474
  if (req.method !== "POST") {
88469
88475
  res.statusCode = 405;
88470
88476
  res.end("Method Not Allowed");
@@ -88591,7 +88597,7 @@ function setupAcpMiddleware(middlewares, serverContext, acpOptions) {
88591
88597
  * Body: { sessionId }
88592
88598
  */
88593
88599
  middlewares.use("/api/acp/cleanup-session", async (req, res) => {
88594
- if (handleCors(res, req.method)) return;
88600
+ if (handleCors(req, res)) return;
88595
88601
  if (req.method !== "POST") {
88596
88602
  res.statusCode = 405;
88597
88603
  res.end("Method Not Allowed");
@@ -88634,7 +88640,7 @@ function setupAcpMiddleware(middlewares, serverContext, acpOptions) {
88634
88640
  * Body: { messages, agent, envVars, sessionId? }
88635
88641
  */
88636
88642
  middlewares.use("/api/acp/chat", async (req, res) => {
88637
- if (handleCors(res, req.method)) return;
88643
+ if (handleCors(req, res)) return;
88638
88644
  if (req.method !== "POST") {
88639
88645
  res.statusCode = 405;
88640
88646
  res.end("Method Not Allowed");
@@ -86961,14 +86961,20 @@ var ConnectionManager = class {
86961
86961
  //#endregion
86962
86962
  //#region src/utils/cors.ts
86963
86963
  /**
86964
- * Set CORS headers and handle preflight requests
86965
- * Returns true if request was handled (preflight), false otherwise
86964
+ * Set CORS headers and handle preflight requests.
86965
+ *
86966
+ * Uses the browser's requested headers (Access-Control-Request-Headers) when present
86967
+ * to avoid mismatches that can break CORS preflight (e.g. 'user-agent').
86968
+ *
86969
+ * Returns true if request was handled (preflight), false otherwise.
86966
86970
  */
86967
- function handleCors(res, method) {
86971
+ function handleCors(req, res) {
86968
86972
  res.setHeader("Access-Control-Allow-Origin", "*");
86969
86973
  res.setHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, OPTIONS");
86970
- res.setHeader("Access-Control-Allow-Headers", "Content-Type, mcp-session-id, mcp-protocol-version");
86971
- if (method === "OPTIONS") {
86974
+ const requested = req.headers["access-control-request-headers"];
86975
+ const requestedValue = Array.isArray(requested) ? requested.join(", ") : requested;
86976
+ res.setHeader("Access-Control-Allow-Headers", requestedValue ?? "Content-Type, mcp-session-id, mcp-protocol-version");
86977
+ if (req.method === "OPTIONS") {
86972
86978
  res.statusCode = 204;
86973
86979
  res.end();
86974
86980
  return true;
@@ -86994,7 +87000,7 @@ async function setupMcpMiddleware(middlewares, serverContext) {
86994
87000
  middlewares.use(async (req, res, next$1) => {
86995
87001
  const url = req.url || "";
86996
87002
  if (url.startsWith("/__mcp__")) {
86997
- if (handleCors(res, req.method)) return;
87003
+ if (handleCors(req, res)) return;
86998
87004
  }
86999
87005
  if (url.startsWith("/__mcp__") && !url.startsWith("/__mcp__/sse") && !url.startsWith("/__mcp__/messages")) {
87000
87006
  if (req.method === "POST") await handleStreamableHttpPost(req, res, serverContext, connectionManager);
@@ -87231,7 +87237,7 @@ function setupInspectorMiddleware(middlewares, config) {
87231
87237
  let filesChecked = false;
87232
87238
  middlewares.use((req, res, next$1) => {
87233
87239
  if (req.url?.startsWith("/__inspector__")) {
87234
- if (handleCors(res, req.method)) return;
87240
+ if (handleCors(req, res)) return;
87235
87241
  }
87236
87242
  if (!filesChecked) {
87237
87243
  cachedScript = getInspectorScript();
@@ -88499,7 +88505,7 @@ function setupAcpMiddleware(middlewares, serverContext, acpOptions) {
88499
88505
  * Returns: { sessionId }
88500
88506
  */
88501
88507
  middlewares.use("/api/acp/init-session", async (req, res) => {
88502
- if (handleCors(res, req.method)) return;
88508
+ if (handleCors(req, res)) return;
88503
88509
  if (req.method !== "POST") {
88504
88510
  res.statusCode = 405;
88505
88511
  res.end("Method Not Allowed");
@@ -88626,7 +88632,7 @@ function setupAcpMiddleware(middlewares, serverContext, acpOptions) {
88626
88632
  * Body: { sessionId }
88627
88633
  */
88628
88634
  middlewares.use("/api/acp/cleanup-session", async (req, res) => {
88629
- if (handleCors(res, req.method)) return;
88635
+ if (handleCors(req, res)) return;
88630
88636
  if (req.method !== "POST") {
88631
88637
  res.statusCode = 405;
88632
88638
  res.end("Method Not Allowed");
@@ -88669,7 +88675,7 @@ function setupAcpMiddleware(middlewares, serverContext, acpOptions) {
88669
88675
  * Body: { messages, agent, envVars, sessionId? }
88670
88676
  */
88671
88677
  middlewares.use("/api/acp/chat", async (req, res) => {
88672
- if (handleCors(res, req.method)) return;
88678
+ if (handleCors(req, res)) return;
88673
88679
  if (req.method !== "POST") {
88674
88680
  res.statusCode = 405;
88675
88681
  res.end("Method Not Allowed");
package/dist/index.cjs CHANGED
@@ -59,9 +59,23 @@ const createDevInspectorPlugin = (name, transformFactory) => {
59
59
  const enabled = options.enabled ?? process.env.NODE_ENV !== "production";
60
60
  const virtualModuleName = options.virtualModuleName ?? "virtual:dev-inspector-mcp";
61
61
  const webpackModuleName = virtualModuleName.replace("virtual:", "");
62
+ let viteCommand;
62
63
  let resolvedHost = options.host || "localhost";
63
64
  let resolvedPort = options.port || 5173;
64
- if (!enabled) return { name };
65
+ const transformImpl = transformFactory(options);
66
+ const transform = (code, id) => {
67
+ if (!enabled) return null;
68
+ if (viteCommand && viteCommand !== "serve") return null;
69
+ return transformImpl(code, id);
70
+ };
71
+ const createNoopVirtualModule = () => {
72
+ return `
73
+ // Production build - no-op
74
+ export function registerInspectorTool(_tool) {
75
+ // No-op in production
76
+ }
77
+ `;
78
+ };
65
79
  return {
66
80
  name,
67
81
  enforce: "pre",
@@ -69,7 +83,9 @@ const createDevInspectorPlugin = (name, transformFactory) => {
69
83
  if (id === virtualModuleName || id === webpackModuleName) return "\0" + virtualModuleName;
70
84
  },
71
85
  load(id) {
72
- if (id === "\0" + virtualModuleName) return `
86
+ if (id === "\0" + virtualModuleName) {
87
+ if (!enabled || viteCommand === "build") return createNoopVirtualModule();
88
+ return `
73
89
  // Development-only code - removed in production builds
74
90
 
75
91
  // Global tools registry
@@ -83,9 +99,13 @@ if (typeof window !== 'undefined') {
83
99
 
84
100
  /**
85
101
  * Register a custom tool for the inspector
102
+ * Only registers in development mode
86
103
  */
87
104
  export function registerInspectorTool(tool) {
105
+ // Skip in production (when bundler replaces import.meta.env.DEV with false)
106
+ if (!import.meta.env.DEV) return;
88
107
  if (typeof window === 'undefined') return;
108
+
89
109
  window.__INSPECTOR_TOOLS__ = window.__INSPECTOR_TOOLS__ || [];
90
110
  window.__INSPECTOR_TOOLS__.push(tool);
91
111
  }
@@ -122,10 +142,14 @@ if (typeof window !== 'undefined' && typeof document !== 'undefined') {
122
142
  }
123
143
  }
124
144
  `;
145
+ }
125
146
  },
126
- transform: transformFactory(options),
147
+ transform,
127
148
  vite: {
128
- apply: "serve",
149
+ apply(_config, env) {
150
+ viteCommand = env.command;
151
+ return true;
152
+ },
129
153
  configResolved(config) {
130
154
  const viteHost = config.server.host;
131
155
  resolvedHost = options.host ?? (typeof viteHost === "string" ? viteHost : viteHost === true ? "0.0.0.0" : "localhost");
@@ -135,6 +159,8 @@ if (typeof window !== 'undefined' && typeof document !== 'undefined') {
135
159
  transformIndexHtml: {
136
160
  order: "pre",
137
161
  handler(html, ctx) {
162
+ if (!enabled) return html;
163
+ if (viteCommand !== "serve") return html;
138
164
  if (!(options.autoInject ?? true)) return html;
139
165
  const server = ctx.server;
140
166
  const viteHost = server?.config.server.host;
@@ -169,6 +195,7 @@ if (typeof window !== 'undefined' && typeof document !== 'undefined') {
169
195
  }
170
196
  },
171
197
  async configureServer(server) {
198
+ if (!enabled) return;
172
199
  const viteHost = server.config.server.host;
173
200
  const serverContext = {
174
201
  host: options.host ?? (typeof viteHost === "string" ? viteHost : viteHost === true ? "0.0.0.0" : "localhost"),
@@ -279,7 +306,7 @@ if (typeof window !== 'undefined' && typeof document !== 'undefined') {
279
306
  });
280
307
  },
281
308
  rollup: {},
282
- esbuild: { setup(build) {} }
309
+ esbuild: { setup(_build) {} }
283
310
  };
284
311
  });
285
312
  };
package/dist/index.js CHANGED
@@ -55,9 +55,23 @@ const createDevInspectorPlugin = (name, transformFactory) => {
55
55
  const enabled = options.enabled ?? process.env.NODE_ENV !== "production";
56
56
  const virtualModuleName = options.virtualModuleName ?? "virtual:dev-inspector-mcp";
57
57
  const webpackModuleName = virtualModuleName.replace("virtual:", "");
58
+ let viteCommand;
58
59
  let resolvedHost = options.host || "localhost";
59
60
  let resolvedPort = options.port || 5173;
60
- if (!enabled) return { name };
61
+ const transformImpl = transformFactory(options);
62
+ const transform = (code, id) => {
63
+ if (!enabled) return null;
64
+ if (viteCommand && viteCommand !== "serve") return null;
65
+ return transformImpl(code, id);
66
+ };
67
+ const createNoopVirtualModule = () => {
68
+ return `
69
+ // Production build - no-op
70
+ export function registerInspectorTool(_tool) {
71
+ // No-op in production
72
+ }
73
+ `;
74
+ };
61
75
  return {
62
76
  name,
63
77
  enforce: "pre",
@@ -65,7 +79,9 @@ const createDevInspectorPlugin = (name, transformFactory) => {
65
79
  if (id === virtualModuleName || id === webpackModuleName) return "\0" + virtualModuleName;
66
80
  },
67
81
  load(id) {
68
- if (id === "\0" + virtualModuleName) return `
82
+ if (id === "\0" + virtualModuleName) {
83
+ if (!enabled || viteCommand === "build") return createNoopVirtualModule();
84
+ return `
69
85
  // Development-only code - removed in production builds
70
86
 
71
87
  // Global tools registry
@@ -79,9 +95,13 @@ if (typeof window !== 'undefined') {
79
95
 
80
96
  /**
81
97
  * Register a custom tool for the inspector
98
+ * Only registers in development mode
82
99
  */
83
100
  export function registerInspectorTool(tool) {
101
+ // Skip in production (when bundler replaces import.meta.env.DEV with false)
102
+ if (!import.meta.env.DEV) return;
84
103
  if (typeof window === 'undefined') return;
104
+
85
105
  window.__INSPECTOR_TOOLS__ = window.__INSPECTOR_TOOLS__ || [];
86
106
  window.__INSPECTOR_TOOLS__.push(tool);
87
107
  }
@@ -118,10 +138,14 @@ if (typeof window !== 'undefined' && typeof document !== 'undefined') {
118
138
  }
119
139
  }
120
140
  `;
141
+ }
121
142
  },
122
- transform: transformFactory(options),
143
+ transform,
123
144
  vite: {
124
- apply: "serve",
145
+ apply(_config, env) {
146
+ viteCommand = env.command;
147
+ return true;
148
+ },
125
149
  configResolved(config) {
126
150
  const viteHost = config.server.host;
127
151
  resolvedHost = options.host ?? (typeof viteHost === "string" ? viteHost : viteHost === true ? "0.0.0.0" : "localhost");
@@ -131,6 +155,8 @@ if (typeof window !== 'undefined' && typeof document !== 'undefined') {
131
155
  transformIndexHtml: {
132
156
  order: "pre",
133
157
  handler(html, ctx) {
158
+ if (!enabled) return html;
159
+ if (viteCommand !== "serve") return html;
134
160
  if (!(options.autoInject ?? true)) return html;
135
161
  const server = ctx.server;
136
162
  const viteHost = server?.config.server.host;
@@ -165,6 +191,7 @@ if (typeof window !== 'undefined' && typeof document !== 'undefined') {
165
191
  }
166
192
  },
167
193
  async configureServer(server) {
194
+ if (!enabled) return;
168
195
  const viteHost = server.config.server.host;
169
196
  const serverContext = {
170
197
  host: options.host ?? (typeof viteHost === "string" ? viteHost : viteHost === true ? "0.0.0.0" : "localhost"),
@@ -275,7 +302,7 @@ if (typeof window !== 'undefined' && typeof document !== 'undefined') {
275
302
  });
276
303
  },
277
304
  rollup: {},
278
- esbuild: { setup(build) {} }
305
+ esbuild: { setup(_build) {} }
279
306
  };
280
307
  });
281
308
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcpc-tech/unplugin-dev-inspector-mcp",
3
- "version": "0.0.39",
3
+ "version": "0.0.40",
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",