skybridge 0.0.0-dev.f27d9e2 → 0.0.0-dev.f2c8fae

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 (150) hide show
  1. package/README.md +153 -0
  2. package/dist/cli/detect-port.d.ts +18 -0
  3. package/dist/cli/detect-port.js +61 -0
  4. package/dist/cli/detect-port.js.map +1 -0
  5. package/dist/cli/telemetry.d.ts +7 -0
  6. package/dist/cli/telemetry.js +123 -0
  7. package/dist/cli/telemetry.js.map +1 -0
  8. package/dist/cli/types.d.ts +5 -0
  9. package/dist/cli/types.js +2 -0
  10. package/dist/cli/types.js.map +1 -0
  11. package/dist/cli/use-execute-steps.d.ts +3 -2
  12. package/dist/cli/use-execute-steps.js +6 -1
  13. package/dist/cli/use-execute-steps.js.map +1 -1
  14. package/dist/cli/use-nodemon.d.ts +2 -0
  15. package/dist/cli/use-nodemon.js +80 -0
  16. package/dist/cli/use-nodemon.js.map +1 -0
  17. package/dist/cli/use-tunnel.d.ts +8 -0
  18. package/dist/cli/use-tunnel.js +101 -0
  19. package/dist/cli/use-tunnel.js.map +1 -0
  20. package/dist/cli/use-typescript-check.d.ts +8 -0
  21. package/dist/cli/use-typescript-check.js +59 -0
  22. package/dist/cli/use-typescript-check.js.map +1 -0
  23. package/dist/commands/build.js +4 -2
  24. package/dist/commands/build.js.map +1 -1
  25. package/dist/commands/dev.d.ts +2 -1
  26. package/dist/commands/dev.js +25 -13
  27. package/dist/commands/dev.js.map +1 -1
  28. package/dist/commands/start.d.ts +3 -1
  29. package/dist/commands/start.js +34 -15
  30. package/dist/commands/start.js.map +1 -1
  31. package/dist/commands/telemetry/disable.d.ts +5 -0
  32. package/dist/commands/telemetry/disable.js +14 -0
  33. package/dist/commands/telemetry/disable.js.map +1 -0
  34. package/dist/commands/telemetry/enable.d.ts +5 -0
  35. package/dist/commands/telemetry/enable.js +14 -0
  36. package/dist/commands/telemetry/enable.js.map +1 -0
  37. package/dist/commands/telemetry/status.d.ts +5 -0
  38. package/dist/commands/telemetry/status.js +14 -0
  39. package/dist/commands/telemetry/status.js.map +1 -0
  40. package/dist/server/asset-base-url-transform-plugin.d.ts +10 -0
  41. package/dist/server/asset-base-url-transform-plugin.js +33 -0
  42. package/dist/server/asset-base-url-transform-plugin.js.map +1 -0
  43. package/dist/server/asset-base-url-transform-plugin.test.d.ts +1 -0
  44. package/dist/server/asset-base-url-transform-plugin.test.js +55 -0
  45. package/dist/server/asset-base-url-transform-plugin.test.js.map +1 -0
  46. package/dist/server/express.d.ts +15 -0
  47. package/dist/server/express.js +77 -0
  48. package/dist/server/express.js.map +1 -0
  49. package/dist/server/express.test.d.ts +1 -0
  50. package/dist/server/express.test.js +252 -0
  51. package/dist/server/express.test.js.map +1 -0
  52. package/dist/server/index.d.ts +1 -0
  53. package/dist/server/index.js.map +1 -1
  54. package/dist/server/middleware.d.ts +124 -0
  55. package/dist/server/middleware.js +93 -0
  56. package/dist/server/middleware.js.map +1 -0
  57. package/dist/server/middleware.test-d.d.ts +1 -0
  58. package/dist/server/middleware.test-d.js +75 -0
  59. package/dist/server/middleware.test-d.js.map +1 -0
  60. package/dist/server/middleware.test.d.ts +1 -0
  61. package/dist/server/middleware.test.js +490 -0
  62. package/dist/server/middleware.test.js.map +1 -0
  63. package/dist/server/monitoring.d.ts +15 -0
  64. package/dist/server/monitoring.js +66 -0
  65. package/dist/server/monitoring.js.map +1 -0
  66. package/dist/server/server.d.ts +52 -1
  67. package/dist/server/server.js +165 -12
  68. package/dist/server/server.js.map +1 -1
  69. package/dist/server/templates/development.hbs +1 -55
  70. package/dist/server/templates/production.hbs +1 -2
  71. package/dist/server/widgetsDevServer.d.ts +2 -1
  72. package/dist/server/widgetsDevServer.js +7 -2
  73. package/dist/server/widgetsDevServer.js.map +1 -1
  74. package/dist/test/widget.test.js +29 -21
  75. package/dist/test/widget.test.js.map +1 -1
  76. package/dist/web/bridges/apps-sdk/adaptor.d.ts +5 -4
  77. package/dist/web/bridges/apps-sdk/adaptor.js +33 -6
  78. package/dist/web/bridges/apps-sdk/adaptor.js.map +1 -1
  79. package/dist/web/bridges/apps-sdk/bridge.d.ts +1 -1
  80. package/dist/web/bridges/apps-sdk/index.d.ts +1 -1
  81. package/dist/web/bridges/apps-sdk/index.js.map +1 -1
  82. package/dist/web/bridges/apps-sdk/types.d.ts +21 -8
  83. package/dist/web/bridges/apps-sdk/types.js.map +1 -1
  84. package/dist/web/bridges/mcp-app/adaptor.d.ts +7 -4
  85. package/dist/web/bridges/mcp-app/adaptor.js +40 -38
  86. package/dist/web/bridges/mcp-app/adaptor.js.map +1 -1
  87. package/dist/web/bridges/mcp-app/bridge.d.ts +13 -30
  88. package/dist/web/bridges/mcp-app/bridge.js +43 -196
  89. package/dist/web/bridges/mcp-app/bridge.js.map +1 -1
  90. package/dist/web/bridges/mcp-app/use-mcp-app-context.d.ts +5 -3
  91. package/dist/web/bridges/mcp-app/use-mcp-app-context.js +2 -2
  92. package/dist/web/bridges/mcp-app/use-mcp-app-context.js.map +1 -1
  93. package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js +1 -41
  94. package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js.map +1 -1
  95. package/dist/web/bridges/types.d.ts +10 -3
  96. package/dist/web/components/modal-provider.js +1 -3
  97. package/dist/web/components/modal-provider.js.map +1 -1
  98. package/dist/web/create-store.test.js +9 -4
  99. package/dist/web/create-store.test.js.map +1 -1
  100. package/dist/web/data-llm.test.js +11 -8
  101. package/dist/web/data-llm.test.js.map +1 -1
  102. package/dist/web/hooks/index.d.ts +2 -1
  103. package/dist/web/hooks/index.js +1 -0
  104. package/dist/web/hooks/index.js.map +1 -1
  105. package/dist/web/hooks/test/utils.js +4 -0
  106. package/dist/web/hooks/test/utils.js.map +1 -1
  107. package/dist/web/hooks/use-display-mode.d.ts +3 -3
  108. package/dist/web/hooks/use-display-mode.js.map +1 -1
  109. package/dist/web/hooks/use-display-mode.test-d.d.ts +1 -0
  110. package/dist/web/hooks/use-display-mode.test-d.js +8 -0
  111. package/dist/web/hooks/use-display-mode.test-d.js.map +1 -0
  112. package/dist/web/hooks/use-files.test.js +5 -1
  113. package/dist/web/hooks/use-files.test.js.map +1 -1
  114. package/dist/web/hooks/use-layout.test.js +3 -3
  115. package/dist/web/hooks/use-layout.test.js.map +1 -1
  116. package/dist/web/hooks/use-open-external.d.ts +3 -1
  117. package/dist/web/hooks/use-open-external.js +1 -1
  118. package/dist/web/hooks/use-open-external.js.map +1 -1
  119. package/dist/web/hooks/use-open-external.test.js +26 -11
  120. package/dist/web/hooks/use-open-external.test.js.map +1 -1
  121. package/dist/web/hooks/use-request-modal.test.js +5 -1
  122. package/dist/web/hooks/use-request-modal.test.js.map +1 -1
  123. package/dist/web/hooks/use-set-open-in-app-url.d.ts +1 -0
  124. package/dist/web/hooks/use-set-open-in-app-url.js +8 -0
  125. package/dist/web/hooks/use-set-open-in-app-url.js.map +1 -0
  126. package/dist/web/hooks/use-set-open-in-app-url.test.d.ts +1 -0
  127. package/dist/web/hooks/use-set-open-in-app-url.test.js +43 -0
  128. package/dist/web/hooks/use-set-open-in-app-url.test.js.map +1 -0
  129. package/dist/web/hooks/use-tool-info.test.js +1 -1
  130. package/dist/web/hooks/use-tool-info.test.js.map +1 -1
  131. package/dist/web/hooks/use-user.js +18 -2
  132. package/dist/web/hooks/use-user.js.map +1 -1
  133. package/dist/web/hooks/use-user.test.js +29 -1
  134. package/dist/web/hooks/use-user.test.js.map +1 -1
  135. package/dist/web/hooks/use-widget-state.test.js +9 -6
  136. package/dist/web/hooks/use-widget-state.test.js.map +1 -1
  137. package/dist/web/plugin/plugin.js +24 -9
  138. package/dist/web/plugin/plugin.js.map +1 -1
  139. package/dist/web/plugin/transform-data-llm.js +1 -1
  140. package/dist/web/plugin/transform-data-llm.js.map +1 -1
  141. package/dist/web/plugin/validate-widget.d.ts +5 -0
  142. package/dist/web/plugin/validate-widget.js +27 -0
  143. package/dist/web/plugin/validate-widget.js.map +1 -0
  144. package/dist/web/plugin/validate-widget.test.d.ts +1 -0
  145. package/dist/web/plugin/validate-widget.test.js +42 -0
  146. package/dist/web/plugin/validate-widget.test.js.map +1 -0
  147. package/dist/web/proxy.js +0 -1
  148. package/dist/web/proxy.js.map +1 -1
  149. package/package.json +33 -23
  150. package/tsconfig.base.json +31 -0
@@ -2,7 +2,9 @@ import type { McpUiResourceMeta } from "@modelcontextprotocol/ext-apps";
2
2
  import { McpServer as McpServerBase, type RegisteredTool } from "@modelcontextprotocol/sdk/server/mcp.js";
3
3
  import type { AnySchema, SchemaOutput, ZodRawShapeCompat } from "@modelcontextprotocol/sdk/server/zod-compat.js";
4
4
  import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
5
- import type { CallToolResult, Resource, ServerNotification, ServerRequest, ToolAnnotations } from "@modelcontextprotocol/sdk/types.js";
5
+ import type { CallToolResult, Resource, ServerNotification, ServerRequest, ServerResult, ToolAnnotations } from "@modelcontextprotocol/sdk/types.js";
6
+ import type { ErrorRequestHandler, RequestHandler } from "express";
7
+ import type { McpExtra, McpExtraFor, McpMethodString, McpMiddlewareFilter, McpMiddlewareFn, McpResultFor, McpTypedMiddlewareFn, McpWildcard } from "./middleware.js";
6
8
  export type ToolDef<TInput = unknown, TOutput = unknown, TResponseMetadata = unknown> = {
7
9
  input: TInput;
8
10
  output: TOutput;
@@ -81,6 +83,55 @@ type ToolHandler<TInput extends ZodRawShapeCompat, TReturn extends {
81
83
  } = CallToolResult> = (args: ShapeOutput<TInput>, extra: RequestHandlerExtra<ServerRequest, ServerNotification>) => TReturn | Promise<TReturn>;
82
84
  export declare class McpServer<TTools extends Record<string, ToolDef> = Record<never, ToolDef>> extends McpServerBase {
83
85
  readonly $types: McpServerTypes<TTools>;
86
+ private express?;
87
+ private customMiddleware;
88
+ private customErrorMiddleware;
89
+ private mcpMiddlewareEntries;
90
+ private mcpMiddlewareApplied;
91
+ use(...handlers: RequestHandler[]): this;
92
+ use(path: string, ...handlers: RequestHandler[]): this;
93
+ useOnError(...handlers: ErrorRequestHandler[]): this;
94
+ useOnError(path: string, ...handlers: ErrorRequestHandler[]): this;
95
+ /**
96
+ * Register MCP protocol-level middleware (catch-all).
97
+ */
98
+ mcpMiddleware(handler: McpMiddlewareFn): this;
99
+ /**
100
+ * Register MCP protocol-level middleware for all requests (`extra` is `McpExtra`).
101
+ */
102
+ mcpMiddleware(filter: "request", handler: (request: {
103
+ method: string;
104
+ params: Record<string, unknown>;
105
+ }, extra: McpExtra, next: () => Promise<ServerResult>) => Promise<unknown> | unknown): this;
106
+ /**
107
+ * Register MCP protocol-level middleware for all notifications (`extra` is `undefined`).
108
+ */
109
+ mcpMiddleware(filter: "notification", handler: (request: {
110
+ method: string;
111
+ params: Record<string, unknown>;
112
+ }, extra: undefined, next: () => Promise<undefined>) => Promise<unknown> | unknown): this;
113
+ /**
114
+ * Register MCP protocol-level middleware for an exact method.
115
+ * Narrows `params`, `extra`, and `next()` result based on the method string.
116
+ */
117
+ mcpMiddleware<M extends McpMethodString>(filter: M, handler: McpTypedMiddlewareFn<M>): this;
118
+ /**
119
+ * Register MCP protocol-level middleware for a wildcard pattern (e.g. `"tools/*"`).
120
+ * `next()` returns the union of result types for matching methods.
121
+ */
122
+ mcpMiddleware<W extends McpWildcard>(filter: W, handler: (request: {
123
+ method: string;
124
+ params: Record<string, unknown>;
125
+ }, extra: McpExtraFor<W>, next: () => Promise<McpResultFor<W>>) => Promise<unknown> | unknown): this;
126
+ /**
127
+ * Register MCP protocol-level middleware with a method filter.
128
+ * Filter can be an exact method (`"tools/call"`), wildcard (`"tools/*"`),
129
+ * category (`"request"` | `"notification"`), or an array of those.
130
+ */
131
+ mcpMiddleware(filter: McpMiddlewareFilter, handler: McpMiddlewareFn): this;
132
+ private applyMcpMiddleware;
133
+ connect(transport: Parameters<typeof McpServerBase.prototype.connect>[0]): Promise<void>;
134
+ run(): Promise<void>;
84
135
  registerWidget<TName extends string, TInput extends ZodRawShapeCompat, TReturn extends {
85
136
  content: CallToolResult["content"];
86
137
  }>(name: TName, resourceConfig: McpServerOriginalResourceConfig, toolConfig: McpServerOriginalToolConfig & {
@@ -1,7 +1,12 @@
1
+ import crypto from "node:crypto";
1
2
  import { readFileSync } from "node:fs";
3
+ import http from "node:http";
2
4
  import path from "node:path";
3
5
  import { McpServer as McpServerBase, } from "@modelcontextprotocol/sdk/server/mcp.js";
4
6
  import { mergeWith, union } from "es-toolkit";
7
+ import { createApp } from "./express.js";
8
+ import { buildMiddlewareChain, getHandlerMaps } from "./middleware.js";
9
+ import { createMonitoringEntry } from "./monitoring.js";
5
10
  import { templateHelper } from "./templateHelper.js";
6
11
  const mergeWithUnion = (target, source) => {
7
12
  return mergeWith(target, source, (targetVal, sourceVal) => {
@@ -11,6 +16,111 @@ const mergeWithUnion = (target, source) => {
11
16
  });
12
17
  };
13
18
  export class McpServer extends McpServerBase {
19
+ express;
20
+ customMiddleware = [];
21
+ customErrorMiddleware = [];
22
+ mcpMiddlewareEntries = [];
23
+ mcpMiddlewareApplied = false;
24
+ use(pathOrHandler, ...handlers) {
25
+ if (typeof pathOrHandler === "string") {
26
+ this.customMiddleware.push({
27
+ path: pathOrHandler,
28
+ handlers,
29
+ });
30
+ }
31
+ else {
32
+ this.customMiddleware.push({
33
+ handlers: [pathOrHandler, ...handlers],
34
+ });
35
+ }
36
+ return this;
37
+ }
38
+ useOnError(pathOrHandler, ...handlers) {
39
+ if (typeof pathOrHandler === "string") {
40
+ this.customErrorMiddleware.push({ path: pathOrHandler, handlers });
41
+ }
42
+ else {
43
+ this.customErrorMiddleware.push({
44
+ handlers: [pathOrHandler, ...handlers],
45
+ });
46
+ }
47
+ return this;
48
+ }
49
+ mcpMiddleware(filterOrHandler,
50
+ // biome-ignore lint/suspicious/noExplicitAny: overloads narrow the handler type at call sites; implementation must accept all variants
51
+ maybeHandler) {
52
+ if (this.mcpMiddlewareApplied) {
53
+ throw new Error("Cannot register MCP middleware after run() or connect() has been called");
54
+ }
55
+ const handler = maybeHandler;
56
+ if (typeof filterOrHandler === "function") {
57
+ this.mcpMiddlewareEntries.push({
58
+ filter: null,
59
+ handler: filterOrHandler,
60
+ });
61
+ }
62
+ else if (handler) {
63
+ this.mcpMiddlewareEntries.push({
64
+ filter: filterOrHandler,
65
+ handler,
66
+ });
67
+ }
68
+ else {
69
+ throw new Error("mcpMiddleware requires a handler function when a filter is provided");
70
+ }
71
+ return this;
72
+ }
73
+ applyMcpMiddleware() {
74
+ if (this.mcpMiddlewareApplied) {
75
+ return;
76
+ }
77
+ this.mcpMiddlewareApplied = true;
78
+ const monitoringEntry = createMonitoringEntry();
79
+ const entries = monitoringEntry
80
+ ? [monitoringEntry, ...this.mcpMiddlewareEntries]
81
+ : this.mcpMiddlewareEntries;
82
+ if (entries.length === 0) {
83
+ return;
84
+ }
85
+ const { requestHandlers, notificationHandlers } = getHandlerMaps(this.server);
86
+ // Wrap existing handlers and proxy future .set() for lazy SDK registration
87
+ const instrumentMap = (map, isNotification) => {
88
+ for (const [method, handler] of map) {
89
+ map.set(method, buildMiddlewareChain(method, isNotification, handler, entries));
90
+ }
91
+ const originalSet = map.set.bind(map);
92
+ map.set = (method, handler) => originalSet(method, buildMiddlewareChain(method, isNotification, handler, entries));
93
+ };
94
+ instrumentMap(requestHandlers, false);
95
+ instrumentMap(notificationHandlers, true);
96
+ }
97
+ async connect(transport) {
98
+ this.applyMcpMiddleware();
99
+ return super.connect(transport);
100
+ }
101
+ async run() {
102
+ this.applyMcpMiddleware();
103
+ const httpServer = http.createServer();
104
+ if (!this.express) {
105
+ this.express = await createApp({
106
+ mcpServer: this,
107
+ httpServer,
108
+ customMiddleware: this.customMiddleware,
109
+ errorMiddleware: this.customErrorMiddleware,
110
+ });
111
+ }
112
+ httpServer.on("request", this.express);
113
+ return new Promise((resolve, reject) => {
114
+ httpServer.on("error", (error) => {
115
+ console.error("Failed to start server:", error);
116
+ reject(error);
117
+ });
118
+ const port = parseInt(process.env.__PORT ?? "3000", 10);
119
+ httpServer.listen(port, () => {
120
+ resolve();
121
+ });
122
+ });
123
+ }
14
124
  registerWidget(name, resourceConfig, toolConfig, toolCallback) {
15
125
  const userMeta = resourceConfig._meta;
16
126
  const toolMeta = {
@@ -21,7 +131,7 @@ export class McpServer extends McpServerBase {
21
131
  hostType: "apps-sdk",
22
132
  uri: `ui://widgets/apps-sdk/${name}.html`,
23
133
  mimeType: "text/html+skybridge",
24
- buildContentMeta: ({ resourceDomains, connectDomains, domain }) => {
134
+ buildContentMeta: ({ resourceDomains, connectDomains, domain }, overrides) => {
25
135
  const userUi = userMeta?.ui;
26
136
  const userCsp = userUi?.csp;
27
137
  const defaults = {
@@ -30,7 +140,7 @@ export class McpServer extends McpServerBase {
30
140
  connect_domains: connectDomains,
31
141
  },
32
142
  "openai/widgetDomain": domain,
33
- "openai/widgetDescription": toolConfig.description,
143
+ "openai/widgetDescription": resourceConfig.description,
34
144
  };
35
145
  const fromUi = {
36
146
  "openai/widgetCSP": {
@@ -43,7 +153,7 @@ export class McpServer extends McpServerBase {
43
153
  "openai/widgetPrefersBorder": userUi?.prefersBorder,
44
154
  };
45
155
  const directOpenaiKeys = Object.fromEntries(Object.entries(userMeta ?? {}).filter(([key]) => key.startsWith("openai/")));
46
- return mergeWithUnion(mergeWithUnion(defaults, fromUi), directOpenaiKeys);
156
+ return mergeWithUnion(mergeWithUnion(mergeWithUnion(defaults, fromUi), directOpenaiKeys), { "openai/widgetDomain": overrides.domain });
47
157
  },
48
158
  };
49
159
  this.registerWidgetResource({
@@ -58,7 +168,7 @@ export class McpServer extends McpServerBase {
58
168
  hostType: "mcp-app",
59
169
  uri: `ui://widgets/ext-apps/${name}.html`,
60
170
  mimeType: "text/html;profile=mcp-app",
61
- buildContentMeta: ({ resourceDomains, connectDomains, domain }) => {
171
+ buildContentMeta: ({ resourceDomains, connectDomains, domain }, overrides) => {
62
172
  const defaults = {
63
173
  ui: {
64
174
  csp: {
@@ -68,7 +178,9 @@ export class McpServer extends McpServerBase {
68
178
  domain,
69
179
  },
70
180
  };
71
- return mergeWithUnion(defaults, { ui: userMeta?.ui });
181
+ return mergeWithUnion(defaults, {
182
+ ui: { ...userMeta?.ui, ...overrides },
183
+ });
72
184
  },
73
185
  };
74
186
  this.registerWidgetResource({
@@ -76,6 +188,8 @@ export class McpServer extends McpServerBase {
76
188
  widgetConfig,
77
189
  resourceConfig,
78
190
  });
191
+ // @ts-expect-error - For backwards compatibility with Claude current implementation of the specs
192
+ toolMeta["ui/resourceUri"] = widgetConfig.uri;
79
193
  toolMeta.ui = { resourceUri: widgetConfig.uri };
80
194
  }
81
195
  this.registerTool(name, {
@@ -92,10 +206,33 @@ export class McpServer extends McpServerBase {
92
206
  const { hostType, uri: widgetUri, mimeType, buildContentMeta, } = widgetConfig;
93
207
  this.registerResource(name, widgetUri, { ...resourceConfig, _meta: resourceConfig._meta }, async (uri, extra) => {
94
208
  const isProduction = process.env.NODE_ENV === "production";
95
- const useForwardedHost = process.env.SKYBRIDGE_USE_FORWARDED_HOST === "true";
96
- const serverUrl = isProduction || useForwardedHost
97
- ? `https://${extra?.requestInfo?.headers?.["x-forwarded-host"] ?? extra?.requestInfo?.headers?.host}`
98
- : "http://localhost:3000";
209
+ const isClaude = extra?.requestInfo?.headers?.["user-agent"] === "Claude-User";
210
+ const headers = extra?.requestInfo?.headers || {};
211
+ const header = (key) => {
212
+ const val = headers[key];
213
+ return Array.isArray(val) ? val[0] : val;
214
+ };
215
+ let serverUrl;
216
+ const forwardedHost = header("x-forwarded-host");
217
+ const origin = header("origin");
218
+ const host = header("host");
219
+ if (forwardedHost) {
220
+ const proto = header("x-forwarded-proto") || "https";
221
+ serverUrl = `${proto}://${forwardedHost}`;
222
+ }
223
+ else if (origin) {
224
+ serverUrl = origin;
225
+ }
226
+ else if (host) {
227
+ const proto = ["127.0.0.1:", "localhost:"].some((p) => host.startsWith(p))
228
+ ? "http"
229
+ : "https";
230
+ serverUrl = `${proto}://${host}`;
231
+ }
232
+ else {
233
+ const devPort = process.env.__PORT || "3000";
234
+ serverUrl = `http://localhost:${devPort}`;
235
+ }
99
236
  const html = isProduction
100
237
  ? templateHelper.renderProduction({
101
238
  hostType,
@@ -108,13 +245,29 @@ export class McpServer extends McpServerBase {
108
245
  serverUrl,
109
246
  widgetName: name,
110
247
  });
111
- const VITE_HMR_WEBSOCKET_DEFAULT_URL = "ws://localhost:24678";
248
+ const connectDomains = [serverUrl];
249
+ if (!isProduction) {
250
+ const wsUrl = new URL(serverUrl);
251
+ wsUrl.protocol = wsUrl.protocol === "https:" ? "wss:" : "ws:";
252
+ connectDomains.push(wsUrl.origin);
253
+ }
254
+ let contentMetaOverrides = {};
255
+ if (isClaude) {
256
+ const pathname = extra?.requestInfo?.url?.pathname ?? "";
257
+ const url = `${serverUrl}${pathname}`;
258
+ const hash = crypto
259
+ .createHash("sha256")
260
+ .update(url)
261
+ .digest("hex")
262
+ .slice(0, 32);
263
+ contentMetaOverrides = { domain: `${hash}.claudemcpcontent.com` };
264
+ }
112
265
  const contentMeta = buildContentMeta({
113
266
  resourceDomains: [serverUrl],
114
- connectDomains: !isProduction ? [VITE_HMR_WEBSOCKET_DEFAULT_URL] : [],
267
+ connectDomains,
115
268
  domain: serverUrl,
116
269
  baseUriDomains: [serverUrl],
117
- });
270
+ }, contentMetaOverrides);
118
271
  return {
119
272
  contents: [
120
273
  { uri: uri.href, mimeType, text: html, _meta: contentMeta },
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server/server.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,4 @@
1
- <base href="{{serverUrl}}" />
2
- <script type="module">window.skybridge = { hostType: "{{hostType}}" };</script>
1
+ <script type="module">window.skybridge = { hostType: "{{hostType}}", serverUrl: "{{serverUrl}}" };</script>
3
2
  <script type="module">
4
3
  import { injectIntoGlobalHook } from "{{serverUrl}}/assets/@react-refresh";
5
4
  injectIntoGlobalHook(window); window.$RefreshReg$ = () => {};
@@ -7,59 +6,6 @@
7
6
  window.__vite_plugin_react_preamble_installed__ = true;
8
7
  </script>
9
8
  <script type="module" src="{{serverUrl}}/@vite/client"></script>
10
- <script type="module">
11
- // Checks for browser support and shows error if local network access is denied
12
- (async () => {
13
- if (!navigator.permissions?.query) {
14
- return;
15
- }
16
-
17
- // Skip for non-http(s) protocols (file://, custom protocols in Electron, etc.)
18
- const protocol = window.location.protocol;
19
- const isNonHttpProtocol = protocol !== 'http:' && protocol !== 'https:'
20
- if (isNonHttpProtocol) {
21
- return;
22
- }
23
-
24
- const host = window.location.hostname;
25
- const isLoopback = host === 'localhost'
26
- || /^127\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.test(host)
27
- || host === '::1';
28
- if (isLoopback) {
29
- return;
30
- }
31
-
32
- try {
33
- const status = await navigator.permissions.query({ name: "local-network-access" });
34
- if (status.state === "denied") {
35
- const errorDiv = document.createElement("div");
36
- errorDiv.style.cssText = "background: #fef2f2; border: 2px solid #ef4444; border-radius: 8px; padding: 16px; text-align: center; z-index: 10000; font-family: system-ui, sans-serif;";
37
-
38
- const errorTitle = document.createElement("div");
39
- errorTitle.style.cssText = "color: #ef4444; font-size: 18px; font-weight: 600; margin-bottom: 8px;";
40
- errorTitle.textContent = "Error: Local network access permission is denied.";
41
-
42
- const errorMessage = document.createElement("div");
43
- errorMessage.style.cssText = "color: #ef4444; font-size: 14px;";
44
- errorMessage.textContent = "Local network access is required for your widget to connect to the local dev server. Please enable it in your browser settings. ";
45
-
46
- const link = document.createElement("a");
47
- link.href = "https://developer.chrome.com/blog/local-network-access";
48
- link.target = "_blank";
49
- link.rel = "noopener noreferrer";
50
- link.style.cssText = "color: #ef4444; text-decoration: underline;";
51
- link.textContent = "Learn more";
52
- errorMessage.appendChild(link);
53
-
54
- errorDiv.appendChild(errorTitle);
55
- errorDiv.appendChild(errorMessage);
56
- document.body.appendChild(errorDiv);
57
- }
58
- } catch (e) {
59
- // Permission API doesn't support local-network-access, ignore silently
60
- }
61
- })();
62
- </script>
63
9
  <div id="root"></div>
64
10
  <script type="module" id="dev-widget-entry">
65
11
  import('{{serverUrl}}/src/widgets/{{widgetName}}');
@@ -1,5 +1,4 @@
1
- <base href="{{serverUrl}}" />
2
- <script type="module">window.skybridge = { hostType: "{{hostType}}" };</script>
1
+ <script type="module">window.skybridge = { hostType: "{{hostType}}", serverUrl: "{{serverUrl}}" };</script>
3
2
  <div id="root"></div>
4
3
  <script type="module">
5
4
  import('{{serverUrl}}/assets/{{widgetFile}}');
@@ -1,3 +1,4 @@
1
+ import type http from "node:http";
1
2
  import { type Router } from "express";
2
3
  /**
3
4
  * Install Vite dev server
@@ -9,4 +10,4 @@ import { type Router } from "express";
9
10
  * app.use(await widgetsRouter());
10
11
  * }
11
12
  */
12
- export declare const widgetsDevServer: () => Promise<Router>;
13
+ export declare const widgetsDevServer: (httpServer: http.Server) => Promise<Router>;
@@ -2,6 +2,7 @@ import { existsSync } from "node:fs";
2
2
  import path from "node:path";
3
3
  import cors from "cors";
4
4
  import express, {} from "express";
5
+ import { assetBaseUrlTransformPlugin } from "./asset-base-url-transform-plugin.js";
5
6
  /**
6
7
  * Install Vite dev server
7
8
  * This router MUST be installed at the application root, like so:
@@ -12,7 +13,7 @@ import express, {} from "express";
12
13
  * app.use(await widgetsRouter());
13
14
  * }
14
15
  */
15
- export const widgetsDevServer = async () => {
16
+ export const widgetsDevServer = async (httpServer) => {
16
17
  const router = express.Router();
17
18
  const { createServer, searchForWorkspaceRoot, loadConfigFromFile } = await import("vite");
18
19
  // Since 0.16.0, the template is a single package that does not rely on workspace.
@@ -26,7 +27,7 @@ export const widgetsDevServer = async () => {
26
27
  webAppRoot = path.join(workspaceRoot, "web");
27
28
  }
28
29
  const configResult = await loadConfigFromFile({ command: "serve", mode: "development" }, path.join(webAppRoot, "vite.config.ts"), webAppRoot);
29
- const { build, preview, ...devConfig } = configResult?.config || {};
30
+ const { build, preview, plugins: userPlugins = [], ...devConfig } = configResult?.config || {};
30
31
  const vite = await createServer({
31
32
  ...devConfig,
32
33
  configFile: false, // Keep this to prevent vite from trying to resolve path in the target config file
@@ -34,11 +35,15 @@ export const widgetsDevServer = async () => {
34
35
  server: {
35
36
  allowedHosts: true,
36
37
  middlewareMode: true,
38
+ hmr: {
39
+ server: httpServer,
40
+ },
37
41
  },
38
42
  root: webAppRoot,
39
43
  optimizeDeps: {
40
44
  include: ["react", "react-dom/client"],
41
45
  },
46
+ plugins: [...userPlugins, assetBaseUrlTransformPlugin()],
42
47
  });
43
48
  router.use(cors());
44
49
  router.use("/", vite.middlewares);
@@ -1 +1 @@
1
- {"version":3,"file":"widgetsDevServer.js","sourceRoot":"","sources":["../../src/server/widgetsDevServer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,OAAO,EAAE,EAAe,MAAM,SAAS,CAAC;AAC/C;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,IAAqB,EAAE;IAC1D,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAEhC,MAAM,EAAE,YAAY,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,GAChE,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;IAEvB,kFAAkF;IAClF,gFAAgF;IAChF,+FAA+F;IAC/F,IAAI,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC;IAEjD,0DAA0D;IAC1D,MAAM,aAAa,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;IAC7C,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,MAAM,aAAa,GAAG,sBAAsB,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QAC5D,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;IAC/C,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,kBAAkB,CAC3C,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,EACzC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,gBAAgB,CAAC,EACvC,UAAU,CACX,CAAC;IAEF,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,SAAS,EAAE,GAAG,YAAY,EAAE,MAAM,IAAI,EAAE,CAAC;IAEpE,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC;QAC9B,GAAG,SAAS;QACZ,UAAU,EAAE,KAAK,EAAE,kFAAkF;QACrG,OAAO,EAAE,QAAQ;QACjB,MAAM,EAAE;YACN,YAAY,EAAE,IAAI;YAClB,cAAc,EAAE,IAAI;SACrB;QACD,IAAI,EAAE,UAAU;QAChB,YAAY,EAAE;YACZ,OAAO,EAAE,CAAC,OAAO,EAAE,kBAAkB,CAAC;SACvC;KACF,CAAC,CAAC;IAEH,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IACnB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAElC,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC"}
1
+ {"version":3,"file":"widgetsDevServer.js","sourceRoot":"","sources":["../../src/server/widgetsDevServer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,OAAO,EAAE,EAAe,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,2BAA2B,EAAE,MAAM,sCAAsC,CAAC;AAEnF;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,EACnC,UAAuB,EACN,EAAE;IACnB,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAEhC,MAAM,EAAE,YAAY,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,GAChE,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;IAEvB,kFAAkF;IAClF,gFAAgF;IAChF,+FAA+F;IAC/F,IAAI,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC;IAEjD,0DAA0D;IAC1D,MAAM,aAAa,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;IAC7C,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,MAAM,aAAa,GAAG,sBAAsB,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QAC5D,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;IAC/C,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,kBAAkB,CAC3C,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,EACzC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,gBAAgB,CAAC,EACvC,UAAU,CACX,CAAC;IAEF,MAAM,EACJ,KAAK,EACL,OAAO,EACP,OAAO,EAAE,WAAW,GAAG,EAAE,EACzB,GAAG,SAAS,EACb,GAAG,YAAY,EAAE,MAAM,IAAI,EAAE,CAAC;IAE/B,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC;QAC9B,GAAG,SAAS;QACZ,UAAU,EAAE,KAAK,EAAE,kFAAkF;QACrG,OAAO,EAAE,QAAQ;QACjB,MAAM,EAAE;YACN,YAAY,EAAE,IAAI;YAClB,cAAc,EAAE,IAAI;YACpB,GAAG,EAAE;gBACH,MAAM,EAAE,UAAU;aACnB;SACF;QACD,IAAI,EAAE,UAAU;QAChB,YAAY,EAAE;YACZ,OAAO,EAAE,CAAC,OAAO,EAAE,kBAAkB,CAAC;SACvC;QACD,OAAO,EAAE,CAAC,GAAG,WAAW,EAAE,2BAA2B,EAAE,CAAC;KACzD,CAAC,CAAC;IAEH,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IACnB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAElC,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC"}
@@ -43,8 +43,10 @@ describe("McpServer.registerWidget", () => {
43
43
  const appsSdkResourceCallback = mockRegisterResource.mock
44
44
  .calls[0]?.[3];
45
45
  expect(appsSdkResourceCallback).toBeDefined();
46
- const serverUrl = "http://localhost:3000";
47
- const mockExtra = createMockExtra("__not_used__");
46
+ const host = "localhost:3000";
47
+ const serverUrl = `http://${host}`;
48
+ const hmrUrl = `ws://${host}`;
49
+ const mockExtra = createMockExtra(host);
48
50
  const result = await appsSdkResourceCallback(new URL("ui://widgets/apps-sdk/my-widget.html"), mockExtra);
49
51
  expect(mockRegisterTool).toHaveBeenCalled();
50
52
  expect(result).toEqual({
@@ -56,10 +58,10 @@ describe("McpServer.registerWidget", () => {
56
58
  _meta: {
57
59
  "openai/widgetCSP": {
58
60
  resource_domains: [serverUrl],
59
- connect_domains: ["ws://localhost:24678"],
61
+ connect_domains: [serverUrl, hmrUrl],
60
62
  },
61
63
  "openai/widgetDomain": serverUrl,
62
- "openai/widgetDescription": "Test tool",
64
+ "openai/widgetDescription": "Test widget",
63
65
  },
64
66
  },
65
67
  ],
@@ -93,10 +95,10 @@ describe("McpServer.registerWidget", () => {
93
95
  _meta: {
94
96
  "openai/widgetCSP": {
95
97
  resource_domains: [serverUrl],
96
- connect_domains: [],
98
+ connect_domains: [serverUrl],
97
99
  },
98
100
  "openai/widgetDomain": serverUrl,
99
- "openai/widgetDescription": "Test tool",
101
+ "openai/widgetDescription": "Test widget",
100
102
  },
101
103
  },
102
104
  ],
@@ -134,7 +136,10 @@ describe("McpServer.registerWidget", () => {
134
136
  expect(mockRegisterResource).toHaveBeenCalledTimes(2);
135
137
  const appsSdkCallback = mockRegisterResource.mock
136
138
  .calls[0]?.[3];
137
- const appsSdkResult = await appsSdkCallback(new URL("ui://widgets/apps-sdk/my-widget.html"), createMockExtra("__not_used__"));
139
+ const appsSdkResult = await appsSdkCallback(new URL("ui://widgets/apps-sdk/my-widget.html"), createMockExtra("localhost:3000"));
140
+ const host = "localhost:3000";
141
+ const serverUrl = `http://${host}`;
142
+ const hmrUrl = `ws://${host}`;
138
143
  expect(appsSdkResult).toEqual({
139
144
  contents: [
140
145
  {
@@ -143,21 +148,21 @@ describe("McpServer.registerWidget", () => {
143
148
  text: expect.stringContaining('<div id="root"></div>'),
144
149
  _meta: {
145
150
  "openai/widgetCSP": {
146
- resource_domains: ["http://localhost:3000"],
147
- connect_domains: ["ws://localhost:24678"],
151
+ resource_domains: [serverUrl],
152
+ connect_domains: [serverUrl, hmrUrl],
148
153
  },
149
- "openai/widgetDomain": "http://localhost:3000",
150
- "openai/widgetDescription": "Test tool",
154
+ "openai/widgetDomain": serverUrl,
155
+ "openai/widgetDescription": "Test widget",
151
156
  "openai/widgetPrefersBorder": true,
152
157
  },
153
158
  },
154
159
  ],
155
160
  });
156
- expect(appsSdkResult.contents[0]?.text).toContain('window.skybridge = { hostType: "apps-sdk" }');
161
+ expect(appsSdkResult.contents[0]?.text).toContain('window.skybridge = { hostType: "apps-sdk", serverUrl: "http://localhost:3000" };');
157
162
  const extAppsResourceCallback = mockRegisterResource.mock
158
163
  .calls[1]?.[3];
159
164
  expect(extAppsResourceCallback).toBeDefined();
160
- const extAppsResult = await extAppsResourceCallback(new URL("ui://widgets/ext-apps/my-widget.html"), createMockExtra("__not_used__"));
165
+ const extAppsResult = await extAppsResourceCallback(new URL("ui://widgets/ext-apps/my-widget.html"), createMockExtra(host));
161
166
  expect(extAppsResult).toEqual({
162
167
  contents: [
163
168
  {
@@ -167,16 +172,16 @@ describe("McpServer.registerWidget", () => {
167
172
  _meta: {
168
173
  ui: {
169
174
  csp: {
170
- resourceDomains: ["http://localhost:3000"],
171
- connectDomains: ["ws://localhost:24678"],
175
+ resourceDomains: [serverUrl],
176
+ connectDomains: [serverUrl, hmrUrl],
172
177
  },
173
- domain: "http://localhost:3000",
178
+ domain: serverUrl,
174
179
  },
175
180
  },
176
181
  },
177
182
  ],
178
183
  });
179
- expect(extAppsResult.contents[0]?.text).toContain('window.skybridge = { hostType: "mcp-app" }');
184
+ expect(extAppsResult.contents[0]?.text).toContain('window.skybridge = { hostType: "mcp-app", serverUrl: "http://localhost:3000" };');
180
185
  });
181
186
  it("should register tool with ui.resourceUri metadata (not deprecated ui/resourceUri)", async () => {
182
187
  const mockToolCallback = vi.fn();
@@ -214,12 +219,15 @@ describe("McpServer.registerWidget", () => {
214
219
  server.registerWidget("override-test", mockRegisterResourceConfig, mockToolConfig, mockToolCallback);
215
220
  const appsSdkCallback = mockRegisterResource.mock
216
221
  .calls[0]?.[3];
217
- const result = await appsSdkCallback(new URL("ui://widgets/apps-sdk/override-test.html"), createMockExtra("__not_used__"));
222
+ const host = `localhost:3000`;
223
+ const serverUrl = `http://${host}`;
224
+ const hmrUrl = `ws://${host}`;
225
+ const result = await appsSdkCallback(new URL("ui://widgets/apps-sdk/override-test.html"), createMockExtra(host));
218
226
  const meta = result.contents[0]?._meta;
219
227
  // CSP arrays are merged with union - all unique domains from defaults and user config are preserved
220
228
  expect(meta["openai/widgetCSP"]).toEqual({
221
- resource_domains: ["http://localhost:3000", "https://from-ui-csp.com"],
222
- connect_domains: ["ws://localhost:24678", "https://from-ui-csp.com"],
229
+ resource_domains: [serverUrl, "https://from-ui-csp.com"],
230
+ connect_domains: [serverUrl, hmrUrl, "https://from-ui-csp.com"],
223
231
  frame_domains: undefined,
224
232
  redirect_domains: undefined,
225
233
  });
@@ -228,7 +236,7 @@ describe("McpServer.registerWidget", () => {
228
236
  // PrefersBorder should be overridden by direct openai/* key (highest priority)
229
237
  expect(meta["openai/widgetPrefersBorder"]).toBe(true);
230
238
  // Description should be from defaults (toolConfig.description)
231
- expect(meta["openai/widgetDescription"]).toBe("Test tool");
239
+ expect(meta["openai/widgetDescription"]).toBe("Test widget");
232
240
  });
233
241
  it("should register tool with ui.resourceUri metadata only", async () => {
234
242
  const mockToolCallback = vi.fn();