@mcp-use/inspector 0.6.1 → 0.7.0

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.
Files changed (61) hide show
  1. package/dist/cli.js +295 -19
  2. package/dist/client/assets/__vite-browser-external-CHS79mP1.js +8 -0
  3. package/dist/client/assets/browser-BdCJ_qyB.js +38211 -0
  4. package/dist/client/assets/chunk-VL2OQCWN-CxD8xDNw.js +6475 -0
  5. package/dist/client/assets/display-YIYC6WJE-B6ZSv77R.js +44742 -0
  6. package/dist/client/assets/embeddings-DlCMB9po.js +21 -0
  7. package/dist/client/assets/index-B0NYybvW.js +5371 -0
  8. package/dist/client/assets/index-CKXUnlZB.js +94617 -0
  9. package/dist/client/assets/index-Cb09SlUY.js +17535 -0
  10. package/dist/client/assets/index-CsP5AdwX.js +10699 -0
  11. package/dist/client/assets/index-DX0TIfSM.js +102 -0
  12. package/dist/client/assets/index-Q_pqNaNk.js +1780 -0
  13. package/dist/client/assets/index-kVFYovMy.css +5752 -0
  14. package/dist/client/assets/path-QsnVvLoj.js +62 -0
  15. package/dist/client/assets/transport-wrapper-browser-ChPHVnHg.js +165 -0
  16. package/dist/client/assets/winston-qgF6niUt.js +12326 -0
  17. package/dist/client/index.html +3 -3
  18. package/dist/server/{chunk-37X7HLUV.js → chunk-3T2VCYG6.js} +87 -13
  19. package/dist/server/chunk-CVECQ7BJ.js +78 -0
  20. package/dist/server/{chunk-555LGZ3I.js → chunk-FS77NTZN.js} +133 -10
  21. package/dist/server/chunk-PKBMQBKP.js +7 -0
  22. package/dist/server/{chunk-WYBXXYSP.js → chunk-RRPLH7DL.js} +1 -1
  23. package/dist/server/{chunk-PYGYQT2G.js → chunk-S7NOZBMG.js} +3 -3
  24. package/dist/server/{chunk-DGUMOD7P.js → chunk-ZONLXYBO.js} +92 -10
  25. package/dist/server/cli.js +6 -4
  26. package/dist/server/index.js +7 -5
  27. package/dist/server/middleware.js +7 -5
  28. package/dist/server/rpc-log-bus.d.ts +17 -0
  29. package/dist/server/rpc-log-bus.d.ts.map +1 -0
  30. package/dist/server/rpc-log-bus.js +7 -0
  31. package/dist/server/server.js +6 -4
  32. package/dist/server/shared-routes.d.ts.map +1 -1
  33. package/dist/server/shared-routes.js +4 -2
  34. package/dist/server/shared-static.js +3 -2
  35. package/dist/server/shared-utils-browser.d.ts +2 -1
  36. package/dist/server/shared-utils-browser.d.ts.map +1 -1
  37. package/dist/server/shared-utils-browser.js +2 -1
  38. package/dist/server/shared-utils.d.ts +4 -1
  39. package/dist/server/shared-utils.d.ts.map +1 -1
  40. package/dist/server/shared-utils.js +2 -1
  41. package/dist/server/transport-wrapper.d.ts +6 -0
  42. package/dist/server/transport-wrapper.d.ts.map +1 -0
  43. package/dist/server/transport-wrapper.js +68 -0
  44. package/dist/server/utils.js +1 -0
  45. package/package.json +12 -3
  46. package/dist/client/assets/__vite-browser-external-DFygW7-s.js +0 -1
  47. package/dist/client/assets/chunk-VL2OQCWN-iRVOQjqe.js +0 -8
  48. package/dist/client/assets/display-LIYVTGEU-D2dm8q2H.js +0 -30
  49. package/dist/client/assets/embeddings-Dcyp0Vlp.js +0 -1
  50. package/dist/client/assets/index-6zrNEwtM.js +0 -4
  51. package/dist/client/assets/index-CAnbiFOL.css +0 -1
  52. package/dist/client/assets/index-CB1s6Wr6.js +0 -146
  53. package/dist/client/assets/index-CoMldIFv.js +0 -2
  54. package/dist/client/assets/index-DRz5BQNA.js +0 -1
  55. package/dist/client/assets/index-DUf1336L.js +0 -1559
  56. package/dist/client/assets/index-DmIKR5St.js +0 -1
  57. package/dist/client/assets/index-DpUpZFq2.js +0 -25
  58. package/dist/client/assets/index-DzegZXPW.js +0 -40
  59. package/dist/client/assets/langfuse-C4HKZ3NL-vCtAvQQV.js +0 -564
  60. package/dist/client/assets/path-C9FudP8b.js +0 -1
  61. package/dist/client/assets/winston-BVJ8PyEn.js +0 -37
@@ -27,9 +27,9 @@
27
27
  rel="stylesheet"
28
28
  />
29
29
  <title>Inspector | mcp-use</title>
30
- <script type="module" crossorigin src="/inspector/assets/index-DUf1336L.js"></script>
31
- <link rel="stylesheet" crossorigin href="/inspector/assets/index-CAnbiFOL.css">
32
- <script>window.__INSPECTOR_VERSION__ = "0.6.1";</script>
30
+ <script type="module" crossorigin src="/inspector/assets/index-CKXUnlZB.js"></script>
31
+ <link rel="stylesheet" crossorigin href="/inspector/assets/index-kVFYovMy.css">
32
+ <script>window.__INSPECTOR_VERSION__ = "0.7.0";</script>
33
33
  </head>
34
34
  <body>
35
35
  <script>
@@ -267,7 +267,9 @@ function storeWidgetData(data) {
267
267
  toolOutput,
268
268
  resourceData,
269
269
  toolId,
270
- widgetCSP
270
+ widgetCSP: _widgetCSP,
271
+ devWidgetUrl,
272
+ devServerBaseUrl
271
273
  } = data;
272
274
  console.log("[Widget Store] Received request for toolId:", toolId);
273
275
  console.log("[Widget Store] Fields:", {
@@ -276,7 +278,9 @@ function storeWidgetData(data) {
276
278
  hasResourceData: !!resourceData,
277
279
  hasToolInput: !!toolInput,
278
280
  hasToolOutput: !!toolOutput,
279
- hasWidgetCSP: !!widgetCSP
281
+ hasWidgetCSP: !!_widgetCSP,
282
+ devWidgetUrl,
283
+ devServerBaseUrl
280
284
  });
281
285
  if (!serverId || !uri || !toolId || !resourceData) {
282
286
  const missingFields = [];
@@ -298,7 +302,9 @@ function storeWidgetData(data) {
298
302
  resourceData,
299
303
  toolId,
300
304
  timestamp: Date.now(),
301
- widgetCSP
305
+ widgetCSP: _widgetCSP,
306
+ devWidgetUrl,
307
+ devServerBaseUrl
302
308
  });
303
309
  console.log("[Widget Store] Data stored successfully for toolId:", toolId);
304
310
  return { success: true };
@@ -341,7 +347,17 @@ function generateWidgetContainerHtml(basePath, toolId) {
341
347
  `;
342
348
  }
343
349
  function generateWidgetContentHtml(widgetData) {
344
- const { serverId, uri, toolInput, toolOutput, resourceData, toolId } = widgetData;
350
+ const {
351
+ serverId,
352
+ uri,
353
+ toolInput,
354
+ toolOutput,
355
+ resourceData,
356
+ toolId,
357
+ widgetCSP: _widgetCSP,
358
+ devServerBaseUrl,
359
+ theme
360
+ } = widgetData;
345
361
  console.log("[Widget Content] Using pre-fetched resource for:", {
346
362
  serverId,
347
363
  uri
@@ -372,23 +388,31 @@ function generateWidgetContentHtml(widgetData) {
372
388
  const safeToolOutput = JSON.stringify(toolOutput ?? null).replace(/</g, "\\u003c").replace(/>/g, "\\u003e");
373
389
  const safeToolId = JSON.stringify(toolId);
374
390
  const safeWidgetStateKey = JSON.stringify(widgetStateKey);
391
+ const safeTheme = JSON.stringify(theme === "dark" ? "dark" : "light");
375
392
  const apiScript = `
376
393
  <script>
377
394
  (function() {
378
395
  'use strict';
379
396
 
380
397
  // Change URL to "/" for React Router compatibility
381
- if (window.location.pathname !== '/') {
398
+ // Skip if running in Inspector dev-widget proxy to prevent redirecting iframe to Inspector home
399
+ if (window.location.pathname !== '/' && !window.location.pathname.includes('/dev-widget/')) {
382
400
  history.replaceState(null, '', '/');
383
401
  }
384
402
 
403
+ // Inject MCP widget utilities for Image component and file access
404
+ window.__mcpPublicUrl = ${devServerBaseUrl ? `"${devServerBaseUrl}/mcp-use/public"` : '""'};
405
+ window.__getFile = function(filename) {
406
+ return ${devServerBaseUrl ? `"${devServerBaseUrl}/mcp-use/widgets/"` : '""'} + filename;
407
+ };
408
+
385
409
  const openaiAPI = {
386
410
  toolInput: ${safeToolInput},
387
411
  toolOutput: ${safeToolOutput},
388
412
  toolResponseMetadata: null,
389
413
  displayMode: 'inline',
390
414
  maxHeight: 600,
391
- theme: 'dark',
415
+ theme: ${safeTheme},
392
416
  locale: 'en-US',
393
417
  safeArea: { insets: { top: 0, bottom: 0, left: 0, right: 0 } },
394
418
  userAgent: {},
@@ -483,6 +507,17 @@ function generateWidgetContentHtml(widgetData) {
483
507
  enumerable: true
484
508
  });
485
509
 
510
+ // Listen for widget state requests from inspector
511
+ window.addEventListener('message', (event) => {
512
+ if (event.data?.type === 'mcp-inspector:getWidgetState') {
513
+ window.parent.postMessage({
514
+ type: 'mcp-inspector:widgetStateResponse',
515
+ toolId: event.data.toolId,
516
+ state: openaiAPI.widgetState
517
+ }, '*');
518
+ }
519
+ });
520
+
486
521
  setTimeout(() => {
487
522
  try {
488
523
  const globalsEvent = new CustomEvent('openai:set_globals', {
@@ -536,7 +571,7 @@ function generateWidgetContentHtml(widgetData) {
536
571
  console.log("[Widget Content] Generated HTML length:", modifiedHtml.length);
537
572
  return { html: modifiedHtml };
538
573
  }
539
- function getWidgetSecurityHeaders(widgetCSP) {
574
+ function getWidgetSecurityHeaders(widgetCSP, devServerBaseUrl) {
540
575
  const trustedCdns = [
541
576
  "https://persistent.oaistatic.com",
542
577
  "https://*.oaistatic.com",
@@ -545,25 +580,48 @@ function getWidgetSecurityHeaders(widgetCSP) {
545
580
  "https://cdnjs.cloudflare.com",
546
581
  "https://cdn.skypack.dev"
547
582
  ];
548
- const allResourceDomains = [...trustedCdns];
583
+ const prodResourceDomains = [...trustedCdns];
549
584
  if (widgetCSP?.resource_domains) {
550
- allResourceDomains.push(...widgetCSP.resource_domains);
585
+ prodResourceDomains.push(...widgetCSP.resource_domains);
586
+ }
587
+ const prodResourceDomainsStr = prodResourceDomains.join(" ");
588
+ let devServerOrigin = null;
589
+ const allResourceDomains = [...prodResourceDomains];
590
+ if (devServerBaseUrl) {
591
+ try {
592
+ devServerOrigin = new URL(devServerBaseUrl).origin;
593
+ allResourceDomains.push(devServerOrigin);
594
+ } catch (e) {
595
+ console.warn(`[CSP] Invalid devServerBaseUrl: ${devServerBaseUrl}`);
596
+ }
551
597
  }
552
598
  const resourceDomainsStr = allResourceDomains.join(" ");
599
+ let imgSrc = "'self' data: https: blob:";
600
+ if (devServerOrigin) {
601
+ imgSrc = `'self' data: https: blob: ${devServerOrigin}`;
602
+ }
603
+ let mediaSrc = "'self' data: https: blob:";
604
+ if (devServerOrigin) {
605
+ mediaSrc = `'self' data: https: blob: ${devServerOrigin}`;
606
+ }
607
+ let fontSrc = `'self' data: ${resourceDomainsStr}`;
608
+ if (devServerOrigin) {
609
+ fontSrc = `'self' data: https: http: ${resourceDomainsStr}`;
610
+ }
553
611
  let connectSrc = "'self' https: wss: ws:";
554
612
  if (widgetCSP?.connect_domains && widgetCSP.connect_domains.length > 0) {
555
613
  connectSrc = `'self' ${widgetCSP.connect_domains.join(" ")} https: wss: ws:`;
556
614
  }
557
- return {
615
+ const headers = {
558
616
  "Content-Security-Policy": [
559
617
  "default-src 'self'",
560
618
  `script-src 'self' 'unsafe-inline' 'unsafe-eval' ${resourceDomainsStr}`,
561
619
  "worker-src 'self' blob:",
562
620
  "child-src 'self' blob:",
563
621
  `style-src 'self' 'unsafe-inline' ${resourceDomainsStr}`,
564
- "img-src 'self' data: https: blob:",
565
- "media-src 'self' data: https: blob:",
566
- `font-src 'self' data: ${resourceDomainsStr}`,
622
+ `img-src ${imgSrc}`,
623
+ `media-src ${mediaSrc}`,
624
+ `font-src ${fontSrc}`,
567
625
  `connect-src ${connectSrc}`,
568
626
  "frame-ancestors 'self'"
569
627
  ].join("; "),
@@ -573,6 +631,22 @@ function getWidgetSecurityHeaders(widgetCSP) {
573
631
  Pragma: "no-cache",
574
632
  Expires: "0"
575
633
  };
634
+ if (devServerOrigin) {
635
+ const prodConnectSrc = "'self' https: wss: ws:";
636
+ headers["Content-Security-Policy-Report-Only"] = [
637
+ "default-src 'self'",
638
+ `script-src 'self' 'unsafe-inline' 'unsafe-eval' ${prodResourceDomainsStr}`,
639
+ "worker-src 'self' blob:",
640
+ "child-src 'self' blob:",
641
+ `style-src 'self' 'unsafe-inline' ${prodResourceDomainsStr}`,
642
+ "img-src 'self' data: https: blob:",
643
+ "media-src 'self' data: https: blob:",
644
+ `font-src 'self' data: ${prodResourceDomainsStr}`,
645
+ `connect-src ${prodConnectSrc}`,
646
+ "frame-ancestors 'self'"
647
+ ].join("; ");
648
+ }
649
+ return headers;
576
650
  }
577
651
 
578
652
  export {
@@ -0,0 +1,78 @@
1
+ import {
2
+ __publicField
3
+ } from "./chunk-PKBMQBKP.js";
4
+
5
+ // src/server/rpc-log-bus.ts
6
+ var SimpleEventEmitter = class {
7
+ constructor() {
8
+ __publicField(this, "listeners", /* @__PURE__ */ new Map());
9
+ }
10
+ on(event, listener) {
11
+ if (!this.listeners.has(event)) {
12
+ this.listeners.set(event, /* @__PURE__ */ new Set());
13
+ }
14
+ this.listeners.get(event).add(listener);
15
+ }
16
+ off(event, listener) {
17
+ this.listeners.get(event)?.delete(listener);
18
+ }
19
+ emit(event, ...args) {
20
+ this.listeners.get(event)?.forEach((listener) => {
21
+ try {
22
+ listener(...args);
23
+ } catch (e) {
24
+ console.error("Error in event listener:", e);
25
+ }
26
+ });
27
+ }
28
+ };
29
+ var RpcLogBus = class {
30
+ constructor() {
31
+ __publicField(this, "emitter", new SimpleEventEmitter());
32
+ __publicField(this, "bufferByServer", /* @__PURE__ */ new Map());
33
+ }
34
+ publish(event) {
35
+ const buffer = this.bufferByServer.get(event.serverId) ?? [];
36
+ buffer.push(event);
37
+ if (buffer.length > 1e3) {
38
+ buffer.shift();
39
+ }
40
+ this.bufferByServer.set(event.serverId, buffer);
41
+ this.emitter.emit("event", event);
42
+ }
43
+ subscribe(serverIds, listener) {
44
+ const filter = new Set(serverIds);
45
+ const handler = (event) => {
46
+ if (filter.size === 0 || filter.has(event.serverId)) listener(event);
47
+ };
48
+ this.emitter.on("event", handler);
49
+ return () => this.emitter.off("event", handler);
50
+ }
51
+ getBuffer(serverIds, limit) {
52
+ const filter = new Set(serverIds);
53
+ const all = [];
54
+ for (const [serverId, buf] of this.bufferByServer.entries()) {
55
+ if (filter.size > 0 && !filter.has(serverId)) continue;
56
+ all.push(...buf);
57
+ }
58
+ all.sort((a, b) => b.timestamp.localeCompare(a.timestamp));
59
+ if (limit === 0) return [];
60
+ if (!Number.isFinite(limit) || limit < 0) return all;
61
+ return all.slice(0, limit);
62
+ }
63
+ clear(serverIds) {
64
+ if (serverIds && serverIds.length > 0) {
65
+ const filter = new Set(serverIds);
66
+ for (const serverId of filter) {
67
+ this.bufferByServer.delete(serverId);
68
+ }
69
+ } else {
70
+ this.bufferByServer.clear();
71
+ }
72
+ }
73
+ };
74
+ var rpcLogBus = new RpcLogBus();
75
+
76
+ export {
77
+ rpcLogBus
78
+ };
@@ -1,6 +1,9 @@
1
1
  import {
2
2
  formatErrorResponse
3
3
  } from "./chunk-JCLAFMDT.js";
4
+ import {
5
+ rpcLogBus
6
+ } from "./chunk-CVECQ7BJ.js";
4
7
  import {
5
8
  generateWidgetContainerHtml,
6
9
  generateWidgetContentHtml,
@@ -9,7 +12,7 @@ import {
9
12
  handleChatRequest,
10
13
  handleChatRequestStream,
11
14
  storeWidgetData
12
- } from "./chunk-DGUMOD7P.js";
15
+ } from "./chunk-ZONLXYBO.js";
13
16
 
14
17
  // src/server/shared-routes.ts
15
18
  import { logger } from "hono/logger";
@@ -217,8 +220,10 @@ function registerInspectorRoutes(app, config) {
217
220
  }
218
221
  );
219
222
  html = html.replace(
220
- /(src|href)="\/mcp-use\/widgets\//g,
221
- `$1="${proxyBase}/mcp-use/widgets/`
223
+ /(src|href)="(\/mcp-use\/widgets\/[^"]+)"/g,
224
+ (_match, attr, path) => {
225
+ return `${attr}="${widgetData.devServerBaseUrl}${path}"`;
226
+ }
222
227
  );
223
228
  html = html.replace(/(src|href)="\.\/([^"]+)"/g, (match, attr, path) => {
224
229
  if (path.match(/\.(js|css|png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot)$/i)) {
@@ -226,14 +231,45 @@ function registerInspectorRoutes(app, config) {
226
231
  }
227
232
  return match;
228
233
  });
229
- const host = c.req.header("host") || "localhost:3000";
230
- const protocol = c.req.header("x-forwarded-proto") || (c.req.url.startsWith("https") ? "https" : "http");
231
- const wsProtocol = protocol === "https" ? "wss" : "ws";
232
- html = html.replace(/__vite_ws__:\s*["']([^"']+)["']/g, () => {
233
- const proxyWsUrl = `${wsProtocol}://${host}/inspector/api/dev-widget/${toolId}/__vite_hmr`;
234
- return `__vite_ws__: "${proxyWsUrl}"`;
234
+ if (widgetData.devServerBaseUrl) {
235
+ const devServerUrl = new URL(widgetData.devServerBaseUrl);
236
+ const wsProtocol = devServerUrl.protocol === "https:" ? "wss" : "ws";
237
+ const wsHost = devServerUrl.host;
238
+ const directWsUrl = `${wsProtocol}://${wsHost}/mcp-use/widgets/`;
239
+ const baseTag = `<base href="${widgetData.devServerBaseUrl}/mcp-use/widgets/${widgetName}/">`;
240
+ const cspWarningScript = `
241
+ <script>
242
+ // Listen for CSP violations (from Report-Only policy)
243
+ document.addEventListener('securitypolicyviolation', (e) => {
244
+ // Only warn about report-only violations (not enforced ones)
245
+ if (e.disposition === 'report') {
246
+ console.warn(
247
+ '%c\u26A0\uFE0F CSP Warning: Resource would be blocked in production',
248
+ 'color: orange; font-weight: bold',
249
+ '\\n Blocked URL:', e.blockedURI,
250
+ '\\n Directive:', e.violatedDirective,
251
+ '\\n Policy:', e.originalPolicy,
252
+ '\\n\\n\u2139\uFE0F To fix: Add this domain to your widget\\'s CSP configuration in appsSdkMetadata[\\'openai/widgetCSP\\']'
253
+ );
254
+ }
235
255
  });
236
- const headers = getWidgetSecurityHeaders(widgetData.widgetCSP);
256
+ </script>`;
257
+ const viteConfigScript = `
258
+ <script>
259
+ // Configure Vite HMR to connect directly to dev server
260
+ window.__vite_ws_url__ = "${directWsUrl}";
261
+ </script>`;
262
+ html = html.replace(/<head>/i, `<head>
263
+ ${baseTag}`);
264
+ html = html.replace(
265
+ /<script/,
266
+ cspWarningScript + viteConfigScript + "\n <script"
267
+ );
268
+ }
269
+ const headers = getWidgetSecurityHeaders(
270
+ widgetData.widgetCSP,
271
+ widgetData.devServerBaseUrl
272
+ );
237
273
  Object.entries(headers).forEach(([key, value]) => {
238
274
  c.header(key, value);
239
275
  });
@@ -340,6 +376,93 @@ function registerInspectorRoutes(app, config) {
340
376
  return c.json({ success: false });
341
377
  }
342
378
  });
379
+ app.post("/inspector/api/rpc/log", async (c) => {
380
+ try {
381
+ const event = await c.req.json();
382
+ rpcLogBus.publish(event);
383
+ return c.json({ success: true });
384
+ } catch (error) {
385
+ console.error("[RPC Log] Error receiving RPC event:", error);
386
+ return c.json({ success: false });
387
+ }
388
+ });
389
+ app.delete("/inspector/api/rpc/log", async (c) => {
390
+ try {
391
+ const url = new URL(c.req.url);
392
+ const serverIdsParam = url.searchParams.get("serverIds");
393
+ const serverIds = serverIdsParam ? serverIdsParam.split(",").filter(Boolean) : void 0;
394
+ rpcLogBus.clear(serverIds);
395
+ return c.json({ success: true });
396
+ } catch (error) {
397
+ console.error("[RPC Log] Error clearing RPC log:", error);
398
+ return c.json({ success: false });
399
+ }
400
+ });
401
+ app.get("/inspector/api/rpc/stream", async (c) => {
402
+ const url = new URL(c.req.url);
403
+ const replay = parseInt(url.searchParams.get("replay") || "3", 10);
404
+ const serverIdsParam = url.searchParams.get("serverIds");
405
+ const serverIds = serverIdsParam ? serverIdsParam.split(",").filter(Boolean) : [];
406
+ const encoder = new TextEncoder();
407
+ const stream = new ReadableStream({
408
+ start(controller) {
409
+ const send = (data) => {
410
+ try {
411
+ controller.enqueue(
412
+ encoder.encode(`data: ${JSON.stringify(data)}
413
+
414
+ `)
415
+ );
416
+ } catch {
417
+ }
418
+ };
419
+ try {
420
+ const recent = rpcLogBus.getBuffer(
421
+ serverIds,
422
+ isNaN(replay) ? 3 : replay
423
+ );
424
+ for (const evt of recent) {
425
+ send({ type: "rpc", ...evt });
426
+ }
427
+ } catch {
428
+ }
429
+ const unsubscribe = rpcLogBus.subscribe(
430
+ serverIds,
431
+ (evt) => {
432
+ send({ type: "rpc", ...evt });
433
+ }
434
+ );
435
+ const keepalive = setInterval(() => {
436
+ try {
437
+ controller.enqueue(encoder.encode(`: keepalive ${Date.now()}
438
+
439
+ `));
440
+ } catch {
441
+ }
442
+ }, 15e3);
443
+ c.req.raw.signal?.addEventListener("abort", () => {
444
+ try {
445
+ clearInterval(keepalive);
446
+ unsubscribe();
447
+ } catch {
448
+ }
449
+ try {
450
+ controller.close();
451
+ } catch {
452
+ }
453
+ });
454
+ }
455
+ });
456
+ return new Response(stream, {
457
+ headers: {
458
+ "Content-Type": "text/event-stream",
459
+ "Cache-Control": "no-cache",
460
+ Connection: "keep-alive",
461
+ "Access-Control-Allow-Origin": "*",
462
+ "Access-Control-Expose-Headers": "*"
463
+ }
464
+ });
465
+ });
343
466
  }
344
467
 
345
468
  export {
@@ -0,0 +1,7 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+
5
+ export {
6
+ __publicField
7
+ };
@@ -2,7 +2,7 @@ import {
2
2
  checkClientFiles,
3
3
  getClientDistPath,
4
4
  getContentType
5
- } from "./chunk-37X7HLUV.js";
5
+ } from "./chunk-3T2VCYG6.js";
6
6
 
7
7
  // src/server/shared-static.ts
8
8
  import { existsSync, readFileSync } from "fs";
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  registerInspectorRoutes
3
- } from "./chunk-555LGZ3I.js";
3
+ } from "./chunk-FS77NTZN.js";
4
4
  import {
5
5
  registerStaticRoutes
6
- } from "./chunk-WYBXXYSP.js";
6
+ } from "./chunk-RRPLH7DL.js";
7
7
  import {
8
8
  checkClientFiles,
9
9
  getClientDistPath
10
- } from "./chunk-37X7HLUV.js";
10
+ } from "./chunk-3T2VCYG6.js";
11
11
 
12
12
  // src/server/middleware.ts
13
13
  import { Hono } from "hono";
@@ -312,7 +312,16 @@ function generateWidgetContainerHtml(basePath, toolId) {
312
312
  `;
313
313
  }
314
314
  function generateWidgetContentHtml(widgetData) {
315
- const { serverId, uri, toolInput, toolOutput, resourceData, toolId } = widgetData;
315
+ const {
316
+ serverId,
317
+ uri,
318
+ toolInput,
319
+ toolOutput,
320
+ resourceData,
321
+ toolId,
322
+ devServerBaseUrl,
323
+ theme
324
+ } = widgetData;
316
325
  console.log("[Widget Content] Using pre-fetched resource for:", {
317
326
  serverId,
318
327
  uri
@@ -343,23 +352,31 @@ function generateWidgetContentHtml(widgetData) {
343
352
  const safeToolOutput = JSON.stringify(toolOutput ?? null).replace(/</g, "\\u003c").replace(/>/g, "\\u003e");
344
353
  const safeToolId = JSON.stringify(toolId);
345
354
  const safeWidgetStateKey = JSON.stringify(widgetStateKey);
355
+ const safeTheme = JSON.stringify(theme === "dark" ? "dark" : "light");
346
356
  const apiScript = `
347
357
  <script>
348
358
  (function() {
349
359
  'use strict';
350
360
 
351
361
  // Change URL to "/" for React Router compatibility
352
- if (window.location.pathname !== '/') {
362
+ // Skip if running in Inspector dev-widget proxy to prevent redirecting iframe to Inspector home
363
+ if (window.location.pathname !== '/' && !window.location.pathname.includes('/dev-widget/')) {
353
364
  history.replaceState(null, '', '/');
354
365
  }
355
366
 
367
+ // Inject MCP widget utilities for Image component and file access
368
+ window.__mcpPublicUrl = ${devServerBaseUrl ? `"${devServerBaseUrl}/mcp-use/public"` : '""'};
369
+ window.__getFile = function(filename) {
370
+ return ${devServerBaseUrl ? `"${devServerBaseUrl}/mcp-use/widgets/"` : '""'} + filename;
371
+ };
372
+
356
373
  const openaiAPI = {
357
374
  toolInput: ${safeToolInput},
358
375
  toolOutput: ${safeToolOutput},
359
376
  toolResponseMetadata: null,
360
377
  displayMode: 'inline',
361
378
  maxHeight: 600,
362
- theme: 'dark',
379
+ theme: ${safeTheme},
363
380
  locale: 'en-US',
364
381
  safeArea: { insets: { top: 0, bottom: 0, left: 0, right: 0 } },
365
382
  userAgent: {},
@@ -432,6 +449,20 @@ function generateWidgetContentHtml(widgetData) {
432
449
  return this.sendFollowupTurn(prompt);
433
450
  },
434
451
 
452
+ async notifyIntrinsicHeight(height) {
453
+ console.log('[OpenAI Widget] notifyIntrinsicHeight called with:', height);
454
+ if (typeof height !== 'number' || height < 0) {
455
+ console.error('[OpenAI Widget] Invalid height value:', height);
456
+ throw new Error('Height must be a non-negative number');
457
+ }
458
+ const message = {
459
+ type: 'openai:notifyIntrinsicHeight',
460
+ height
461
+ };
462
+ console.log('[OpenAI Widget] Sending postMessage to parent:', message);
463
+ window.parent.postMessage(message, '*');
464
+ },
465
+
435
466
  openExternal(payload) {
436
467
  const href = typeof payload === 'string' ? payload : payload?.href;
437
468
  if (href) {
@@ -476,6 +507,18 @@ function generateWidgetContentHtml(widgetData) {
476
507
  } catch (err) {}
477
508
  }, 0);
478
509
 
510
+ // Listen for widget state requests from inspector
511
+ window.addEventListener('message', (event) => {
512
+ if (event.data?.type === 'mcp-inspector:getWidgetState') {
513
+ window.parent.postMessage({
514
+ type: 'mcp-inspector:widgetStateResponse',
515
+ toolId: event.data.toolId,
516
+ state: openaiAPI.widgetState
517
+ }, '*');
518
+ return;
519
+ }
520
+ });
521
+
479
522
  // Listen for globals changes from parent (for displayMode, theme, etc.)
480
523
  window.addEventListener('message', (event) => {
481
524
  // Handle new general globalsChanged message
@@ -602,7 +645,7 @@ function generateWidgetContentHtml(widgetData) {
602
645
  console.log("[Widget Content] Generated HTML length:", modifiedHtml.length);
603
646
  return { html: modifiedHtml };
604
647
  }
605
- function getWidgetSecurityHeaders(widgetCSP) {
648
+ function getWidgetSecurityHeaders(widgetCSP, devServerBaseUrl) {
606
649
  const trustedCdns = [
607
650
  "https://persistent.oaistatic.com",
608
651
  "https://*.oaistatic.com",
@@ -611,25 +654,48 @@ function getWidgetSecurityHeaders(widgetCSP) {
611
654
  "https://cdnjs.cloudflare.com",
612
655
  "https://cdn.skypack.dev"
613
656
  ];
614
- const allResourceDomains = [...trustedCdns];
657
+ const prodResourceDomains = [...trustedCdns];
615
658
  if (widgetCSP?.resource_domains) {
616
- allResourceDomains.push(...widgetCSP.resource_domains);
659
+ prodResourceDomains.push(...widgetCSP.resource_domains);
660
+ }
661
+ const prodResourceDomainsStr = prodResourceDomains.join(" ");
662
+ let devServerOrigin = null;
663
+ const allResourceDomains = [...prodResourceDomains];
664
+ if (devServerBaseUrl) {
665
+ try {
666
+ devServerOrigin = new URL(devServerBaseUrl).origin;
667
+ allResourceDomains.push(devServerOrigin);
668
+ } catch (e) {
669
+ console.warn(`[CSP] Invalid devServerBaseUrl: ${devServerBaseUrl}`);
670
+ }
617
671
  }
618
672
  const resourceDomainsStr = allResourceDomains.join(" ");
673
+ let imgSrc = "'self' data: https: blob:";
674
+ if (devServerOrigin) {
675
+ imgSrc = `'self' data: https: blob: ${devServerOrigin}`;
676
+ }
677
+ let mediaSrc = "'self' data: https: blob:";
678
+ if (devServerOrigin) {
679
+ mediaSrc = `'self' data: https: blob: ${devServerOrigin}`;
680
+ }
681
+ let fontSrc = `'self' data: ${resourceDomainsStr}`;
682
+ if (devServerOrigin) {
683
+ fontSrc = `'self' data: https: http: ${resourceDomainsStr}`;
684
+ }
619
685
  let connectSrc = "'self' https: wss: ws:";
620
686
  if (widgetCSP?.connect_domains && widgetCSP.connect_domains.length > 0) {
621
687
  connectSrc = `'self' ${widgetCSP.connect_domains.join(" ")} https: wss: ws:`;
622
688
  }
623
- return {
689
+ const headers = {
624
690
  "Content-Security-Policy": [
625
691
  "default-src 'self'",
626
692
  `script-src 'self' 'unsafe-inline' 'unsafe-eval' ${resourceDomainsStr}`,
627
693
  "worker-src 'self' blob:",
628
694
  "child-src 'self' blob:",
629
695
  `style-src 'self' 'unsafe-inline' ${resourceDomainsStr}`,
630
- "img-src 'self' data: https: blob:",
631
- "media-src 'self' data: https: blob:",
632
- `font-src 'self' data: ${resourceDomainsStr}`,
696
+ `img-src ${imgSrc}`,
697
+ `media-src ${mediaSrc}`,
698
+ `font-src ${fontSrc}`,
633
699
  `connect-src ${connectSrc}`,
634
700
  "frame-ancestors 'self'"
635
701
  ].join("; "),
@@ -639,6 +705,22 @@ function getWidgetSecurityHeaders(widgetCSP) {
639
705
  Pragma: "no-cache",
640
706
  Expires: "0"
641
707
  };
708
+ if (devServerOrigin) {
709
+ const prodConnectSrc = "'self' https: wss: ws:";
710
+ headers["Content-Security-Policy-Report-Only"] = [
711
+ "default-src 'self'",
712
+ `script-src 'self' 'unsafe-inline' 'unsafe-eval' ${prodResourceDomainsStr}`,
713
+ "worker-src 'self' blob:",
714
+ "child-src 'self' blob:",
715
+ `style-src 'self' 'unsafe-inline' ${prodResourceDomainsStr}`,
716
+ "img-src 'self' data: https: blob:",
717
+ "media-src 'self' data: https: blob:",
718
+ `font-src 'self' data: ${prodResourceDomainsStr}`,
719
+ `connect-src ${prodConnectSrc}`,
720
+ "frame-ancestors 'self'"
721
+ ].join("; ");
722
+ }
723
+ return headers;
642
724
  }
643
725
 
644
726
  export {