skybridge 0.0.0-dev.66b8f6b → 0.0.0-dev.66ea4ea

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 (264) hide show
  1. package/LICENSE +21 -674
  2. package/README.md +143 -1
  3. package/bin/run.js +5 -0
  4. package/dist/cli/detect-port.d.ts +18 -0
  5. package/dist/cli/detect-port.js +61 -0
  6. package/dist/cli/detect-port.js.map +1 -0
  7. package/dist/cli/header.d.ts +4 -0
  8. package/dist/cli/header.js +6 -0
  9. package/dist/cli/header.js.map +1 -0
  10. package/dist/cli/run-command.d.ts +2 -0
  11. package/dist/cli/run-command.js +43 -0
  12. package/dist/cli/run-command.js.map +1 -0
  13. package/dist/cli/telemetry.d.ts +7 -0
  14. package/dist/cli/telemetry.js +123 -0
  15. package/dist/cli/telemetry.js.map +1 -0
  16. package/dist/cli/use-execute-steps.d.ts +11 -0
  17. package/dist/cli/use-execute-steps.js +36 -0
  18. package/dist/cli/use-execute-steps.js.map +1 -0
  19. package/dist/cli/use-nodemon.d.ts +6 -0
  20. package/dist/cli/use-nodemon.js +69 -0
  21. package/dist/cli/use-nodemon.js.map +1 -0
  22. package/dist/cli/use-typescript-check.d.ts +8 -0
  23. package/dist/cli/use-typescript-check.js +59 -0
  24. package/dist/cli/use-typescript-check.js.map +1 -0
  25. package/dist/commands/build.d.ts +9 -0
  26. package/dist/commands/build.js +46 -0
  27. package/dist/commands/build.js.map +1 -0
  28. package/dist/commands/dev.d.ts +10 -0
  29. package/dist/commands/dev.js +42 -0
  30. package/dist/commands/dev.js.map +1 -0
  31. package/dist/commands/start.d.ts +9 -0
  32. package/dist/commands/start.js +52 -0
  33. package/dist/commands/start.js.map +1 -0
  34. package/dist/commands/telemetry/disable.d.ts +5 -0
  35. package/dist/commands/telemetry/disable.js +14 -0
  36. package/dist/commands/telemetry/disable.js.map +1 -0
  37. package/dist/commands/telemetry/enable.d.ts +5 -0
  38. package/dist/commands/telemetry/enable.js +14 -0
  39. package/dist/commands/telemetry/enable.js.map +1 -0
  40. package/dist/commands/telemetry/status.d.ts +5 -0
  41. package/dist/commands/telemetry/status.js +14 -0
  42. package/dist/commands/telemetry/status.js.map +1 -0
  43. package/dist/server/asset-base-url-transform-plugin.d.ts +11 -0
  44. package/dist/server/asset-base-url-transform-plugin.js +34 -0
  45. package/dist/server/asset-base-url-transform-plugin.js.map +1 -0
  46. package/dist/server/asset-base-url-transform-plugin.test.d.ts +1 -0
  47. package/dist/server/asset-base-url-transform-plugin.test.js +56 -0
  48. package/dist/server/asset-base-url-transform-plugin.test.js.map +1 -0
  49. package/dist/server/const.d.ts +1 -0
  50. package/dist/server/const.js +2 -0
  51. package/dist/server/const.js.map +1 -0
  52. package/dist/server/express.d.ts +9 -0
  53. package/dist/server/express.js +72 -0
  54. package/dist/server/express.js.map +1 -0
  55. package/dist/server/express.test.d.ts +1 -0
  56. package/dist/server/express.test.js +74 -0
  57. package/dist/server/express.test.js.map +1 -0
  58. package/dist/server/index.d.ts +2 -1
  59. package/dist/server/index.js +0 -1
  60. package/dist/server/index.js.map +1 -1
  61. package/dist/server/inferUtilityTypes.d.ts +64 -0
  62. package/dist/server/inferUtilityTypes.js +2 -0
  63. package/dist/server/inferUtilityTypes.js.map +1 -0
  64. package/dist/server/server.d.ts +103 -10
  65. package/dist/server/server.js +191 -57
  66. package/dist/server/server.js.map +1 -1
  67. package/dist/server/templateHelper.d.ts +19 -0
  68. package/dist/server/templateHelper.js +30 -0
  69. package/dist/server/templateHelper.js.map +1 -0
  70. package/dist/server/templates/development.hbs +67 -0
  71. package/dist/server/templates/production.hbs +6 -0
  72. package/dist/server/widgetsDevServer.d.ts +7 -4
  73. package/dist/server/widgetsDevServer.js +35 -8
  74. package/dist/server/widgetsDevServer.js.map +1 -1
  75. package/dist/test/utils.d.ts +135 -0
  76. package/dist/test/utils.js +242 -0
  77. package/dist/test/utils.js.map +1 -0
  78. package/dist/test/widget.test.d.ts +1 -0
  79. package/dist/test/widget.test.js +261 -0
  80. package/dist/test/widget.test.js.map +1 -0
  81. package/dist/web/bridges/apps-sdk/adaptor.d.ts +22 -0
  82. package/dist/web/bridges/apps-sdk/adaptor.js +71 -0
  83. package/dist/web/bridges/apps-sdk/adaptor.js.map +1 -0
  84. package/dist/web/bridges/apps-sdk/bridge.d.ts +10 -0
  85. package/dist/web/bridges/apps-sdk/bridge.js +46 -0
  86. package/dist/web/bridges/apps-sdk/bridge.js.map +1 -0
  87. package/dist/web/bridges/apps-sdk/index.d.ts +5 -0
  88. package/dist/web/bridges/apps-sdk/index.js +5 -0
  89. package/dist/web/bridges/apps-sdk/index.js.map +1 -0
  90. package/dist/web/bridges/apps-sdk/types.d.ts +118 -0
  91. package/dist/web/bridges/apps-sdk/types.js +10 -0
  92. package/dist/web/bridges/apps-sdk/types.js.map +1 -0
  93. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.d.ts +2 -0
  94. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js +7 -0
  95. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js.map +1 -0
  96. package/dist/web/bridges/get-adaptor.d.ts +2 -0
  97. package/dist/web/bridges/get-adaptor.js +8 -0
  98. package/dist/web/bridges/get-adaptor.js.map +1 -0
  99. package/dist/web/bridges/index.d.ts +5 -0
  100. package/dist/web/bridges/index.js +6 -0
  101. package/dist/web/bridges/index.js.map +1 -0
  102. package/dist/web/bridges/mcp-app/adaptor.d.ts +36 -0
  103. package/dist/web/bridges/mcp-app/adaptor.js +190 -0
  104. package/dist/web/bridges/mcp-app/adaptor.js.map +1 -0
  105. package/dist/web/bridges/mcp-app/bridge.d.ts +43 -0
  106. package/dist/web/bridges/mcp-app/bridge.js +260 -0
  107. package/dist/web/bridges/mcp-app/bridge.js.map +1 -0
  108. package/dist/web/bridges/mcp-app/index.d.ts +4 -0
  109. package/dist/web/bridges/mcp-app/index.js +4 -0
  110. package/dist/web/bridges/mcp-app/index.js.map +1 -0
  111. package/dist/web/bridges/mcp-app/types.d.ts +8 -0
  112. package/dist/web/bridges/mcp-app/types.js +2 -0
  113. package/dist/web/bridges/mcp-app/types.js.map +1 -0
  114. package/dist/web/bridges/mcp-app/use-mcp-app-context.d.ts +5 -0
  115. package/dist/web/bridges/mcp-app/use-mcp-app-context.js +7 -0
  116. package/dist/web/bridges/mcp-app/use-mcp-app-context.js.map +1 -0
  117. package/dist/web/bridges/mcp-app/use-mcp-app-context.test.d.ts +1 -0
  118. package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js +66 -0
  119. package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js.map +1 -0
  120. package/dist/web/bridges/types.d.ts +98 -0
  121. package/dist/web/bridges/types.js +2 -0
  122. package/dist/web/bridges/types.js.map +1 -0
  123. package/dist/web/bridges/use-host-context.d.ts +2 -0
  124. package/dist/web/bridges/use-host-context.js +8 -0
  125. package/dist/web/bridges/use-host-context.js.map +1 -0
  126. package/dist/web/components/modal-provider.d.ts +4 -0
  127. package/dist/web/components/modal-provider.js +47 -0
  128. package/dist/web/components/modal-provider.js.map +1 -0
  129. package/dist/web/create-store.d.ts +3 -0
  130. package/dist/web/create-store.js +24 -0
  131. package/dist/web/create-store.js.map +1 -0
  132. package/dist/web/create-store.test.d.ts +1 -0
  133. package/dist/web/create-store.test.js +126 -0
  134. package/dist/web/create-store.test.js.map +1 -0
  135. package/dist/web/data-llm.d.ts +14 -0
  136. package/dist/web/data-llm.js +72 -0
  137. package/dist/web/data-llm.js.map +1 -0
  138. package/dist/web/data-llm.test.d.ts +1 -0
  139. package/dist/web/data-llm.test.js +141 -0
  140. package/dist/web/data-llm.test.js.map +1 -0
  141. package/dist/web/generate-helpers.d.ts +116 -0
  142. package/dist/web/generate-helpers.js +111 -0
  143. package/dist/web/generate-helpers.js.map +1 -0
  144. package/dist/web/generate-helpers.test-d.d.ts +1 -0
  145. package/dist/web/generate-helpers.test-d.js +209 -0
  146. package/dist/web/generate-helpers.test-d.js.map +1 -0
  147. package/dist/web/generate-helpers.test.d.ts +1 -0
  148. package/dist/web/generate-helpers.test.js +17 -0
  149. package/dist/web/generate-helpers.test.js.map +1 -0
  150. package/dist/web/helpers/state.d.ts +7 -0
  151. package/dist/web/helpers/state.js +45 -0
  152. package/dist/web/helpers/state.js.map +1 -0
  153. package/dist/web/helpers/state.test.d.ts +1 -0
  154. package/dist/web/helpers/state.test.js +53 -0
  155. package/dist/web/helpers/state.test.js.map +1 -0
  156. package/dist/web/hooks/index.d.ts +11 -0
  157. package/dist/web/hooks/index.js +12 -0
  158. package/dist/web/hooks/index.js.map +1 -0
  159. package/dist/web/hooks/test/utils.d.ts +16 -0
  160. package/dist/web/hooks/test/utils.js +60 -0
  161. package/dist/web/hooks/test/utils.js.map +1 -0
  162. package/dist/web/hooks/use-call-tool.d.ts +101 -0
  163. package/dist/web/hooks/use-call-tool.js +68 -0
  164. package/dist/web/hooks/use-call-tool.js.map +1 -0
  165. package/dist/web/hooks/use-call-tool.test-d.d.ts +1 -0
  166. package/dist/web/hooks/use-call-tool.test-d.js +104 -0
  167. package/dist/web/hooks/use-call-tool.test-d.js.map +1 -0
  168. package/dist/web/hooks/use-call-tool.test.d.ts +1 -0
  169. package/dist/web/hooks/use-call-tool.test.js +190 -0
  170. package/dist/web/hooks/use-call-tool.test.js.map +1 -0
  171. package/dist/web/hooks/use-display-mode.d.ts +4 -0
  172. package/dist/web/hooks/use-display-mode.js +9 -0
  173. package/dist/web/hooks/use-display-mode.js.map +1 -0
  174. package/dist/web/hooks/use-display-mode.test.d.ts +1 -0
  175. package/dist/web/hooks/use-display-mode.test.js +41 -0
  176. package/dist/web/hooks/use-display-mode.test.js.map +1 -0
  177. package/dist/web/hooks/use-files.d.ts +6 -0
  178. package/dist/web/hooks/use-files.js +9 -0
  179. package/dist/web/hooks/use-files.js.map +1 -0
  180. package/dist/web/hooks/use-files.test.d.ts +1 -0
  181. package/dist/web/hooks/use-files.test.js +34 -0
  182. package/dist/web/hooks/use-files.test.js.map +1 -0
  183. package/dist/web/hooks/use-layout.d.ts +22 -0
  184. package/dist/web/hooks/use-layout.js +23 -0
  185. package/dist/web/hooks/use-layout.js.map +1 -0
  186. package/dist/web/hooks/use-layout.test.d.ts +1 -0
  187. package/dist/web/hooks/use-layout.test.js +96 -0
  188. package/dist/web/hooks/use-layout.test.js.map +1 -0
  189. package/dist/web/hooks/use-open-external.d.ts +1 -0
  190. package/dist/web/hooks/use-open-external.js +8 -0
  191. package/dist/web/hooks/use-open-external.js.map +1 -0
  192. package/dist/web/hooks/use-open-external.test.d.ts +1 -0
  193. package/dist/web/hooks/use-open-external.test.js +50 -0
  194. package/dist/web/hooks/use-open-external.test.js.map +1 -0
  195. package/dist/web/hooks/use-request-modal.d.ts +9 -0
  196. package/dist/web/hooks/use-request-modal.js +16 -0
  197. package/dist/web/hooks/use-request-modal.js.map +1 -0
  198. package/dist/web/hooks/use-request-modal.test.d.ts +1 -0
  199. package/dist/web/hooks/use-request-modal.test.js +57 -0
  200. package/dist/web/hooks/use-request-modal.test.js.map +1 -0
  201. package/dist/web/hooks/use-send-follow-up-message.d.ts +1 -0
  202. package/dist/web/hooks/use-send-follow-up-message.js +8 -0
  203. package/dist/web/hooks/use-send-follow-up-message.js.map +1 -0
  204. package/dist/web/hooks/use-set-open-in-app-url.d.ts +1 -0
  205. package/dist/web/hooks/use-set-open-in-app-url.js +8 -0
  206. package/dist/web/hooks/use-set-open-in-app-url.js.map +1 -0
  207. package/dist/web/hooks/use-set-open-in-app-url.test.d.ts +1 -0
  208. package/dist/web/hooks/use-set-open-in-app-url.test.js +43 -0
  209. package/dist/web/hooks/use-set-open-in-app-url.test.js.map +1 -0
  210. package/dist/web/hooks/use-tool-info.d.ts +36 -0
  211. package/dist/web/hooks/use-tool-info.js +26 -0
  212. package/dist/web/hooks/use-tool-info.js.map +1 -0
  213. package/dist/web/hooks/use-tool-info.test-d.d.ts +1 -0
  214. package/dist/web/hooks/use-tool-info.test-d.js +109 -0
  215. package/dist/web/hooks/use-tool-info.test-d.js.map +1 -0
  216. package/dist/web/hooks/use-tool-info.test.d.ts +1 -0
  217. package/dist/web/hooks/use-tool-info.test.js +130 -0
  218. package/dist/web/hooks/use-tool-info.test.js.map +1 -0
  219. package/dist/web/hooks/use-user.d.ts +18 -0
  220. package/dist/web/hooks/use-user.js +19 -0
  221. package/dist/web/hooks/use-user.js.map +1 -0
  222. package/dist/web/hooks/use-user.test.d.ts +1 -0
  223. package/dist/web/hooks/use-user.test.js +94 -0
  224. package/dist/web/hooks/use-user.test.js.map +1 -0
  225. package/dist/web/hooks/use-widget-state.d.ts +4 -0
  226. package/dist/web/hooks/use-widget-state.js +32 -0
  227. package/dist/web/hooks/use-widget-state.js.map +1 -0
  228. package/dist/web/hooks/use-widget-state.test.d.ts +1 -0
  229. package/dist/web/hooks/use-widget-state.test.js +62 -0
  230. package/dist/web/hooks/use-widget-state.test.js.map +1 -0
  231. package/dist/web/index.d.ts +7 -3
  232. package/dist/web/index.js +7 -3
  233. package/dist/web/index.js.map +1 -1
  234. package/dist/web/mount-widget.js +20 -3
  235. package/dist/web/mount-widget.js.map +1 -1
  236. package/dist/web/plugin/data-llm.test.d.ts +1 -0
  237. package/dist/web/plugin/data-llm.test.js +81 -0
  238. package/dist/web/plugin/data-llm.test.js.map +1 -0
  239. package/dist/web/plugin/plugin.d.ts +2 -0
  240. package/dist/web/plugin/plugin.js +46 -0
  241. package/dist/web/plugin/plugin.js.map +1 -0
  242. package/dist/web/plugin/transform-data-llm.d.ts +12 -0
  243. package/dist/web/plugin/transform-data-llm.js +96 -0
  244. package/dist/web/plugin/transform-data-llm.js.map +1 -0
  245. package/dist/web/plugin/transform-data-llm.test.d.ts +1 -0
  246. package/dist/web/plugin/transform-data-llm.test.js +81 -0
  247. package/dist/web/plugin/transform-data-llm.test.js.map +1 -0
  248. package/dist/web/proxy.d.ts +1 -0
  249. package/dist/web/proxy.js +52 -0
  250. package/dist/web/proxy.js.map +1 -0
  251. package/dist/web/types.d.ts +13 -92
  252. package/dist/web/types.js +1 -9
  253. package/dist/web/types.js.map +1 -1
  254. package/package.json +69 -20
  255. package/tsconfig.base.json +28 -0
  256. package/dist/server/middleware.d.ts +0 -3
  257. package/dist/server/middleware.js +0 -47
  258. package/dist/server/middleware.js.map +0 -1
  259. package/dist/web/use-openai-global.d.ts +0 -2
  260. package/dist/web/use-openai-global.js +0 -21
  261. package/dist/web/use-openai-global.js.map +0 -1
  262. package/dist/web/use-tool-output.d.ts +0 -3
  263. package/dist/web/use-tool-output.js +0 -5
  264. package/dist/web/use-tool-output.js.map +0 -1
@@ -0,0 +1,64 @@
1
+ import type { McpServerTypes, ToolDef } from "./server.js";
2
+ /**
3
+ * Any tool registry shape (includes both widgets and regular tools).
4
+ * Used as a constraint for type parameters that accept tool registries.
5
+ */
6
+ export type AnyToolRegistry = Record<string, ToolDef>;
7
+ /**
8
+ * Extract the tool registry type from an McpServer instance.
9
+ * This includes both widgets (registered via widget()) and regular tools (registered via registerTool()).
10
+ *
11
+ * Uses the `$types` property pattern for cross-package type inference.
12
+ * This works across package boundaries because TypeScript uses structural typing
13
+ * on the shape of `$types`, rather than nominal typing on the McpServer class itself.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * type MyTools = InferTools<MyServer>;
18
+ * // { "search": ToolDef<...>, "calculate": ToolDef<...> }
19
+ * ```
20
+ */
21
+ export type InferTools<ServerType> = ServerType extends {
22
+ $types: McpServerTypes<infer W>;
23
+ } ? W : never;
24
+ type ExtractTool<ServerType, K extends ToolNames<ServerType>> = InferTools<ServerType>[K];
25
+ /**
26
+ * Get a union of all tool names from an McpServer instance.
27
+ * This includes both widgets and regular tools.
28
+ *
29
+ * @example
30
+ * ```ts
31
+ * type Names = ToolNames<MyServer>;
32
+ * // "search" | "calculate" | "details"
33
+ * ```
34
+ */
35
+ export type ToolNames<ServerType> = keyof InferTools<ServerType> & string;
36
+ /**
37
+ * Get the input type for a specific tool (widget or regular tool).
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * type SearchInput = ToolInput<MyServer, "search">;
42
+ * ```
43
+ */
44
+ export type ToolInput<ServerType, ToolName extends ToolNames<ServerType>> = ExtractTool<ServerType, ToolName>["input"];
45
+ /**
46
+ * Get the output type for a specific tool (widget or regular tool).
47
+ *
48
+ * @example
49
+ * ```ts
50
+ * type SearchOutput = ToolOutput<MyServer, "search">;
51
+ * ```
52
+ */
53
+ export type ToolOutput<ServerType, ToolName extends ToolNames<ServerType>> = ExtractTool<ServerType, ToolName>["output"];
54
+ /**
55
+ * Get the responseMetadata type for a specific tool (widget or regular tool).
56
+ * This is inferred from the `_meta` property of the tool callback's return value.
57
+ *
58
+ * @example
59
+ * ```ts
60
+ * type SearchMeta = ToolResponseMetadata<MyServer, "search">;
61
+ * ```
62
+ */
63
+ export type ToolResponseMetadata<ServerType, ToolName extends ToolNames<ServerType>> = ExtractTool<ServerType, ToolName>["responseMetadata"];
64
+ export {};
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=inferUtilityTypes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inferUtilityTypes.js","sourceRoot":"","sources":["../../src/server/inferUtilityTypes.ts"],"names":[],"mappings":""}
@@ -1,12 +1,105 @@
1
- import { McpServer as McpServerBase, type ToolCallback } from "@modelcontextprotocol/sdk/server/mcp.js";
2
- import type { Resource } from "@modelcontextprotocol/sdk/types.js";
3
- import type { ZodRawShape } from "zod";
4
- type McpServerOriginalResourceConfig = Omit<Resource, "uri" | "name" | "mimeType">;
5
- type McpServerOriginalToolConfig = Omit<Parameters<McpServer["registerTool"]>[1], "inputSchema" | "outputSchema">;
6
- export declare class McpServer extends McpServerBase {
7
- widget<InputArgs extends ZodRawShape, OutputArgs extends ZodRawShape>(name: string, resourceConfig: McpServerOriginalResourceConfig, toolConfig: McpServerOriginalToolConfig & {
8
- inputSchema?: InputArgs;
9
- outputSchema?: OutputArgs;
10
- }, toolCallback: ToolCallback<InputArgs>): void;
1
+ import type { McpUiResourceMeta } from "@modelcontextprotocol/ext-apps";
2
+ import { McpServer as McpServerBase, type RegisteredTool } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import type { AnySchema, SchemaOutput, ZodRawShapeCompat } from "@modelcontextprotocol/sdk/server/zod-compat.js";
4
+ import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
5
+ import type { CallToolResult, Resource, ServerNotification, ServerRequest, ToolAnnotations } from "@modelcontextprotocol/sdk/types.js";
6
+ import type { RequestHandler } from "express";
7
+ export type ToolDef<TInput = unknown, TOutput = unknown, TResponseMetadata = unknown> = {
8
+ input: TInput;
9
+ output: TOutput;
10
+ responseMetadata: TResponseMetadata;
11
+ };
12
+ /**
13
+ * Extended MCP Apps CSP with upcoming fields from ext-apps PR #158
14
+ * and Skybridge-specific fields for OpenAI compatibility
15
+ * @see https://github.com/modelcontextprotocol/ext-apps/pull/158
16
+ */
17
+ type ExtendedMcpUiResourceCsp = McpUiResourceMeta["csp"] & {
18
+ /**
19
+ * Origins that can receive openExternal redirects without safe-link modal (OpenAI-specific)
20
+ * @see https://developers.openai.com/apps-sdk/reference#component-resource-_meta-fields
21
+ */
22
+ redirectDomains?: string[];
23
+ };
24
+ /** Extended MCP Apps resource metadata with upcoming CSP fields */
25
+ type ExtendedMcpUiResourceMeta = Omit<McpUiResourceMeta, "csp"> & {
26
+ csp?: ExtendedMcpUiResourceCsp;
27
+ };
28
+ /** User-provided resource configuration with optional CSP override */
29
+ export type WidgetResourceMeta = {
30
+ ui?: ExtendedMcpUiResourceMeta;
31
+ } & Resource["_meta"];
32
+ export type WidgetHostType = "apps-sdk" | "mcp-app";
33
+ type McpServerOriginalResourceConfig = Omit<Resource, "uri" | "name" | "mimeType" | "_meta"> & {
34
+ _meta?: WidgetResourceMeta;
35
+ /** Restrict host types to a specific subset */
36
+ hosts?: WidgetHostType[];
37
+ };
38
+ type McpServerOriginalToolConfig = Omit<Parameters<typeof McpServerBase.prototype.registerTool<ZodRawShapeCompat, ZodRawShapeCompat>>[1], "inputSchema" | "outputSchema">;
39
+ type Simplify<T> = {
40
+ [K in keyof T]: T[K];
41
+ };
42
+ type ExtractStructuredContent<T> = T extends {
43
+ structuredContent: infer SC;
44
+ } ? Simplify<SC> : never;
45
+ type ExtractMeta<T> = [Extract<T, {
46
+ _meta: unknown;
47
+ }>] extends [never] ? unknown : Extract<T, {
48
+ _meta: unknown;
49
+ }> extends {
50
+ _meta: infer M;
51
+ } ? Simplify<M> : unknown;
52
+ /**
53
+ * Type-level marker interface for cross-package type inference.
54
+ * This enables TypeScript to infer tool types across package boundaries
55
+ * using structural typing on the $types property, rather than relying on
56
+ * class generic inference which fails when McpServer comes from different
57
+ * package installations.
58
+ *
59
+ * Inspired by tRPC's _def pattern and Hono's type markers.
60
+ */
61
+ export interface McpServerTypes<TTools extends Record<string, ToolDef>> {
62
+ readonly tools: TTools;
63
+ }
64
+ type ShapeOutput<Shape extends ZodRawShapeCompat> = Simplify<{
65
+ [K in keyof Shape as undefined extends SchemaOutput<Shape[K]> ? never : K]: SchemaOutput<Shape[K]>;
66
+ } & {
67
+ [K in keyof Shape as undefined extends SchemaOutput<Shape[K]> ? K : never]?: SchemaOutput<Shape[K]>;
68
+ }>;
69
+ type AddTool<TTools, TName extends string, TInput extends ZodRawShapeCompat, TOutput, TResponseMetadata = unknown> = McpServer<TTools & {
70
+ [K in TName]: ToolDef<ShapeOutput<TInput>, TOutput, TResponseMetadata>;
71
+ }>;
72
+ type ToolConfig<TInput extends ZodRawShapeCompat | AnySchema> = {
73
+ title?: string;
74
+ description?: string;
75
+ inputSchema?: TInput;
76
+ outputSchema?: ZodRawShapeCompat | AnySchema;
77
+ annotations?: ToolAnnotations;
78
+ _meta?: Record<string, unknown>;
79
+ };
80
+ type ToolHandler<TInput extends ZodRawShapeCompat, TReturn extends {
81
+ content: CallToolResult["content"];
82
+ } = CallToolResult> = (args: ShapeOutput<TInput>, extra: RequestHandlerExtra<ServerRequest, ServerNotification>) => TReturn | Promise<TReturn>;
83
+ export declare class McpServer<TTools extends Record<string, ToolDef> = Record<never, ToolDef>> extends McpServerBase {
84
+ readonly $types: McpServerTypes<TTools>;
85
+ private express?;
86
+ private customMiddleware;
87
+ use(...handlers: RequestHandler[]): this;
88
+ use(path: string, ...handlers: RequestHandler[]): this;
89
+ run(): Promise<void>;
90
+ registerWidget<TName extends string, TInput extends ZodRawShapeCompat, TReturn extends {
91
+ content: CallToolResult["content"];
92
+ }>(name: TName, resourceConfig: McpServerOriginalResourceConfig, toolConfig: McpServerOriginalToolConfig & {
93
+ inputSchema?: TInput;
94
+ outputSchema?: ZodRawShapeCompat | AnySchema;
95
+ }, toolCallback: ToolHandler<TInput, TReturn>): AddTool<TTools, TName, TInput, ExtractStructuredContent<TReturn>, ExtractMeta<TReturn>>;
96
+ registerTool<TName extends string, InputArgs extends ZodRawShapeCompat, TReturn extends {
97
+ content: CallToolResult["content"];
98
+ }>(name: TName, config: ToolConfig<InputArgs>, cb: ToolHandler<InputArgs, TReturn>): AddTool<TTools, TName, InputArgs, ExtractStructuredContent<TReturn>, ExtractMeta<TReturn>>;
99
+ registerTool<InputArgs extends ZodRawShapeCompat>(name: string, config: ToolConfig<InputArgs>, cb: ToolHandler<InputArgs>): RegisteredTool;
100
+ private registerWidgetResource;
101
+ private lookupDistFile;
102
+ private lookupDistFileWithIndexFallback;
103
+ private readManifest;
11
104
  }
12
105
  export {};
@@ -1,70 +1,204 @@
1
- import { McpServer as McpServerBase } from "@modelcontextprotocol/sdk/server/mcp.js";
1
+ import crypto from "node:crypto";
2
+ import { readFileSync } from "node:fs";
3
+ import http from "node:http";
4
+ import path from "node:path";
5
+ import { McpServer as McpServerBase, } from "@modelcontextprotocol/sdk/server/mcp.js";
6
+ import { mergeWith, union } from "es-toolkit";
7
+ import { DEFAULT_HMR_PORT } from "./const.js";
8
+ import { createServer } from "./express.js";
9
+ import { templateHelper } from "./templateHelper.js";
10
+ const mergeWithUnion = (target, source) => {
11
+ return mergeWith(target, source, (targetVal, sourceVal) => {
12
+ if (Array.isArray(targetVal) && Array.isArray(sourceVal)) {
13
+ return union(targetVal, sourceVal);
14
+ }
15
+ });
16
+ };
2
17
  export class McpServer extends McpServerBase {
3
- widget(name, resourceConfig, toolConfig, toolCallback) {
4
- const uri = `ui://widgets/${name}.html`;
5
- const resourceMetadata = { ...(resourceConfig._meta ?? {}) };
6
- if (toolConfig.description !== undefined) {
7
- resourceMetadata["openai/widgetDescription"] = toolConfig.description;
18
+ express;
19
+ customMiddleware = [];
20
+ use(pathOrHandler, ...handlers) {
21
+ if (typeof pathOrHandler === "string") {
22
+ this.customMiddleware.push({
23
+ path: pathOrHandler,
24
+ handlers,
25
+ });
8
26
  }
9
- this.resource(name, uri, {
10
- ...resourceConfig,
11
- _meta: resourceMetadata,
12
- }, async (_uri, extra) => {
13
- const serverUrl = process.env.NODE_ENV === "production"
14
- ? `https://${extra?.requestInfo?.headers?.host}`
15
- : `http://localhost:3000`;
16
- const injectViteClient = (html) => `
17
- <script type="module">import { injectIntoGlobalHook } from "${serverUrl}/@react-refresh";
18
- injectIntoGlobalHook(window);
19
- window.$RefreshReg$ = () => {};
20
- window.$RefreshSig$ = () => (type) => type;
21
- window.__vite_plugin_react_preamble_installed__ = true;
22
- </script>
23
-
24
- <script type="module" src="${serverUrl}/@vite/client"></script>
25
- ` + html;
26
- const buildHtml = () => {
27
- if (process.env.NODE_ENV === "production") {
28
- try {
29
- return `
30
- <div id="root"></div>
31
- <script type="module">
32
- import('${serverUrl}/assets/${name}.js');
33
- </script>
34
- <link rel="stylesheet" crossorigin href="${serverUrl}/assets/style.css">
35
- `;
36
- }
37
- catch (error) {
38
- console.error("Failed to load production assets:", error);
39
- return "";
40
- }
41
- }
42
- return `
43
- <div id="root"></div>
44
- <script type="module">
45
- import('${serverUrl}/src/widgets/${name}.tsx');
46
- </script>
47
- `;
48
- };
49
- const html = buildHtml();
50
- return {
51
- contents: [
52
- {
53
- uri,
54
- mimeType: "text/html+skybridge",
55
- text: process.env.NODE_ENV === "production" ? html : injectViteClient(html),
56
- },
57
- ],
58
- };
27
+ else {
28
+ this.customMiddleware.push({
29
+ handlers: [pathOrHandler, ...handlers],
30
+ });
31
+ }
32
+ return this;
33
+ }
34
+ async run() {
35
+ if (!this.express) {
36
+ this.express = await createServer({
37
+ server: this,
38
+ customMiddleware: this.customMiddleware,
39
+ });
40
+ }
41
+ const express = this.express;
42
+ return new Promise((resolve, reject) => {
43
+ const server = http.createServer(express);
44
+ server.on("error", (error) => {
45
+ console.error("Failed to start server:", error);
46
+ reject(error);
47
+ });
48
+ const port = parseInt(process.env.__PORT ?? "3000", 10);
49
+ server.listen(port, () => {
50
+ resolve();
51
+ });
59
52
  });
53
+ }
54
+ registerWidget(name, resourceConfig, toolConfig, toolCallback) {
55
+ const userMeta = resourceConfig._meta;
60
56
  const toolMeta = {
61
57
  ...toolConfig._meta,
62
- "openai/outputTemplate": uri,
63
58
  };
59
+ if (!resourceConfig.hosts || resourceConfig.hosts.includes("apps-sdk")) {
60
+ const widgetConfig = {
61
+ hostType: "apps-sdk",
62
+ uri: `ui://widgets/apps-sdk/${name}.html`,
63
+ mimeType: "text/html+skybridge",
64
+ buildContentMeta: ({ resourceDomains, connectDomains, domain }, overrides) => {
65
+ const userUi = userMeta?.ui;
66
+ const userCsp = userUi?.csp;
67
+ const defaults = {
68
+ "openai/widgetCSP": {
69
+ resource_domains: resourceDomains,
70
+ connect_domains: connectDomains,
71
+ },
72
+ "openai/widgetDomain": domain,
73
+ "openai/widgetDescription": resourceConfig.description,
74
+ };
75
+ const fromUi = {
76
+ "openai/widgetCSP": {
77
+ resource_domains: userCsp?.resourceDomains,
78
+ connect_domains: userCsp?.connectDomains,
79
+ frame_domains: userCsp?.frameDomains,
80
+ redirect_domains: userCsp?.redirectDomains,
81
+ },
82
+ "openai/widgetDomain": userUi?.domain,
83
+ "openai/widgetPrefersBorder": userUi?.prefersBorder,
84
+ };
85
+ const directOpenaiKeys = Object.fromEntries(Object.entries(userMeta ?? {}).filter(([key]) => key.startsWith("openai/")));
86
+ return mergeWithUnion(mergeWithUnion(mergeWithUnion(defaults, fromUi), directOpenaiKeys), { "openai/widgetDomain": overrides.domain });
87
+ },
88
+ };
89
+ this.registerWidgetResource({
90
+ name,
91
+ widgetConfig,
92
+ resourceConfig,
93
+ });
94
+ toolMeta["openai/outputTemplate"] = widgetConfig.uri;
95
+ }
96
+ if (!resourceConfig.hosts || resourceConfig.hosts.includes("mcp-app")) {
97
+ const widgetConfig = {
98
+ hostType: "mcp-app",
99
+ uri: `ui://widgets/ext-apps/${name}.html`,
100
+ mimeType: "text/html;profile=mcp-app",
101
+ buildContentMeta: ({ resourceDomains, connectDomains, domain }, overrides) => {
102
+ const defaults = {
103
+ ui: {
104
+ csp: {
105
+ resourceDomains,
106
+ connectDomains,
107
+ },
108
+ domain,
109
+ },
110
+ };
111
+ return mergeWithUnion(defaults, {
112
+ ui: { ...userMeta?.ui, ...overrides },
113
+ });
114
+ },
115
+ };
116
+ this.registerWidgetResource({
117
+ name,
118
+ widgetConfig,
119
+ resourceConfig,
120
+ });
121
+ // @ts-expect-error - For backwards compatibility with Claude current implementation of the specs
122
+ toolMeta["ui/resourceUri"] = widgetConfig.uri;
123
+ toolMeta.ui = { resourceUri: widgetConfig.uri };
124
+ }
64
125
  this.registerTool(name, {
65
126
  ...toolConfig,
66
127
  _meta: toolMeta,
67
128
  }, toolCallback);
129
+ return this;
130
+ }
131
+ registerTool(name, config, cb) {
132
+ super.registerTool(name, config, cb);
133
+ return this;
134
+ }
135
+ registerWidgetResource({ name, widgetConfig, resourceConfig, }) {
136
+ const { hostType, uri: widgetUri, mimeType, buildContentMeta, } = widgetConfig;
137
+ this.registerResource(name, widgetUri, { ...resourceConfig, _meta: resourceConfig._meta }, async (uri, extra) => {
138
+ const isProduction = process.env.NODE_ENV === "production";
139
+ const useForwardedHost = process.env.SKYBRIDGE_USE_FORWARDED_HOST === "true";
140
+ const isClaude = extra?.requestInfo?.headers?.["user-agent"] === "Claude-User";
141
+ const hostFromHeaders = extra?.requestInfo?.headers?.["x-forwarded-host"] ??
142
+ extra?.requestInfo?.headers?.host;
143
+ const useExternalHost = isProduction || useForwardedHost || isClaude;
144
+ const devPort = process.env.__PORT || "3000";
145
+ const serverUrl = useExternalHost
146
+ ? `https://${hostFromHeaders}`
147
+ : `http://localhost:${devPort}`;
148
+ const html = isProduction
149
+ ? templateHelper.renderProduction({
150
+ hostType,
151
+ serverUrl,
152
+ widgetFile: this.lookupDistFileWithIndexFallback(`src/widgets/${name}`),
153
+ styleFile: this.lookupDistFile("style.css"),
154
+ })
155
+ : templateHelper.renderDevelopment({
156
+ hostType,
157
+ serverUrl,
158
+ useLocalNetworkAccess: !useExternalHost,
159
+ widgetName: name,
160
+ });
161
+ const connectDomains = [serverUrl];
162
+ if (!isProduction) {
163
+ const hmrPort = process.env.__SKYBRIDGE_HMR_PORT ?? DEFAULT_HMR_PORT;
164
+ const VITE_HMR_WEBSOCKET_DEFAULT_URL = `ws://localhost:${hmrPort}`;
165
+ connectDomains.push(VITE_HMR_WEBSOCKET_DEFAULT_URL);
166
+ }
167
+ const contentMetaOverrides = isClaude
168
+ ? {
169
+ domain: `${crypto
170
+ .createHash("sha256")
171
+ .update(extra.requestInfo?.url?.href ||
172
+ `https://${hostFromHeaders}/mcp`)
173
+ .digest("hex")
174
+ .slice(0, 32)}.claudemcpcontent.com`,
175
+ }
176
+ : {};
177
+ const contentMeta = buildContentMeta({
178
+ resourceDomains: [serverUrl],
179
+ connectDomains,
180
+ domain: serverUrl,
181
+ baseUriDomains: [serverUrl],
182
+ }, contentMetaOverrides);
183
+ return {
184
+ contents: [
185
+ { uri: uri.href, mimeType, text: html, _meta: contentMeta },
186
+ ],
187
+ };
188
+ });
189
+ }
190
+ lookupDistFile(key) {
191
+ const manifest = this.readManifest();
192
+ return manifest[key]?.file;
193
+ }
194
+ lookupDistFileWithIndexFallback(basePath) {
195
+ const manifest = this.readManifest();
196
+ const flatFileKey = `${basePath}.tsx`;
197
+ const indexFileKey = `${basePath}/index.tsx`;
198
+ return manifest[flatFileKey]?.file ?? manifest[indexFileKey]?.file;
199
+ }
200
+ readManifest() {
201
+ return JSON.parse(readFileSync(path.join(process.cwd(), "dist", "assets", ".vite", "manifest.json"), "utf-8"));
68
202
  }
69
203
  }
70
204
  //# sourceMappingURL=server.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,IAAI,aAAa,EAAqB,MAAM,yCAAyC,CAAC;AAwBxG,MAAM,OAAO,SAAU,SAAQ,aAAa;IAC1C,MAAM,CACJ,IAAY,EACZ,cAA+C,EAC/C,UAGC,EACD,YAAqC;QAErC,MAAM,GAAG,GAAG,gBAAgB,IAAI,OAAO,CAAC;QACxC,MAAM,gBAAgB,GAAiB,EAAE,GAAG,CAAC,cAAc,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC;QAC3E,IAAI,UAAU,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;YACzC,gBAAgB,CAAC,0BAA0B,CAAC,GAAG,UAAU,CAAC,WAAW,CAAC;QACxE,CAAC;QAED,IAAI,CAAC,QAAQ,CACX,IAAI,EACJ,GAAG,EACH;YACE,GAAG,cAAc;YACjB,KAAK,EAAE,gBAAgB;SACxB,EACD,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE;YACpB,MAAM,SAAS,GACb,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY;gBACnC,CAAC,CAAC,WAAW,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE;gBAChD,CAAC,CAAC,uBAAuB,CAAC;YAE9B,MAAM,gBAAgB,GAAG,CAAC,IAAY,EAAE,EAAE,CACxC;0EACgE,SAAS;;;;;;;yCAO1C,SAAS;SACzC,GAAG,IAAI,CAAC;YAET,MAAM,SAAS,GAAG,GAAG,EAAE;gBACrB,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;oBAC1C,IAAI,CAAC;wBACH,OAAO;;;4BAGO,SAAS,WAAW,IAAI;;2DAEO,SAAS;eACrD,CAAC;oBACJ,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACf,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,KAAK,CAAC,CAAC;wBAC1D,OAAO,EAAE,CAAC;oBACZ,CAAC;gBACH,CAAC;gBAED,OAAO;;;wBAGO,SAAS,gBAAgB,IAAI;;WAE1C,CAAC;YACJ,CAAC,CAAC;YAEF,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;YAEzB,OAAO;gBACL,QAAQ,EAAE;oBACR;wBACE,GAAG;wBACH,QAAQ,EAAE,qBAAqB;wBAC/B,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC;qBAC5E;iBACF;aACF,CAAC;QACJ,CAAC,CACF,CAAC;QAEF,MAAM,QAAQ,GAAa;YACzB,GAAG,UAAU,CAAC,KAAK;YACnB,uBAAuB,EAAE,GAAG;SAC7B,CAAC;QAEF,IAAI,CAAC,YAAY,CACf,IAAI,EACJ;YACE,GAAG,UAAU;YACb,KAAK,EAAE,QAAQ;SAChB,EACD,YAAY,CACb,CAAC;IACJ,CAAC;CACF"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { WidgetHostType } from "./server.js";
2
+ declare class TemplateHelper {
3
+ private templateCache;
4
+ private loadTemplate;
5
+ renderProduction(data: {
6
+ hostType: WidgetHostType;
7
+ serverUrl: string;
8
+ widgetFile: string;
9
+ styleFile: string;
10
+ }): string;
11
+ renderDevelopment(data: {
12
+ hostType: WidgetHostType;
13
+ serverUrl: string;
14
+ useLocalNetworkAccess: boolean;
15
+ widgetName: string;
16
+ }): string;
17
+ }
18
+ export declare const templateHelper: TemplateHelper;
19
+ export {};
@@ -0,0 +1,30 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import Handlebars from "handlebars";
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = dirname(__filename);
7
+ class TemplateHelper {
8
+ templateCache = new Map();
9
+ loadTemplate(templateName) {
10
+ const cached = this.templateCache.get(templateName);
11
+ if (cached) {
12
+ return cached;
13
+ }
14
+ const templatePath = join(__dirname, "templates", `${templateName}.hbs`);
15
+ const templateSource = readFileSync(templatePath, "utf-8");
16
+ const template = Handlebars.compile(templateSource);
17
+ this.templateCache.set(templateName, template);
18
+ return template;
19
+ }
20
+ renderProduction(data) {
21
+ const template = this.loadTemplate("production");
22
+ return template(data);
23
+ }
24
+ renderDevelopment(data) {
25
+ const template = this.loadTemplate("development");
26
+ return template(data);
27
+ }
28
+ }
29
+ export const templateHelper = new TemplateHelper();
30
+ //# sourceMappingURL=templateHelper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templateHelper.js","sourceRoot":"","sources":["../../src/server/templateHelper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,UAAU,MAAM,YAAY,CAAC;AAGpC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,MAAM,cAAc;IACV,aAAa,GAAG,IAAI,GAAG,EAAsC,CAAC;IAE9D,YAAY,CAAC,YAAoB;QACvC,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QACpD,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,EAAE,WAAW,EAAE,GAAG,YAAY,MAAM,CAAC,CAAC;QACzE,MAAM,cAAc,GAAG,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAC3D,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QAEpD,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;QAC/C,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,gBAAgB,CAAC,IAKhB;QACC,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;QACjD,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAED,iBAAiB,CAAC,IAKjB;QACC,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;QAClD,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;CACF;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,cAAc,EAAE,CAAC"}
@@ -0,0 +1,67 @@
1
+ <script type="module">window.skybridge = { hostType: "{{hostType}}", serverUrl: "{{serverUrl}}" };</script>
2
+ <script type="module">
3
+ import { injectIntoGlobalHook } from "{{serverUrl}}/assets/@react-refresh";
4
+ injectIntoGlobalHook(window); window.$RefreshReg$ = () => {};
5
+ window.$RefreshSig$ = () => (type) => type;
6
+ window.__vite_plugin_react_preamble_installed__ = true;
7
+ </script>
8
+ <script type="module" src="{{serverUrl}}/@vite/client"></script>
9
+ {{#if useLocalNetworkAccess}}
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
+ {{/if}}
64
+ <div id="root"></div>
65
+ <script type="module" id="dev-widget-entry">
66
+ import('{{serverUrl}}/src/widgets/{{widgetName}}');
67
+ </script>
@@ -0,0 +1,6 @@
1
+ <script type="module">window.skybridge = { hostType: "{{hostType}}", serverUrl: "{{serverUrl}}" };</script>
2
+ <div id="root"></div>
3
+ <script type="module">
4
+ import('{{serverUrl}}/assets/{{widgetFile}}');
5
+ </script>
6
+ <link rel="stylesheet" crossorigin href="{{serverUrl}}/assets/{{styleFile}}" />
@@ -1,9 +1,12 @@
1
- import { type RequestHandler } from "express";
1
+ import { type Router } from "express";
2
2
  /**
3
- * Install Vite dev server when env is not production
3
+ * Install Vite dev server
4
4
  * This router MUST be installed at the application root, like so:
5
5
  *
6
6
  * const app = express();
7
- * app.use(await widgetsRouter());
7
+ *
8
+ * if (env.NODE_ENV !== "production") {
9
+ * app.use(await widgetsRouter());
10
+ * }
8
11
  */
9
- export declare const widgetsDevServer: () => Promise<RequestHandler>;
12
+ export declare const widgetsDevServer: () => Promise<Router>;