skybridge 0.0.0-dev.f1722d8 → 0.0.0-dev.f1a8f84

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 (442) hide show
  1. package/LICENSE +21 -674
  2. package/README.md +123 -342
  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/tunnel-control-server.d.ts +9 -0
  17. package/dist/cli/tunnel-control-server.js +31 -0
  18. package/dist/cli/tunnel-control-server.js.map +1 -0
  19. package/dist/cli/tunnel-control-server.test.js +39 -0
  20. package/dist/cli/tunnel-control-server.test.js.map +1 -0
  21. package/dist/cli/tunnel-handler.d.ts +3 -0
  22. package/dist/cli/tunnel-handler.js +48 -0
  23. package/dist/cli/tunnel-handler.js.map +1 -0
  24. package/dist/cli/tunnel-handler.test.js +105 -0
  25. package/dist/cli/tunnel-handler.test.js.map +1 -0
  26. package/dist/cli/tunnel.d.ts +57 -0
  27. package/dist/cli/tunnel.js +154 -0
  28. package/dist/cli/tunnel.js.map +1 -0
  29. package/dist/cli/tunnel.test.js +190 -0
  30. package/dist/cli/tunnel.test.js.map +1 -0
  31. package/dist/cli/types.d.ts +5 -0
  32. package/dist/cli/types.js +2 -0
  33. package/dist/cli/types.js.map +1 -0
  34. package/dist/cli/use-execute-steps.d.ts +11 -0
  35. package/dist/cli/use-execute-steps.js +36 -0
  36. package/dist/cli/use-execute-steps.js.map +1 -0
  37. package/dist/cli/use-messages.d.ts +3 -0
  38. package/dist/cli/use-messages.js +11 -0
  39. package/dist/cli/use-messages.js.map +1 -0
  40. package/dist/cli/use-nodemon.d.ts +2 -0
  41. package/dist/cli/use-nodemon.js +73 -0
  42. package/dist/cli/use-nodemon.js.map +1 -0
  43. package/dist/cli/use-open-browser.d.ts +1 -0
  44. package/dist/cli/use-open-browser.js +44 -0
  45. package/dist/cli/use-open-browser.js.map +1 -0
  46. package/dist/cli/use-tunnel.d.ts +14 -0
  47. package/dist/cli/use-tunnel.js +131 -0
  48. package/dist/cli/use-tunnel.js.map +1 -0
  49. package/dist/cli/use-typescript-check.d.ts +9 -0
  50. package/dist/cli/use-typescript-check.js +94 -0
  51. package/dist/cli/use-typescript-check.js.map +1 -0
  52. package/dist/commands/build.d.ts +9 -0
  53. package/dist/commands/build.js +102 -0
  54. package/dist/commands/build.js.map +1 -0
  55. package/dist/commands/create.d.ts +9 -0
  56. package/dist/commands/create.js +30 -0
  57. package/dist/commands/create.js.map +1 -0
  58. package/dist/commands/dev.d.ts +12 -0
  59. package/dist/commands/dev.js +80 -0
  60. package/dist/commands/dev.js.map +1 -0
  61. package/dist/commands/start.d.ts +9 -0
  62. package/dist/commands/start.js +49 -0
  63. package/dist/commands/start.js.map +1 -0
  64. package/dist/commands/telemetry/disable.d.ts +5 -0
  65. package/dist/commands/telemetry/disable.js +14 -0
  66. package/dist/commands/telemetry/disable.js.map +1 -0
  67. package/dist/commands/telemetry/enable.d.ts +5 -0
  68. package/dist/commands/telemetry/enable.js +14 -0
  69. package/dist/commands/telemetry/enable.js.map +1 -0
  70. package/dist/commands/telemetry/status.d.ts +5 -0
  71. package/dist/commands/telemetry/status.js +14 -0
  72. package/dist/commands/telemetry/status.js.map +1 -0
  73. package/dist/server/asset-base-url-transform-plugin.d.ts +11 -0
  74. package/dist/server/asset-base-url-transform-plugin.js +48 -0
  75. package/dist/server/asset-base-url-transform-plugin.js.map +1 -0
  76. package/dist/server/asset-base-url-transform-plugin.test.js +134 -0
  77. package/dist/server/asset-base-url-transform-plugin.test.js.map +1 -0
  78. package/dist/server/content-helpers.d.ts +27 -0
  79. package/dist/server/content-helpers.js +46 -0
  80. package/dist/server/content-helpers.js.map +1 -0
  81. package/dist/server/content-helpers.test.js +70 -0
  82. package/dist/server/content-helpers.test.js.map +1 -0
  83. package/dist/server/express.d.ts +11 -0
  84. package/dist/server/express.js +101 -0
  85. package/dist/server/express.js.map +1 -0
  86. package/dist/server/express.test.js +430 -0
  87. package/dist/server/express.test.js.map +1 -0
  88. package/dist/server/file-ref.d.ts +8 -0
  89. package/dist/server/file-ref.js +8 -0
  90. package/dist/server/file-ref.js.map +1 -0
  91. package/dist/server/index.d.ts +7 -0
  92. package/dist/server/index.js +5 -0
  93. package/dist/server/index.js.map +1 -0
  94. package/dist/{src/server → server}/inferUtilityTypes.d.ts +15 -5
  95. package/dist/server/inferUtilityTypes.js.map +1 -0
  96. package/dist/server/metric.d.ts +14 -0
  97. package/dist/server/metric.js +62 -0
  98. package/dist/server/metric.js.map +1 -0
  99. package/dist/server/middleware.d.ts +124 -0
  100. package/dist/server/middleware.js +93 -0
  101. package/dist/server/middleware.js.map +1 -0
  102. package/dist/server/middleware.test-d.js +75 -0
  103. package/dist/server/middleware.test-d.js.map +1 -0
  104. package/dist/server/middleware.test.js +493 -0
  105. package/dist/server/middleware.test.js.map +1 -0
  106. package/dist/server/server.d.ts +199 -0
  107. package/dist/server/server.js +468 -0
  108. package/dist/server/server.js.map +1 -0
  109. package/dist/{src/server → server}/templateHelper.d.ts +5 -4
  110. package/dist/server/templateHelper.js +11 -0
  111. package/dist/server/templateHelper.js.map +1 -0
  112. package/dist/server/templates.generated.d.ts +4 -0
  113. package/dist/server/templates.generated.js +47 -0
  114. package/dist/server/templates.generated.js.map +1 -0
  115. package/dist/server/tunnel-proxy-router.d.ts +7 -0
  116. package/dist/server/tunnel-proxy-router.js +110 -0
  117. package/dist/server/tunnel-proxy-router.js.map +1 -0
  118. package/dist/server/tunnel-proxy-router.test.js +229 -0
  119. package/dist/server/tunnel-proxy-router.test.js.map +1 -0
  120. package/dist/server/viewsDevServer.d.ts +14 -0
  121. package/dist/server/viewsDevServer.js +45 -0
  122. package/dist/server/viewsDevServer.js.map +1 -0
  123. package/dist/test/utils.d.ts +127 -0
  124. package/dist/test/utils.js +247 -0
  125. package/dist/test/utils.js.map +1 -0
  126. package/dist/test/view.test.js +523 -0
  127. package/dist/test/view.test.js.map +1 -0
  128. package/dist/version.d.ts +1 -0
  129. package/dist/version.js +3 -0
  130. package/dist/version.js.map +1 -0
  131. package/dist/web/bridges/apps-sdk/adaptor.d.ts +26 -0
  132. package/dist/web/bridges/apps-sdk/adaptor.js +108 -0
  133. package/dist/web/bridges/apps-sdk/adaptor.js.map +1 -0
  134. package/dist/web/bridges/apps-sdk/bridge.d.ts +10 -0
  135. package/dist/web/bridges/apps-sdk/bridge.js +46 -0
  136. package/dist/web/bridges/apps-sdk/bridge.js.map +1 -0
  137. package/dist/web/bridges/apps-sdk/index.d.ts +5 -0
  138. package/dist/web/bridges/apps-sdk/index.js +5 -0
  139. package/dist/web/bridges/apps-sdk/index.js.map +1 -0
  140. package/dist/web/bridges/apps-sdk/types.d.ts +133 -0
  141. package/dist/{src/web → web/bridges/apps-sdk}/types.js +0 -1
  142. package/dist/web/bridges/apps-sdk/types.js.map +1 -0
  143. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.d.ts +2 -0
  144. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js +7 -0
  145. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js.map +1 -0
  146. package/dist/web/bridges/get-adaptor.d.ts +2 -0
  147. package/dist/web/bridges/get-adaptor.js +8 -0
  148. package/dist/web/bridges/get-adaptor.js.map +1 -0
  149. package/dist/web/bridges/index.d.ts +5 -0
  150. package/dist/web/bridges/index.js +6 -0
  151. package/dist/web/bridges/index.js.map +1 -0
  152. package/dist/web/bridges/mcp-app/adaptor.d.ts +50 -0
  153. package/dist/web/bridges/mcp-app/adaptor.js +271 -0
  154. package/dist/web/bridges/mcp-app/adaptor.js.map +1 -0
  155. package/dist/web/bridges/mcp-app/bridge.d.ts +26 -0
  156. package/dist/web/bridges/mcp-app/bridge.js +102 -0
  157. package/dist/web/bridges/mcp-app/bridge.js.map +1 -0
  158. package/dist/web/bridges/mcp-app/index.d.ts +4 -0
  159. package/dist/web/bridges/mcp-app/index.js +4 -0
  160. package/dist/web/bridges/mcp-app/index.js.map +1 -0
  161. package/dist/web/bridges/mcp-app/types.d.ts +8 -0
  162. package/dist/web/bridges/mcp-app/types.js +2 -0
  163. package/dist/web/bridges/mcp-app/types.js.map +1 -0
  164. package/dist/web/bridges/mcp-app/use-mcp-app-context.d.ts +7 -0
  165. package/dist/web/bridges/mcp-app/use-mcp-app-context.js +7 -0
  166. package/dist/web/bridges/mcp-app/use-mcp-app-context.js.map +1 -0
  167. package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js +26 -0
  168. package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js.map +1 -0
  169. package/dist/web/bridges/types.d.ts +117 -0
  170. package/dist/web/bridges/types.js +2 -0
  171. package/dist/web/bridges/types.js.map +1 -0
  172. package/dist/web/bridges/use-host-context.d.ts +2 -0
  173. package/dist/web/bridges/use-host-context.js +8 -0
  174. package/dist/web/bridges/use-host-context.js.map +1 -0
  175. package/dist/web/components/modal-provider.d.ts +4 -0
  176. package/dist/web/components/modal-provider.js +45 -0
  177. package/dist/web/components/modal-provider.js.map +1 -0
  178. package/dist/web/create-store.d.ts +3 -0
  179. package/dist/web/create-store.js +38 -0
  180. package/dist/web/create-store.js.map +1 -0
  181. package/dist/web/create-store.test.js +129 -0
  182. package/dist/web/create-store.test.js.map +1 -0
  183. package/dist/{src/web → web}/data-llm.d.ts +1 -0
  184. package/dist/{src/web → web}/data-llm.js +13 -8
  185. package/dist/web/data-llm.js.map +1 -0
  186. package/dist/web/data-llm.test.js +142 -0
  187. package/dist/web/data-llm.test.js.map +1 -0
  188. package/dist/{src/web → web}/generate-helpers.d.ts +30 -25
  189. package/dist/{src/web → web}/generate-helpers.js +24 -20
  190. package/dist/web/generate-helpers.js.map +1 -0
  191. package/dist/{src/web → web}/generate-helpers.test-d.js +79 -23
  192. package/dist/web/generate-helpers.test-d.js.map +1 -0
  193. package/dist/{src/web → web}/generate-helpers.test.js +1 -1
  194. package/dist/web/generate-helpers.test.js.map +1 -0
  195. package/dist/web/helpers/state.d.ts +7 -0
  196. package/dist/web/helpers/state.js +45 -0
  197. package/dist/web/helpers/state.js.map +1 -0
  198. package/dist/web/helpers/state.test.js +53 -0
  199. package/dist/web/helpers/state.test.js.map +1 -0
  200. package/dist/web/hooks/index.d.ts +13 -0
  201. package/dist/{src/web → web}/hooks/index.js +6 -5
  202. package/dist/web/hooks/index.js.map +1 -0
  203. package/dist/web/hooks/test/utils.d.ts +16 -0
  204. package/dist/web/hooks/test/utils.js +64 -0
  205. package/dist/web/hooks/test/utils.js.map +1 -0
  206. package/dist/{src/web → web}/hooks/use-call-tool.d.ts +3 -2
  207. package/dist/{src/web → web}/hooks/use-call-tool.js +12 -4
  208. package/dist/web/hooks/use-call-tool.js.map +1 -0
  209. package/dist/{src/web → web}/hooks/use-call-tool.test-d.js +1 -1
  210. package/dist/web/hooks/use-call-tool.test-d.js.map +1 -0
  211. package/dist/{src/web → web}/hooks/use-call-tool.test.js +59 -19
  212. package/dist/web/hooks/use-call-tool.test.js.map +1 -0
  213. package/dist/web/hooks/use-display-mode.d.ts +4 -0
  214. package/dist/web/hooks/use-display-mode.js +9 -0
  215. package/dist/web/hooks/use-display-mode.js.map +1 -0
  216. package/dist/web/hooks/use-display-mode.test-d.d.ts +1 -0
  217. package/dist/web/hooks/use-display-mode.test-d.js +8 -0
  218. package/dist/web/hooks/use-display-mode.test-d.js.map +1 -0
  219. package/dist/web/hooks/use-display-mode.test.d.ts +1 -0
  220. package/dist/{src/web → web}/hooks/use-display-mode.test.js +3 -2
  221. package/dist/web/hooks/use-display-mode.test.js.map +1 -0
  222. package/dist/web/hooks/use-files.d.ts +7 -0
  223. package/dist/web/hooks/use-files.js +10 -0
  224. package/dist/web/hooks/use-files.js.map +1 -0
  225. package/dist/web/hooks/use-files.test.d.ts +1 -0
  226. package/dist/web/hooks/use-files.test.js +54 -0
  227. package/dist/web/hooks/use-files.test.js.map +1 -0
  228. package/dist/web/hooks/use-layout.d.ts +22 -0
  229. package/dist/web/hooks/use-layout.js +23 -0
  230. package/dist/web/hooks/use-layout.js.map +1 -0
  231. package/dist/web/hooks/use-layout.test.d.ts +1 -0
  232. package/dist/web/hooks/use-layout.test.js +96 -0
  233. package/dist/web/hooks/use-layout.test.js.map +1 -0
  234. package/dist/web/hooks/use-open-external.d.ts +3 -0
  235. package/dist/web/hooks/use-open-external.js +8 -0
  236. package/dist/web/hooks/use-open-external.js.map +1 -0
  237. package/dist/web/hooks/use-open-external.test.d.ts +1 -0
  238. package/dist/web/hooks/use-open-external.test.js +65 -0
  239. package/dist/web/hooks/use-open-external.test.js.map +1 -0
  240. package/dist/web/hooks/use-request-close.d.ts +2 -0
  241. package/dist/web/hooks/use-request-close.js +8 -0
  242. package/dist/web/hooks/use-request-close.js.map +1 -0
  243. package/dist/web/hooks/use-request-close.test.d.ts +1 -0
  244. package/dist/web/hooks/use-request-close.test.js +52 -0
  245. package/dist/web/hooks/use-request-close.test.js.map +1 -0
  246. package/dist/web/hooks/use-request-modal.d.ts +9 -0
  247. package/dist/web/hooks/use-request-modal.js +16 -0
  248. package/dist/web/hooks/use-request-modal.js.map +1 -0
  249. package/dist/web/hooks/use-request-modal.test.d.ts +1 -0
  250. package/dist/web/hooks/use-request-modal.test.js +61 -0
  251. package/dist/web/hooks/use-request-modal.test.js.map +1 -0
  252. package/dist/web/hooks/use-request-size.d.ts +3 -0
  253. package/dist/web/hooks/use-request-size.js +8 -0
  254. package/dist/web/hooks/use-request-size.js.map +1 -0
  255. package/dist/web/hooks/use-request-size.test.d.ts +1 -0
  256. package/dist/web/hooks/use-request-size.test.js +65 -0
  257. package/dist/web/hooks/use-request-size.test.js.map +1 -0
  258. package/dist/web/hooks/use-send-follow-up-message.d.ts +2 -0
  259. package/dist/web/hooks/use-send-follow-up-message.js +8 -0
  260. package/dist/web/hooks/use-send-follow-up-message.js.map +1 -0
  261. package/dist/web/hooks/use-set-open-in-app-url.d.ts +1 -0
  262. package/dist/web/hooks/use-set-open-in-app-url.js +8 -0
  263. package/dist/web/hooks/use-set-open-in-app-url.js.map +1 -0
  264. package/dist/web/hooks/use-set-open-in-app-url.test.d.ts +1 -0
  265. package/dist/web/hooks/use-set-open-in-app-url.test.js +43 -0
  266. package/dist/web/hooks/use-set-open-in-app-url.test.js.map +1 -0
  267. package/dist/{src/web → web}/hooks/use-tool-info.d.ts +13 -2
  268. package/dist/web/hooks/use-tool-info.js +26 -0
  269. package/dist/web/hooks/use-tool-info.js.map +1 -0
  270. package/dist/web/hooks/use-tool-info.test-d.d.ts +1 -0
  271. package/dist/{src/web → web}/hooks/use-tool-info.test-d.js +40 -5
  272. package/dist/web/hooks/use-tool-info.test-d.js.map +1 -0
  273. package/dist/web/hooks/use-tool-info.test.d.ts +1 -0
  274. package/dist/web/hooks/use-tool-info.test.js +130 -0
  275. package/dist/web/hooks/use-tool-info.test.js.map +1 -0
  276. package/dist/web/hooks/use-user.d.ts +18 -0
  277. package/dist/web/hooks/use-user.js +35 -0
  278. package/dist/web/hooks/use-user.js.map +1 -0
  279. package/dist/web/hooks/use-user.test.d.ts +1 -0
  280. package/dist/web/hooks/use-user.test.js +122 -0
  281. package/dist/web/hooks/use-user.test.js.map +1 -0
  282. package/dist/web/hooks/use-view-state.d.ts +4 -0
  283. package/dist/web/hooks/use-view-state.js +32 -0
  284. package/dist/web/hooks/use-view-state.js.map +1 -0
  285. package/dist/web/hooks/use-view-state.test.d.ts +1 -0
  286. package/dist/web/hooks/use-view-state.test.js +177 -0
  287. package/dist/web/hooks/use-view-state.test.js.map +1 -0
  288. package/dist/{src/web → web}/index.d.ts +5 -5
  289. package/dist/{src/web → web}/index.js +5 -5
  290. package/dist/web/index.js.map +1 -0
  291. package/dist/web/mount-view.d.ts +1 -0
  292. package/dist/{src/web/mount-widget.js → web/mount-view.js} +11 -3
  293. package/dist/web/mount-view.js.map +1 -0
  294. package/dist/web/plugin/data-llm.test.d.ts +1 -0
  295. package/dist/web/plugin/data-llm.test.js.map +1 -0
  296. package/dist/web/plugin/plugin.d.ts +5 -0
  297. package/dist/web/plugin/plugin.js +163 -0
  298. package/dist/web/plugin/plugin.js.map +1 -0
  299. package/dist/web/plugin/scan-views.d.ts +16 -0
  300. package/dist/web/plugin/scan-views.js +88 -0
  301. package/dist/web/plugin/scan-views.js.map +1 -0
  302. package/dist/web/plugin/scan-views.test.d.ts +1 -0
  303. package/dist/web/plugin/scan-views.test.js +99 -0
  304. package/dist/web/plugin/scan-views.test.js.map +1 -0
  305. package/dist/{src/web → web}/plugin/transform-data-llm.js +7 -4
  306. package/dist/web/plugin/transform-data-llm.js.map +1 -0
  307. package/dist/web/plugin/transform-data-llm.test.d.ts +1 -0
  308. package/dist/web/plugin/transform-data-llm.test.js.map +1 -0
  309. package/dist/web/plugin/validate-view.d.ts +1 -0
  310. package/dist/web/plugin/validate-view.js +9 -0
  311. package/dist/web/plugin/validate-view.js.map +1 -0
  312. package/dist/web/plugin/validate-view.test.d.ts +1 -0
  313. package/dist/web/plugin/validate-view.test.js +24 -0
  314. package/dist/web/plugin/validate-view.test.js.map +1 -0
  315. package/dist/{src/web → web}/proxy.js +6 -2
  316. package/dist/web/proxy.js.map +1 -0
  317. package/dist/web/types.d.ts +16 -0
  318. package/dist/web/types.js +2 -0
  319. package/dist/web/types.js.map +1 -0
  320. package/package.json +84 -38
  321. package/tsconfig.base.json +33 -0
  322. package/dist/src/server/index.d.ts +0 -4
  323. package/dist/src/server/index.js +0 -3
  324. package/dist/src/server/index.js.map +0 -1
  325. package/dist/src/server/inferUtilityTypes.js.map +0 -1
  326. package/dist/src/server/server.d.ts +0 -48
  327. package/dist/src/server/server.js +0 -62
  328. package/dist/src/server/server.js.map +0 -1
  329. package/dist/src/server/templateHelper.js +0 -29
  330. package/dist/src/server/templateHelper.js.map +0 -1
  331. package/dist/src/server/templates/development.hbs +0 -12
  332. package/dist/src/server/templates/production.hbs +0 -6
  333. package/dist/src/server/widgetsDevServer.d.ts +0 -12
  334. package/dist/src/server/widgetsDevServer.js +0 -39
  335. package/dist/src/server/widgetsDevServer.js.map +0 -1
  336. package/dist/src/test/utils.d.ts +0 -89
  337. package/dist/src/test/utils.js +0 -164
  338. package/dist/src/test/utils.js.map +0 -1
  339. package/dist/src/test/widget.test.js +0 -90
  340. package/dist/src/test/widget.test.js.map +0 -1
  341. package/dist/src/web/create-store.d.ts +0 -3
  342. package/dist/src/web/create-store.js +0 -103
  343. package/dist/src/web/create-store.js.map +0 -1
  344. package/dist/src/web/data-llm.js.map +0 -1
  345. package/dist/src/web/data-llm.test.js +0 -76
  346. package/dist/src/web/data-llm.test.js.map +0 -1
  347. package/dist/src/web/generate-helpers.js.map +0 -1
  348. package/dist/src/web/generate-helpers.test-d.js.map +0 -1
  349. package/dist/src/web/generate-helpers.test.js.map +0 -1
  350. package/dist/src/web/hooks/index.d.ts +0 -12
  351. package/dist/src/web/hooks/index.js.map +0 -1
  352. package/dist/src/web/hooks/use-call-tool.js.map +0 -1
  353. package/dist/src/web/hooks/use-call-tool.test-d.js.map +0 -1
  354. package/dist/src/web/hooks/use-call-tool.test.js.map +0 -1
  355. package/dist/src/web/hooks/use-display-mode.d.ts +0 -4
  356. package/dist/src/web/hooks/use-display-mode.js +0 -7
  357. package/dist/src/web/hooks/use-display-mode.js.map +0 -1
  358. package/dist/src/web/hooks/use-display-mode.test.js.map +0 -1
  359. package/dist/src/web/hooks/use-files.d.ts +0 -10
  360. package/dist/src/web/hooks/use-files.js +0 -7
  361. package/dist/src/web/hooks/use-files.js.map +0 -1
  362. package/dist/src/web/hooks/use-files.test.js +0 -29
  363. package/dist/src/web/hooks/use-files.test.js.map +0 -1
  364. package/dist/src/web/hooks/use-locale.d.ts +0 -1
  365. package/dist/src/web/hooks/use-locale.js +0 -5
  366. package/dist/src/web/hooks/use-locale.js.map +0 -1
  367. package/dist/src/web/hooks/use-locale.test.js +0 -21
  368. package/dist/src/web/hooks/use-locale.test.js.map +0 -1
  369. package/dist/src/web/hooks/use-open-external.d.ts +0 -1
  370. package/dist/src/web/hooks/use-open-external.js +0 -6
  371. package/dist/src/web/hooks/use-open-external.js.map +0 -1
  372. package/dist/src/web/hooks/use-open-external.test.js +0 -24
  373. package/dist/src/web/hooks/use-open-external.test.js.map +0 -1
  374. package/dist/src/web/hooks/use-openai-global.d.ts +0 -2
  375. package/dist/src/web/hooks/use-openai-global.js +0 -23
  376. package/dist/src/web/hooks/use-openai-global.js.map +0 -1
  377. package/dist/src/web/hooks/use-request-modal.d.ts +0 -6
  378. package/dist/src/web/hooks/use-request-modal.js +0 -9
  379. package/dist/src/web/hooks/use-request-modal.js.map +0 -1
  380. package/dist/src/web/hooks/use-request-modal.test.js +0 -24
  381. package/dist/src/web/hooks/use-request-modal.test.js.map +0 -1
  382. package/dist/src/web/hooks/use-send-follow-up-message.d.ts +0 -1
  383. package/dist/src/web/hooks/use-send-follow-up-message.js +0 -11
  384. package/dist/src/web/hooks/use-send-follow-up-message.js.map +0 -1
  385. package/dist/src/web/hooks/use-theme.d.ts +0 -1
  386. package/dist/src/web/hooks/use-theme.js +0 -5
  387. package/dist/src/web/hooks/use-theme.js.map +0 -1
  388. package/dist/src/web/hooks/use-theme.test.js +0 -26
  389. package/dist/src/web/hooks/use-theme.test.js.map +0 -1
  390. package/dist/src/web/hooks/use-tool-info.js +0 -22
  391. package/dist/src/web/hooks/use-tool-info.js.map +0 -1
  392. package/dist/src/web/hooks/use-tool-info.test-d.js.map +0 -1
  393. package/dist/src/web/hooks/use-tool-info.test.js +0 -59
  394. package/dist/src/web/hooks/use-tool-info.test.js.map +0 -1
  395. package/dist/src/web/hooks/use-user-agent.d.ts +0 -1
  396. package/dist/src/web/hooks/use-user-agent.js +0 -5
  397. package/dist/src/web/hooks/use-user-agent.js.map +0 -1
  398. package/dist/src/web/hooks/use-user-agent.test.js +0 -31
  399. package/dist/src/web/hooks/use-user-agent.test.js.map +0 -1
  400. package/dist/src/web/hooks/use-widget-state.d.ts +0 -4
  401. package/dist/src/web/hooks/use-widget-state.js +0 -54
  402. package/dist/src/web/hooks/use-widget-state.js.map +0 -1
  403. package/dist/src/web/hooks/use-widget-state.test.js +0 -60
  404. package/dist/src/web/hooks/use-widget-state.test.js.map +0 -1
  405. package/dist/src/web/index.js.map +0 -1
  406. package/dist/src/web/mount-widget.d.ts +0 -1
  407. package/dist/src/web/mount-widget.js.map +0 -1
  408. package/dist/src/web/plugin/data-llm.test.js.map +0 -1
  409. package/dist/src/web/plugin/plugin.d.ts +0 -2
  410. package/dist/src/web/plugin/plugin.js +0 -33
  411. package/dist/src/web/plugin/plugin.js.map +0 -1
  412. package/dist/src/web/plugin/transform-data-llm.js.map +0 -1
  413. package/dist/src/web/plugin/transform-data-llm.test.js.map +0 -1
  414. package/dist/src/web/proxy.js.map +0 -1
  415. package/dist/src/web/types.d.ts +0 -133
  416. package/dist/src/web/types.js.map +0 -1
  417. package/dist/vitest.config.d.ts +0 -2
  418. package/dist/vitest.config.js +0 -8
  419. package/dist/vitest.config.js.map +0 -1
  420. /package/dist/{src/test/widget.test.d.ts → cli/tunnel-control-server.test.d.ts} +0 -0
  421. /package/dist/{src/web/data-llm.test.d.ts → cli/tunnel-handler.test.d.ts} +0 -0
  422. /package/dist/{src/web/generate-helpers.test-d.d.ts → cli/tunnel.test.d.ts} +0 -0
  423. /package/dist/{src/web/generate-helpers.test.d.ts → server/asset-base-url-transform-plugin.test.d.ts} +0 -0
  424. /package/dist/{src/web/hooks/use-call-tool.test-d.d.ts → server/content-helpers.test.d.ts} +0 -0
  425. /package/dist/{src/web/hooks/use-call-tool.test.d.ts → server/express.test.d.ts} +0 -0
  426. /package/dist/{src/server → server}/inferUtilityTypes.js +0 -0
  427. /package/dist/{src/web/hooks/use-display-mode.test.d.ts → server/middleware.test-d.d.ts} +0 -0
  428. /package/dist/{src/web/hooks/use-files.test.d.ts → server/middleware.test.d.ts} +0 -0
  429. /package/dist/{src/web/hooks/use-locale.test.d.ts → server/tunnel-proxy-router.test.d.ts} +0 -0
  430. /package/dist/{src/web/hooks/use-open-external.test.d.ts → test/view.test.d.ts} +0 -0
  431. /package/dist/{src/web/hooks/use-request-modal.test.d.ts → web/bridges/mcp-app/use-mcp-app-context.test.d.ts} +0 -0
  432. /package/dist/{src/web/hooks/use-theme.test.d.ts → web/create-store.test.d.ts} +0 -0
  433. /package/dist/{src/web/plugin → web}/data-llm.test.d.ts +0 -0
  434. /package/dist/{src/web/hooks/use-tool-info.test-d.d.ts → web/generate-helpers.test-d.d.ts} +0 -0
  435. /package/dist/{src/web/hooks/use-tool-info.test.d.ts → web/generate-helpers.test.d.ts} +0 -0
  436. /package/dist/{src/web/hooks/use-user-agent.test.d.ts → web/helpers/state.test.d.ts} +0 -0
  437. /package/dist/{src/web/hooks/use-widget-state.test.d.ts → web/hooks/use-call-tool.test-d.d.ts} +0 -0
  438. /package/dist/{src/web/plugin/transform-data-llm.test.d.ts → web/hooks/use-call-tool.test.d.ts} +0 -0
  439. /package/dist/{src/web → web}/plugin/data-llm.test.js +0 -0
  440. /package/dist/{src/web → web}/plugin/transform-data-llm.d.ts +0 -0
  441. /package/dist/{src/web → web}/plugin/transform-data-llm.test.js +0 -0
  442. /package/dist/{src/web → web}/proxy.d.ts +0 -0
package/README.md CHANGED
@@ -1,371 +1,152 @@
1
- <div align="center">
2
-
3
- # Skybridge
4
-
5
- **Skybridge is the TypeScript framework for building ChatGPT apps**
6
-
7
- [![By Alpic](https://img.shields.io/badge/Made%20by%20Alpic-f6ffed?logo=alpic)](https://alpic.ai)
8
-
9
- ![NPM Downloads](https://img.shields.io/npm/dm/skybridge?color=e90060)
10
- ![NPM Version](https://img.shields.io/npm/v/skybridge?color=e90060)
11
- ![GitHub License](https://img.shields.io/github/license/alpic-ai/skybridge?color=e90060)
12
-
13
- </div>
14
-
15
- Skybridge comes with 2 packages:
16
-
17
- - `skybridge/server`: A drop-in replacement of the `@modelcontextprotocol/sdk` official `McpServer` class with extra features for widget development.
18
- - `skybridge/web`: A react library with hooks and components to build widgets on the underlying _OpenAI iFrame skybridge_ runtime.
19
-
20
- ## Quick start
21
-
22
- To get started in less than a minute, you can [create a new repository](https://github.com/new?template_name=apps-sdk-template&template_owner=alpic-ai) using our [ChatGPT SDK template](https://github.com/alpic-ai/apps-sdk-template). This template includes a basic setup for both the server and the widgets.
23
-
24
- ## Installation
25
-
1
+ # Skybridge - the MCP Apps framework
2
+
3
+ <p align="center">
4
+ <a href="https://docs.skybridge.tech">
5
+ <picture>
6
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/alpic-ai/skybridge/main/docs/images/skybridge-readme-banner-dark.png" />
7
+ <img alt="Skybridge, the full-stack React framework for MCP apps and MCP servers" src="https://raw.githubusercontent.com/alpic-ai/skybridge/main/docs/images/skybridge-readme-banner-light.png" width="100%" />
8
+ </picture>
9
+ </a>
10
+ </p>
11
+
12
+ <p align="center">
13
+ <strong>The full-stack React framework for MCP Apps and MCP Servers.</strong>
14
+ </p>
15
+
16
+ <p align="center">
17
+ <a href="https://docs.skybridge.tech">Documentation</a> ·
18
+ <a href="https://docs.skybridge.tech/quickstart/create-new-app">Quickstart</a> ·
19
+ <a href="https://github.com/alpic-ai/skybridge/tree/main/examples">Examples</a>
20
+ </p>
21
+
22
+ <p align="center">
23
+ <a href="https://www.npmjs.com/package/skybridge"><picture><source media="(prefers-color-scheme: dark)" srcset="https://img.shields.io/npm/v/skybridge?color=77F5EE&amp;labelColor=161B22&amp;style=for-the-badge"><img alt="npm version" src="https://img.shields.io/npm/v/skybridge?color=E3FAF7&amp;labelColor=F6F8FA&amp;style=for-the-badge"></picture></a>
24
+ <a href="https://www.npmjs.com/package/skybridge"><picture><source media="(prefers-color-scheme: dark)" srcset="https://img.shields.io/npm/dm/skybridge?color=D7FFC8&amp;labelColor=161B22&amp;style=for-the-badge"><img alt="npm downloads" src="https://img.shields.io/npm/dm/skybridge?color=E8FBD9&amp;labelColor=F6F8FA&amp;style=for-the-badge"></picture></a>
25
+ <a href="https://discord.com/invite/gNAazGueab"><picture><source media="(prefers-color-scheme: dark)" srcset="https://img.shields.io/badge/Discord-community-77F5EE?style=for-the-badge&amp;logo=discord&amp;logoColor=77F5EE&amp;labelColor=161B22"><img alt="Discord community" src="https://img.shields.io/badge/Discord-community-E3FAF7?style=for-the-badge&amp;logo=discord&amp;logoColor=5865F2&amp;labelColor=F6F8FA"></picture></a>
26
+ <a href="https://github.com/alpic-ai/skybridge/blob/main/LICENSE"><picture><source media="(prefers-color-scheme: dark)" srcset="https://img.shields.io/github/license/alpic-ai/skybridge?color=D7FFC8&amp;labelColor=161B22&amp;style=for-the-badge"><img alt="License: MIT" src="https://img.shields.io/github/license/alpic-ai/skybridge?color=E8FBD9&amp;labelColor=F6F8FA&amp;style=for-the-badge"></picture></a>
27
+ </p>
28
+
29
+ ## About Skybridge
30
+
31
+ Skybridge helps developers build type-safe MCP apps for Claude, ChatGPT and other UI-enabled MCP clients, with a complete set of tooling designed for both humans and agents.
32
+
33
+ Why? MCP apps extend the [Model Context Protocol](https://modelcontextprotocol.io/docs/getting-started/intro) with **rich, interactive UI views** rendered from MCP servers. Conversational apps need seamless interaction between the user, the UI, and the model. This means new UX patterns, developer tooling, and abstractions.
34
+ Plus, the raw SDKs are low-level: no hooks, type safety, HMR, etc.
35
+
36
+ That's why we built *Skybridge*.
37
+
38
+ Features include:
39
+
40
+ - **Delightful dev environment**: Skybridge provides a dev server with a local emulator, hot module reload, and a permanent tunnel to connect your local app to Claude and ChatGPT.
41
+ - **Write once, run everywhere**: the framework abstracts implementation differences between MCP clients, so your app runs seamlessly in Claude, ChatGPT, VSCode, and any other MCP apps compatible client.
42
+ - **Agent-ready**: powerful skills, CLI, and programmatic dev tool APIs, everything your coding agent needs to build MCP apps end-to-end.
43
+ - **Type-safe end-to-end**: tRPC-style inference from MCP server tool definition to React view for type safety from server to frontend.
44
+ - **React-first**: Intuitive React Query-style hooks, with advanced state management.
45
+ - **Example library**: get started quickly with ChatGPT- and Claude-ready app examples for ecommerce, travel, SaaS, and more.
46
+
47
+ They chose to build their MCP apps with Skybridge:
48
+
49
+ <p align="center">
50
+ <a href="https://www.datadoghq.com"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/alpic-ai/skybridge/main/docs/images/user-logos/datadog-dark.svg"><img src="https://raw.githubusercontent.com/alpic-ai/skybridge/main/docs/images/user-logos/datadog-light.svg" alt="Datadog" height="24"></picture></a>
51
+ &nbsp;&nbsp;
52
+ <a href="https://bitmovin.com"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/alpic-ai/skybridge/main/docs/images/user-logos/bitmovin-dark.svg"><img src="https://raw.githubusercontent.com/alpic-ai/skybridge/main/docs/images/user-logos/bitmovin-light.svg" alt="Bitmovin" height="22"></picture></a>
53
+ &nbsp;&nbsp;
54
+ <a href="https://www.evaneos.com"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/alpic-ai/skybridge/main/docs/images/user-logos/evaneos-dark.svg"><img src="https://raw.githubusercontent.com/alpic-ai/skybridge/main/docs/images/user-logos/evaneos-light.svg" alt="Evaneos" height="18"></picture></a>
55
+ &nbsp;&nbsp;
56
+ <a href="https://www.touchstream.media"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/alpic-ai/skybridge/main/docs/images/user-logos/touchstream-dark.svg"><img src="https://raw.githubusercontent.com/alpic-ai/skybridge/main/docs/images/user-logos/touchstream-light.svg" alt="Touchstream" height="24"></picture></a>
57
+ &nbsp;&nbsp;
58
+ <a href="https://www.cottages.com"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/alpic-ai/skybridge/main/docs/images/user-logos/cottages-dark.svg"><img src="https://raw.githubusercontent.com/alpic-ai/skybridge/main/docs/images/user-logos/cottages-light.svg" alt="Cottages.com" height="24"></picture></a>
59
+ </p>
60
+
61
+ ## Get started
62
+
63
+ **For agents**
64
+
65
+ Install our [skill](https://docs.skybridge.tech/devtools/skills) for building MCP apps and ChatGPT apps:
26
66
  ```bash
27
- pnpm add skybridge
28
- ```
29
-
30
- ## Concepts
31
-
32
- ### Widgets
33
-
34
- > A widget is a UI component that turns structured tool results into a human-friendly UI. Those are built using React components. They are rendered inside an iframe inline with the conversation on ChatGPT.
35
-
36
- Each widget in your app must have a unique name. The name is used to bridge the tool invocation result with the widget React component.
37
-
38
- For example, in order to register a new widget named `pokemon` on your ChatGPT app. You should have the following file structure and file contents:
39
-
40
- _Project structure_
41
-
42
- ```
43
- server/
44
- └── src/
45
- └── index.ts // Register the widget with McpServer.widget()
46
- web/
47
- └── src/
48
- └── widgets/
49
- └── pokemon.tsx // Use the same widget name as the file name
50
- ```
51
-
52
- _server/src/index.ts_
53
-
54
- ```ts
55
- import { McpServer } from "skybridge/server";
56
-
57
- const server = new McpServer();
58
-
59
- server.widget(
60
- "pokemon"
61
- // Remaining arguments...
62
- );
63
- ```
64
-
65
- _web/src/widgets/pokemon.tsx_
66
-
67
- ```ts
68
- import { mountWidget } from "skybridge/web";
69
-
70
- const Pokemon: React.FunctionComponent = () => {
71
- // Your React component code goes here...
72
- };
73
-
74
- mountWidget(<Pokemon />);
75
- ```
76
-
77
- ## Packages
78
-
79
- ### skybridge/server
80
-
81
- The `skybridge/server` package is a drop-in replacement of the `@modelcontextprotocol/sdk` official `McpServer` class with extra features for widget development. If you're already using the `@modelcontextprotocol/sdk`, you can simply replace your `McpServer` import with `skybridge/server` and you're good to go.
82
-
83
- ### skybridge/web
84
-
85
- The `skybridge/web` package is a react library with hooks and components to build widgets on the underlying _OpenAI iFrame skybridge_ runtime.
86
-
87
- **Vite plugin**
88
-
89
- The `skybridge/web` package comes with a Vite plugin that allows you to build your widgets as regular Vite apps.
90
-
91
- ```ts
92
- import { defineConfig } from "vite";
93
- import { skybridge } from "skybridge/web";
94
-
95
- export default defineConfig({
96
- plugins: [skybridge()],
97
- });
98
- ```
99
-
100
- **Typed Hooks**
101
-
102
- Skybridge provides fully typed hooks that give you autocomplete for tool names and type inference for inputs/outputs - similar to tRPC. This is opt-in and requires exporting your server type.
103
-
104
- > **Tip:** For the best TypeScript experience, use typed hooks throughout your application. They provide autocomplete, type safety, and better IDE support.
105
-
106
- > **Important:** For `generateHelpers` to work correctly, your MCP server must be defined using method chaining (e.g., `server.widget(...).widget(...).registerTool(...)`). This ensures TypeScript can properly infer the tool registry type from the chained calls.
107
-
108
- **Examples:**
109
-
110
- ✅ **Works** - Using method chaining:
111
-
112
- ```ts
113
- import { McpServer } from "skybridge/server";
114
- import { z } from "zod";
115
-
116
- const server = new McpServer({ name: "my-app", version: "1.0" }, {})
117
- .widget("search-voyage", {}, {
118
- inputSchema: { destination: z.string() },
119
- }, async ({ destination }) => {
120
- return { content: [{ type: "text", text: `Found trips to ${destination}` }] };
121
- })
122
- .registerTool("calculate-price", {
123
- inputSchema: { tripId: z.string() },
124
- }, async ({ tripId }) => {
125
- return { content: [{ type: "text", text: `Price for ${tripId}` }] };
126
- });
127
-
128
- export type AppType = typeof server; // ✅ Type inference works correctly
129
- ```
130
-
131
- ❌ **Doesn't work** - Without method chaining:
132
-
133
- ```ts
134
- import { McpServer } from "skybridge/server";
135
- import { z } from "zod";
136
-
137
- const server = new McpServer({ name: "my-app", version: "1.0" }, {});
138
-
139
- server.widget("search-voyage", {}, {
140
- inputSchema: { destination: z.string() },
141
- }, async ({ destination }) => {
142
- return { content: [{ type: "text", text: `Found trips to ${destination}` }] };
143
- });
144
-
145
- server.registerTool("calculate-price", {
146
- inputSchema: { tripId: z.string() },
147
- }, async ({ tripId }) => {
148
- return { content: [{ type: "text", text: `Price for ${tripId}` }] };
149
- });
150
-
151
- export type AppType = typeof server; // ❌ Type inference fails - tool registry is empty
152
- ```
153
-
154
- _Server setup (server/src/index.ts)_
155
-
156
- ```ts
157
- import { McpServer } from "skybridge/server";
158
- import { z } from "zod";
159
-
160
- const server = new McpServer({ name: "my-app", version: "1.0" }, {})
161
- .widget("search-voyage", {}, {
162
- description: "Search for trips",
163
- inputSchema: {
164
- destination: z.string(),
165
- departureDate: z.string().optional(),
166
- },
167
- outputSchema: {
168
- results: z.array(z.object({ id: z.string(), name: z.string() })),
169
- totalCount: z.number(),
170
- },
171
- }, async ({ destination }) => {
172
- // Your tool logic here...
173
- return { content: [{ type: "text", text: `Found trips to ${destination}` }] };
174
- })
175
- .widget("get-details", {}, {
176
- inputSchema: { tripId: z.string() },
177
- }, async ({ tripId }) => {
178
- return { content: [{ type: "text", text: `Details for ${tripId}` }] };
179
- });
180
-
181
- // Export the server type for the client
182
- export type AppType = typeof server;
67
+ npx skills add alpic-ai/skybridge -s skybridge
183
68
  ```
69
+ Once installed, ask your agent "What skills do you have?" to confirm, then try:
184
70
 
185
- _One-time setup (web/src/skybridge.ts)_
71
+ - _Create a new MCP app_
72
+ - _Migrate my MCP server to the Skybridge framework_
73
+ - _Add a new view to my MCP app_
186
74
 
187
- Create typed hooks once and export them for use across your app. This file acts as a bridge between your server types and your widgets:
75
+ **For humans**
188
76
 
189
- ```ts
190
- import type { AppType } from "../server"; // type-only import
191
- import { generateHelpers } from "skybridge/web";
192
-
193
- export const { useCallTool, useToolInfo } = generateHelpers<AppType>();
194
- ```
195
-
196
- _Usage in widgets (web/src/widgets/search.tsx)_
197
-
198
- ```tsx
199
- import { useCallTool, useToolInfo } from "../skybridge"; // import typed hooks
200
-
201
- export function SearchWidget() {
202
- const { callTool, data, isPending } = useCallTool("search-voyage");
203
- // ^ autocomplete for tool names
204
- const toolInfo = useToolInfo<"search-voyage">();
205
- // ^ autocomplete for widget names
206
-
207
- const handleSearch = () => {
208
- callTool({ destination: "Spain" });
209
- // ^ autocomplete for input fields
210
- };
211
-
212
- return (
213
- <div>
214
- <button onClick={handleSearch} disabled={isPending}>
215
- Search
216
- </button>
217
- {toolInfo.isSuccess && (
218
- <div>Found {toolInfo.output.structuredContent.totalCount} results</div>
219
- // ^ typed output
220
- )}
221
- </div>
222
- );
223
- }
224
- ```
225
-
226
- **Hooks**
227
-
228
- The `skybridge/web` package comes with a set of hooks to help you build your widgets :
229
-
230
- - `useOpenAiGlobal`: A generic hook to get any global data from the OpenAI iFrame skybridge runtime (in `window.openai`).
231
- - `useToolOutput`: A hook to get the initial tool `structuredContent` returned when rendering the widget for the first time. The data inside this hook is not updated when the tool is called again.
232
- - `useToolResponseMetadata`: A hook to get the initial tool `meta` returned when rendering the widget for the first time. The data inside this hook is not updated when the tool is called again.
233
- - `useToolInfo`: A hook to get the tool input, output, and response metadata with type inference. Provides a discriminated union based on status (pending/success).
234
- - `useCallTool`: A @tanstack/react-query inspired hook to send make additional tool calls inside a widget.
235
- - `generateHelpers`: A factory that creates typed versions of `useCallTool` and `useToolInfo` with full type inference from your server type.
236
-
237
- _useOpenAiGlobal_
238
-
239
- ```ts
240
- import { useOpenAiGlobal } from "skybridge/web";
241
-
242
- const theme = useOpenAiGlobal("theme");
77
+ Bootstrap a new project with:
78
+ ```bash
79
+ npm create skybridge@latest my-app
243
80
  ```
81
+ For full install instructions, read our [**Quickstart guide**](https://docs.skybridge.tech/quickstart/create-new-app).
244
82
 
245
- _useToolOutput_
83
+ ## Documentation
246
84
 
247
- ```ts
248
- import { useToolOutput } from "skybridge/web";
85
+ The [Skybridge documentation](https://docs.skybridge.tech) covers the full lifecycle of building MCP Apps:
249
86
 
250
- const toolOutput = useToolOutput();
251
- ```
87
+ - [Fundamentals](https://docs.skybridge.tech/fundamentals): understand MCP Apps, ChatGPT Apps, and how Skybridge bridges both runtimes.
88
+ - [Core concepts](https://docs.skybridge.tech/concepts): learn about server <> model <> UI data flows, LLM context sync, type safety, and instant local iteration with our devtools.
89
+ - [Guides](https://docs.skybridge.tech/guides/fetching-data): build real app behavior with tools, views, state, and model communication.
90
+ - [API Reference](https://docs.skybridge.tech/api-reference): browse our MCP server APIs, React hooks, CLI commands, and runtime compatibility.
252
91
 
253
- _useToolResponseMetadata_
92
+ ## Deploy
254
93
 
255
- ```ts
256
- import { useToolResponseMetadata } from "skybridge/web";
94
+ Deploy Skybridge apps instantly on [Alpic](https://alpic.ai) for scalable hosting, MCP-specific analytics, permanent tunneling, app store compliance auditing and submission help. You can also self-host on any Node.js-compatible platform.
257
95
 
258
- const toolResponseMetadata = useToolResponseMetadata();
259
- ```
96
+ See our [deployment guide](https://docs.skybridge.tech/quickstart/deploy) for the full production path.
260
97
 
261
- _useToolInfo_
98
+ ## Community & Contributing
262
99
 
263
- ```ts
264
- import { useToolInfo } from "skybridge/web";
100
+ We'd love your help improving Skybridge. Here are a few ways to get involved:
265
101
 
266
- const toolInfo = useToolInfo<{
267
- input: { query: string };
268
- output: { results: string[] };
269
- responseMetadata: { id: number };
270
- }>();
102
+ - **Bugs**: If you run into a bug or unexpected behavior, open a [GitHub Issue](https://github.com/alpic-ai/skybridge/issues) with a clear reproduction.
103
+ - **Questions and ideas**: Need help building with Skybridge or have ideas to improve the framework, docs, examples, or developer experience? [Open an issue](https://github.com/alpic-ai/skybridge/issues) or share them on our [Discord](https://discord.com/invite/gNAazGueab).
104
+ - **Pull requests**: For code or documentation changes, read the [Contributing Guide](https://github.com/alpic-ai/skybridge/blob/main/CONTRIBUTING.md) before opening a PR.
271
105
 
272
- // toolInfo.input is typed based on the input type
273
- // toolInfo.output.structuredContent is typed based on the output type (undefined when pending)
274
- // toolInfo.status narrows correctly: "pending" | "success"
106
+ Skybridge is released under the [MIT License](https://github.com/alpic-ai/skybridge/blob/main/LICENSE).
275
107
 
276
- if (toolInfo.isPending) {
277
- // toolInfo.output is undefined here (pending state)
278
- console.log(toolInfo.input.query);
279
- }
108
+ ### Contributors
280
109
 
281
- if (toolInfo.isSuccess) {
282
- // toolInfo.output.structuredContent is typed here
283
- console.log(toolInfo.output.structuredContent.results);
284
- }
285
- ```
110
+ Built and maintained with ❤️ by [Harijoe](https://github.com/harijoe), [Fred Barthelet](https://github.com/fredericbarthelet), and the [Alpic](https://alpic.ai) team.
286
111
 
287
- _useToolInfo_ with typed hooks (recommended)
112
+ <a href="https://github.com/alpic-ai/skybridge/graphs/contributors">
113
+ <img src="https://contrib.rocks/image?repo=alpic-ai/skybridge" alt="Skybridge contributors">
114
+ </a>
288
115
 
289
- ```tsx
290
- import { useToolInfo } from "../skybridge"; // import typed hooks
116
+ ## Example templates
291
117
 
292
- export function SearchWidget() {
293
- const toolInfo = useToolInfo<"search-voyage">();
294
- // ^ autocomplete for widget names
295
- // toolInfo.input is typed as { destination: string; departureDate?: string; ... }
296
- // toolInfo.output.structuredContent is typed as { results: Array<...>; totalCount: number; }
118
+ Explore all our example templates in the [Examples](https://docs.skybridge.tech/examples) section of the documentation.
297
119
 
298
- if (toolInfo.isSuccess) {
299
- return <div>Found {toolInfo.output.structuredContent.totalCount} results</div>;
300
- }
120
+ ### Basic
301
121
 
302
- return <div>Searching for {toolInfo.input.destination}...</div>;
303
- }
304
- ```
122
+ | Preview | App | Description | Demo | Code |
123
+ | --- | --- | --- | --- | --- |
124
+ | <img src="docs/images/showcase-example.png" alt="Everything" width="160" /> | Everything | Comprehensive playground app showcasing all Skybridge hooks and features. | [Try Demo](https://everything.skybridge.tech/try) | [View code](https://github.com/alpic-ai/skybridge/tree/main/examples/everything) |
305
125
 
306
- _useCallTool_ in synchronous mode
307
-
308
- ```ts
309
- import { useCallTool } from "skybridge/web";
310
-
311
- export const TestTool: React.FunctionComponent = () => {
312
- const { callTool, isPending } = useCallTool("myToolName");
313
-
314
- return (
315
- <div>
316
- <button
317
- disabled={isPending}
318
- onClick={() => {
319
- callTool({ input: "test input" }, {
320
- onSuccess: (data) => {
321
- alert("Tool returned: " + data);
322
- },
323
- });
324
- >
325
- Call Tool inside a widget
326
- </button>
327
- </div>
328
- );
329
- };
330
- ```
331
-
332
- _useCallTool_ in asynchronous mode
333
-
334
- ```ts
335
- import { useCallTool } from "skybridge/web";
336
-
337
- export const TestTool: React.FunctionComponent = () => {
338
- const { callToolAsync, isPending } = useCallTool("myToolName");
339
-
340
- return (
341
- <div>
342
- <button
343
- disabled={isPending}
344
- onClick={async () => {
345
- const data = await callToolAsync({ input: "test input" });
346
- alert("Tool returned: " + data);
347
- }}
348
- >
349
- Call Tool inside a widget
350
- </button>
351
- </div>
352
- );
353
- };
354
- ```
126
+ ### Use cases
355
127
 
356
- ## Migrate your existing MCP server to a ChatGPT app
128
+ | Preview | App | Description | Demo | Code |
129
+ | --- | --- | --- | --- | --- |
130
+ | <img src="docs/images/showcase-capitals.png" alt="Capitals Explorer" width="160" /> | Capitals Explorer | Interactive world map with geolocation, country information, and dynamic capital exploration. | [Try Demo](https://capitals.skybridge.tech/try) | [View code](https://github.com/alpic-ai/skybridge/tree/main/examples/capitals) |
131
+ | <img src="docs/images/showcase-flight-booking.png" alt="Flight Booking" width="160" /> | Flight Booking | Flight search carousel with route details, pricing comparison, and external booking. | [Try Demo](https://flight-booking.skybridge.tech/try) | [View code](https://github.com/alpic-ai/skybridge/tree/main/examples/flight-booking) |
132
+ | <img src="docs/images/showcase-ecommerce.png" alt="Ecommerce Carousel" width="160" /> | Ecommerce Carousel | Product carousel with persistent cart, localization, theme switching, and modal dialogs. | [Try Demo](https://ecommerce.skybridge.tech/try) | [View code](https://github.com/alpic-ai/skybridge/tree/main/examples/ecom-carousel) |
133
+ | <img src="docs/images/showcase-investigation-game.png" alt="Investigation Game" width="160" /> | Investigation Game | Multi-screen mystery game with fullscreen mode, dynamic story progression and context asynchronicity demonstration | [Try Demo](https://investigation-game.skybridge.tech/try) | [View code](https://github.com/alpic-ai/skybridge/tree/main/examples/investigation-game) |
134
+ | <img src="docs/images/showcase-productivity.png" alt="Productivity" width="160" /> | Productivity | Interactive analytics dashboard with charts, theme adaptation, localization, fullscreen mode, and bidirectional tool calls. | [Try Demo](https://productivity.skybridge.tech/try) | [View code](https://github.com/alpic-ai/skybridge/tree/main/examples/productivity) |
135
+ | <img src="docs/images/showcase-times-up.png" alt="Time's Up" width="160" /> | Time's Up | Word-guessing party game where the user gives hints and the AI tries to guess. | [Try Demo](https://times-up.skybridge.tech/try) | [View code](https://github.com/alpic-ai/skybridge/tree/main/examples/times-up) |
136
+ | <img src="docs/images/showcase-lumo.png" alt="Lumo Interactive AI Tutor" width="160" /> | Lumo — Interactive AI Tutor | Adaptive tutor with Mermaid diagrams, mind maps, quizzes, and fill-in-the-blank exercises. | [Try Demo](https://lumo-mcp-app-39519fdd.alpic.live/try) | [View code](https://github.com/connorads/lumo-mcp-app) |
357
137
 
358
- If you're already using the `@modelcontextprotocol/sdk` to build a MCP server, you can migrate to a ChatGPT app by following these steps:
138
+ ### Auth
359
139
 
360
- 1. Replace your `McpServer` import from `@modelcontextprotocol/sdk` with the same import from `skybridge/server`
361
- 2. Create a new vite project in a folder named `web` and install the `skybridge` package
362
- 3. Replace the `vite.config.ts` file with the following:
140
+ | Preview | Provider | Description | Code |
141
+ | --- | --- | --- | --- |
142
+ | <img src="docs/images/showcase-clerk.png" alt="Auth Clerk" width="160" /> | Clerk | Full OAuth authentication with Clerk and personalized coffee shop search. | [View code](https://github.com/alpic-ai/skybridge/tree/main/examples/auth-clerk) |
143
+ | <img src="docs/images/showcase-workos.png" alt="Auth WorkOS AuthKit" width="160" /> | WorkOS AuthKit | Full OAuth authentication with WorkOS AuthKit and personalized coffee shop search. | [View code](https://github.com/alpic-ai/skybridge/tree/main/examples/auth-workos) |
144
+ | <img src="docs/images/showcase-stytch.png" alt="Auth Stytch" width="160" /> | Stytch | Full OAuth authentication with Stytch and personalized coffee shop search. | [View code](https://github.com/alpic-ai/skybridge/tree/main/examples/auth-stytch) |
145
+ | <img src="docs/images/showcase-auth0.png" alt="Auth Auth0" width="160" /> | Auth0 | Full OAuth authentication with Auth0 and personalized coffee shop search. | [View code](https://github.com/alpic-ai/skybridge/tree/main/examples/auth-auth0) |
363
146
 
364
- ```ts
365
- import { defineConfig } from "vite";
366
- import { skybridge } from "skybridge/web";
147
+ ### UI and component libraries
367
148
 
368
- export default defineConfig({
369
- plugins: [skybridge()],
370
- });
371
- ```
149
+ | Preview | App | Description | Demo | Code |
150
+ | --- | --- | --- | --- | --- |
151
+ | <img src="docs/images/showcase-manifest-ui.png" alt="Manifest UI" width="160" /> | Manifest UI | Agentic component library example for rich AI-powered experiences. | [Try Demo](https://manifest-ui.skybridge.tech/try) | [View code](https://github.com/alpic-ai/skybridge/tree/main/examples/manifest-ui) |
152
+ | <img src="docs/images/showcase-generative-ui.png" alt="Generative UI" width="160" /> | Generative UI | LLM-generated dynamic UIs with json-render and 36 pre-built shadcn/ui components. | [Try Demo](https://generative-ui.skybridge.tech/try) | [View code](https://github.com/alpic-ai/skybridge/tree/main/examples/generative-ui) |
package/bin/run.js ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { execute } from "@oclif/core";
4
+
5
+ await execute({ dir: import.meta.url });
@@ -0,0 +1,18 @@
1
+ export declare function resolvePort(flagPort?: number): Promise<{
2
+ port: number;
3
+ fallback: boolean;
4
+ envWarning?: undefined;
5
+ } | {
6
+ port: number;
7
+ fallback: boolean;
8
+ envWarning: string;
9
+ }>;
10
+ /**
11
+ * Returns the given port if available, otherwise lets the OS
12
+ * pick a free port via `listen(0)`.
13
+ *
14
+ * @param host - Bind address for the check. Pass `"localhost"` for
15
+ * services that bind to 127.0.0.1 (e.g. Vite HMR). Omit for
16
+ * services that bind to all interfaces (e.g. the HTTP server).
17
+ */
18
+ export declare function detectAvailablePort(startPort: number, host?: string): Promise<number>;
@@ -0,0 +1,61 @@
1
+ import net from "node:net";
2
+ const DEFAULT_PORT = 3000;
3
+ export async function resolvePort(flagPort) {
4
+ if (flagPort && flagPort > 1) {
5
+ return { port: flagPort, fallback: false };
6
+ }
7
+ const rawEnv = process.env.PORT;
8
+ if (rawEnv) {
9
+ const parsed = Number(rawEnv);
10
+ if (Number.isInteger(parsed) && parsed > 0) {
11
+ return { port: parsed, fallback: false };
12
+ }
13
+ return {
14
+ port: await detectAvailablePort(DEFAULT_PORT),
15
+ fallback: false,
16
+ envWarning: `Invalid PORT="${rawEnv}", ignoring and using default`,
17
+ };
18
+ }
19
+ const port = await detectAvailablePort(DEFAULT_PORT);
20
+ return { port, fallback: port !== DEFAULT_PORT };
21
+ }
22
+ /**
23
+ * Returns the given port if available, otherwise lets the OS
24
+ * pick a free port via `listen(0)`.
25
+ *
26
+ * @param host - Bind address for the check. Pass `"localhost"` for
27
+ * services that bind to 127.0.0.1 (e.g. Vite HMR). Omit for
28
+ * services that bind to all interfaces (e.g. the HTTP server).
29
+ */
30
+ export async function detectAvailablePort(startPort, host) {
31
+ const available = await isPortAvailable(startPort, host);
32
+ if (available) {
33
+ return startPort;
34
+ }
35
+ return new Promise((resolve, reject) => {
36
+ const server = net.createServer();
37
+ server.once("error", reject);
38
+ server.once("listening", () => {
39
+ const addr = server.address();
40
+ if (addr && typeof addr === "object") {
41
+ const { port } = addr;
42
+ server.close(() => resolve(port));
43
+ }
44
+ else {
45
+ server.close(() => reject(new Error("Failed to detect available port")));
46
+ }
47
+ });
48
+ server.listen(0, host);
49
+ });
50
+ }
51
+ function isPortAvailable(port, host) {
52
+ return new Promise((resolve) => {
53
+ const server = net.createServer();
54
+ server.once("error", () => resolve(false));
55
+ server.once("listening", () => {
56
+ server.close(() => resolve(true));
57
+ });
58
+ server.listen(port, host);
59
+ });
60
+ }
61
+ //# sourceMappingURL=detect-port.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect-port.js","sourceRoot":"","sources":["../../src/cli/detect-port.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,UAAU,CAAC;AAE3B,MAAM,YAAY,GAAG,IAAI,CAAC;AAE1B,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,QAAiB;IACjD,IAAI,QAAQ,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;QAC7B,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAC7C,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;IAChC,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QAC9B,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;QAC3C,CAAC;QACD,OAAO;YACL,IAAI,EAAE,MAAM,mBAAmB,CAAC,YAAY,CAAC;YAC7C,QAAQ,EAAE,KAAK;YACf,UAAU,EAAE,iBAAiB,MAAM,+BAA+B;SACnE,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,mBAAmB,CAAC,YAAY,CAAC,CAAC;IACrD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,KAAK,YAAY,EAAE,CAAC;AACnD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,SAAiB,EACjB,IAAa;IAEb,MAAM,SAAS,GAAG,MAAM,eAAe,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IACzD,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,MAAM,GAAG,GAAG,CAAC,YAAY,EAAE,CAAC;QAElC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC7B,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE;YAC5B,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;YAC9B,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACrC,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;gBACtB,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;YACpC,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAChB,MAAM,CAAC,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC,CACrD,CAAC;YACJ,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IACzB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,eAAe,CAAC,IAAY,EAAE,IAAa;IAClD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,MAAM,GAAG,GAAG,CAAC,YAAY,EAAE,CAAC;QAElC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QAC3C,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE;YAC5B,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import net from \"node:net\";\n\nconst DEFAULT_PORT = 3000;\n\nexport async function resolvePort(flagPort?: number) {\n if (flagPort && flagPort > 1) {\n return { port: flagPort, fallback: false };\n }\n\n const rawEnv = process.env.PORT;\n if (rawEnv) {\n const parsed = Number(rawEnv);\n if (Number.isInteger(parsed) && parsed > 0) {\n return { port: parsed, fallback: false };\n }\n return {\n port: await detectAvailablePort(DEFAULT_PORT),\n fallback: false,\n envWarning: `Invalid PORT=\"${rawEnv}\", ignoring and using default`,\n };\n }\n\n const port = await detectAvailablePort(DEFAULT_PORT);\n return { port, fallback: port !== DEFAULT_PORT };\n}\n\n/**\n * Returns the given port if available, otherwise lets the OS\n * pick a free port via `listen(0)`.\n *\n * @param host - Bind address for the check. Pass `\"localhost\"` for\n * services that bind to 127.0.0.1 (e.g. Vite HMR). Omit for\n * services that bind to all interfaces (e.g. the HTTP server).\n */\nexport async function detectAvailablePort(\n startPort: number,\n host?: string,\n): Promise<number> {\n const available = await isPortAvailable(startPort, host);\n if (available) {\n return startPort;\n }\n\n return new Promise((resolve, reject) => {\n const server = net.createServer();\n\n server.once(\"error\", reject);\n server.once(\"listening\", () => {\n const addr = server.address();\n if (addr && typeof addr === \"object\") {\n const { port } = addr;\n server.close(() => resolve(port));\n } else {\n server.close(() =>\n reject(new Error(\"Failed to detect available port\")),\n );\n }\n });\n\n server.listen(0, host);\n });\n}\n\nfunction isPortAvailable(port: number, host?: string): Promise<boolean> {\n return new Promise((resolve) => {\n const server = net.createServer();\n\n server.once(\"error\", () => resolve(false));\n server.once(\"listening\", () => {\n server.close(() => resolve(true));\n });\n\n server.listen(port, host);\n });\n}\n"]}
@@ -0,0 +1,4 @@
1
+ export declare const Header: ({ version, children, }: {
2
+ version: string;
3
+ children?: React.ReactNode;
4
+ }) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,6 @@
1
+ import { jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Text } from "ink";
3
+ export const Header = ({ version, children, }) => {
4
+ return (_jsxs(Box, { marginBottom: 1, children: [_jsxs(Text, { color: "cyan", bold: true, children: ["\u26F0", " ", "Skybridge"] }), _jsxs(Text, { color: "cyan", children: [" v", version] }), children] }));
5
+ };
6
+ //# sourceMappingURL=header.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"header.js","sourceRoot":"","sources":["../../src/cli/header.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAEhC,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,EACrB,OAAO,EACP,QAAQ,GAIT,EAAE,EAAE;IACH,OAAO,CACL,MAAC,GAAG,IAAC,YAAY,EAAE,CAAC,aAClB,MAAC,IAAI,IAAC,KAAK,EAAC,MAAM,EAAC,IAAI,6BACnB,IAAI,iBACD,EACP,MAAC,IAAI,IAAC,KAAK,EAAC,MAAM,mBAAI,OAAO,IAAQ,EACpC,QAAQ,IACL,CACP,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { Box, Text } from \"ink\";\n\nexport const Header = ({\n version,\n children,\n}: {\n version: string;\n children?: React.ReactNode;\n}) => {\n return (\n <Box marginBottom={1}>\n <Text color=\"cyan\" bold>\n ⛰{\" \"}Skybridge\n </Text>\n <Text color=\"cyan\"> v{version}</Text>\n {children}\n </Box>\n );\n};\n"]}
@@ -0,0 +1,2 @@
1
+ import { type SpawnOptions } from "node:child_process";
2
+ export declare function runCommand(command: string, options?: SpawnOptions): Promise<void>;