skybridge 0.0.0-dev.f1f2ce8 → 0.0.0-dev.f2073a1

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 (323) hide show
  1. package/README.md +16 -14
  2. package/dist/cli/build-helpers.d.ts +1 -1
  3. package/dist/cli/build-helpers.js +4 -4
  4. package/dist/cli/build-helpers.js.map +1 -1
  5. package/dist/cli/build-helpers.test.js +6 -4
  6. package/dist/cli/build-helpers.test.js.map +1 -1
  7. package/dist/cli/build-steps.js +1 -1
  8. package/dist/cli/build-steps.js.map +1 -1
  9. package/dist/cli/build-steps.test.js +3 -3
  10. package/dist/cli/build-steps.test.js.map +1 -1
  11. package/dist/cli/detect-port.js +0 -1
  12. package/dist/cli/detect-port.js.map +1 -1
  13. package/dist/cli/run-plain.js +2 -1
  14. package/dist/cli/run-plain.js.map +1 -1
  15. package/dist/cli/telemetry.js +2 -0
  16. package/dist/cli/telemetry.js.map +1 -1
  17. package/dist/cli/use-execute-steps.d.ts +1 -1
  18. package/dist/cli/use-nodemon.d.ts +11 -1
  19. package/dist/cli/use-nodemon.js +30 -8
  20. package/dist/cli/use-nodemon.js.map +1 -1
  21. package/dist/cli/use-typescript-check.js +1 -1
  22. package/dist/cli/use-typescript-check.js.map +1 -1
  23. package/dist/commands/dev.js +4 -4
  24. package/dist/commands/dev.js.map +1 -1
  25. package/dist/commands/start.js +2 -2
  26. package/dist/commands/start.js.map +1 -1
  27. package/dist/context-warnings.d.ts +5 -0
  28. package/dist/context-warnings.js +31 -0
  29. package/dist/context-warnings.js.map +1 -0
  30. package/dist/context-warnings.test.js +28 -0
  31. package/dist/context-warnings.test.js.map +1 -0
  32. package/dist/server/app.d.ts +194 -0
  33. package/dist/server/app.js +266 -0
  34. package/dist/server/app.js.map +1 -0
  35. package/dist/server/app.test.js +97 -0
  36. package/dist/server/app.test.js.map +1 -0
  37. package/dist/server/auth/discovery.d.ts +2 -1
  38. package/dist/server/auth/discovery.js +2 -2
  39. package/dist/server/auth/discovery.js.map +1 -1
  40. package/dist/server/auth/index.d.ts +35 -5
  41. package/dist/server/auth/index.js.map +1 -1
  42. package/dist/server/auth/providers/auth0.d.ts +25 -3
  43. package/dist/server/auth/providers/auth0.js +13 -8
  44. package/dist/server/auth/providers/auth0.js.map +1 -1
  45. package/dist/server/auth/providers/auth0.test.js +5 -3
  46. package/dist/server/auth/providers/auth0.test.js.map +1 -1
  47. package/dist/server/auth/providers/authplane.d.ts +49 -0
  48. package/dist/server/auth/providers/authplane.js +57 -0
  49. package/dist/server/auth/providers/authplane.js.map +1 -0
  50. package/dist/server/auth/providers/authplane.test.js +143 -0
  51. package/dist/server/auth/providers/authplane.test.js.map +1 -0
  52. package/dist/server/auth/providers/clerk.d.ts +40 -3
  53. package/dist/server/auth/providers/clerk.js +4 -1
  54. package/dist/server/auth/providers/clerk.js.map +1 -1
  55. package/dist/server/auth/providers/clerk.test.js +5 -3
  56. package/dist/server/auth/providers/clerk.test.js.map +1 -1
  57. package/dist/server/auth/providers/custom.d.ts +16 -6
  58. package/dist/server/auth/providers/custom.js +14 -4
  59. package/dist/server/auth/providers/custom.js.map +1 -1
  60. package/dist/server/auth/providers/custom.test.js +24 -19
  61. package/dist/server/auth/providers/custom.test.js.map +1 -1
  62. package/dist/server/auth/providers/descope.d.ts +32 -3
  63. package/dist/server/auth/providers/descope.js.map +1 -1
  64. package/dist/server/auth/providers/descope.test.js +8 -6
  65. package/dist/server/auth/providers/descope.test.js.map +1 -1
  66. package/dist/server/auth/providers/stytch.d.ts +16 -3
  67. package/dist/server/auth/providers/stytch.js +4 -1
  68. package/dist/server/auth/providers/stytch.js.map +1 -1
  69. package/dist/server/auth/providers/verify-spy.d.ts +12 -0
  70. package/dist/server/auth/providers/verify-spy.js +21 -0
  71. package/dist/server/auth/providers/verify-spy.js.map +1 -0
  72. package/dist/server/auth/providers/workos.d.ts +28 -5
  73. package/dist/server/auth/providers/workos.js +6 -2
  74. package/dist/server/auth/providers/workos.js.map +1 -1
  75. package/dist/server/auth/setup.d.ts +1 -1
  76. package/dist/server/auth/setup.js +4 -5
  77. package/dist/server/auth/setup.js.map +1 -1
  78. package/dist/server/auth/setup.test.js +97 -57
  79. package/dist/server/auth/setup.test.js.map +1 -1
  80. package/dist/server/auth/verify.d.ts +42 -6
  81. package/dist/server/auth/verify.js +27 -3
  82. package/dist/server/auth/verify.js.map +1 -1
  83. package/dist/server/auth/verify.test.js +65 -0
  84. package/dist/server/auth/verify.test.js.map +1 -1
  85. package/dist/server/auth-extra.test-d.js +130 -0
  86. package/dist/server/auth-extra.test-d.js.map +1 -0
  87. package/dist/server/auth.d.ts +43 -6
  88. package/dist/server/auth.js +4 -5
  89. package/dist/server/auth.js.map +1 -1
  90. package/dist/server/build-manifest.test.js +7 -6
  91. package/dist/server/build-manifest.test.js.map +1 -1
  92. package/dist/server/content-helpers.d.ts +1 -1
  93. package/dist/server/content-helpers.js.map +1 -1
  94. package/dist/server/events.d.ts +113 -0
  95. package/dist/server/events.js +318 -0
  96. package/dist/server/events.js.map +1 -0
  97. package/dist/server/events.test.js +172 -0
  98. package/dist/server/events.test.js.map +1 -0
  99. package/dist/server/express.d.ts +23 -3
  100. package/dist/server/express.js +43 -32
  101. package/dist/server/express.js.map +1 -1
  102. package/dist/server/express.test.js +221 -103
  103. package/dist/server/express.test.js.map +1 -1
  104. package/dist/server/file-ref.d.ts +1 -1
  105. package/dist/server/file-ref.js +1 -1
  106. package/dist/server/file-ref.js.map +1 -1
  107. package/dist/server/form-input.d.ts +120 -0
  108. package/dist/server/form-input.js +89 -0
  109. package/dist/server/form-input.js.map +1 -0
  110. package/dist/server/index.d.ts +16 -8
  111. package/dist/server/index.js +9 -2
  112. package/dist/server/index.js.map +1 -1
  113. package/dist/server/mcp-errors.test.js +41 -0
  114. package/dist/server/mcp-errors.test.js.map +1 -0
  115. package/dist/server/middleware.d.ts +35 -10
  116. package/dist/server/middleware.js +33 -0
  117. package/dist/server/middleware.js.map +1 -1
  118. package/dist/server/middleware.test-d.js +1 -1
  119. package/dist/server/middleware.test-d.js.map +1 -1
  120. package/dist/server/middleware.test.js +242 -134
  121. package/dist/server/middleware.test.js.map +1 -1
  122. package/dist/server/register-tool.test.d.ts +1 -0
  123. package/dist/server/register-tool.test.js +230 -0
  124. package/dist/server/register-tool.test.js.map +1 -0
  125. package/dist/server/server.d.ts +337 -128
  126. package/dist/server/server.js +373 -305
  127. package/dist/server/server.js.map +1 -1
  128. package/dist/server/skills-integration.test.js +44 -21
  129. package/dist/server/skills-integration.test.js.map +1 -1
  130. package/dist/server/skills.d.ts +14 -10
  131. package/dist/server/skills.js +49 -39
  132. package/dist/server/skills.js.map +1 -1
  133. package/dist/server/skills.test.js +77 -44
  134. package/dist/server/skills.test.js.map +1 -1
  135. package/dist/server/templateHelper.d.ts +0 -3
  136. package/dist/server/templateHelper.js.map +1 -1
  137. package/dist/server/templates.generated.js +4 -8
  138. package/dist/server/templates.generated.js.map +1 -1
  139. package/dist/server/tool-extra.test.d.ts +1 -0
  140. package/dist/server/tool-extra.test.js +167 -0
  141. package/dist/server/tool-extra.test.js.map +1 -0
  142. package/dist/server/view-resource-resolution.test.js +18 -13
  143. package/dist/server/view-resource-resolution.test.js.map +1 -1
  144. package/dist/test/utils.d.ts +9 -11
  145. package/dist/test/utils.js +220 -201
  146. package/dist/test/utils.js.map +1 -1
  147. package/dist/test/view.test.js +41 -37
  148. package/dist/test/view.test.js.map +1 -1
  149. package/dist/views/index.d.ts +10 -0
  150. package/dist/views/index.js +3 -0
  151. package/dist/views/index.js.map +1 -0
  152. package/dist/{web/plugin → views}/scan-views.js +1 -1
  153. package/dist/views/scan-views.js.map +1 -0
  154. package/dist/views/scan-views.test.d.ts +1 -0
  155. package/dist/views/scan-views.test.js.map +1 -0
  156. package/dist/views/validate-view.d.ts +1 -0
  157. package/dist/{web/plugin → views}/validate-view.js +2 -2
  158. package/dist/views/validate-view.js.map +1 -0
  159. package/dist/views/validate-view.test.d.ts +1 -0
  160. package/dist/views/validate-view.test.js.map +1 -0
  161. package/dist/web/bridges/adaptor.d.ts +14 -3
  162. package/dist/web/bridges/adaptor.js +171 -30
  163. package/dist/web/bridges/adaptor.js.map +1 -1
  164. package/dist/web/bridges/adaptor.test.js +69 -13
  165. package/dist/web/bridges/adaptor.test.js.map +1 -1
  166. package/dist/web/bridges/apps-sdk/bridge.js +1 -1
  167. package/dist/web/bridges/apps-sdk/bridge.js.map +1 -1
  168. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.d.ts +4 -4
  169. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js +4 -4
  170. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js.map +1 -1
  171. package/dist/web/bridges/get-adaptor.test.js +2 -2
  172. package/dist/web/bridges/get-adaptor.test.js.map +1 -1
  173. package/dist/web/bridges/mcp-app/bridge.d.ts +1 -1
  174. package/dist/web/bridges/mcp-app/bridge.js +10 -3
  175. package/dist/web/bridges/mcp-app/bridge.js.map +1 -1
  176. package/dist/web/bridges/mcp-app/bridge.test.js +2 -2
  177. package/dist/web/bridges/mcp-app/bridge.test.js.map +1 -1
  178. package/dist/web/bridges/mcp-app/types.d.ts +18 -3
  179. package/dist/web/bridges/mcp-app/types.js.map +1 -1
  180. package/dist/web/bridges/mcp-app/use-mcp-app-context.d.ts +2 -2
  181. package/dist/web/bridges/mcp-app/use-mcp-app-context.js +1 -1
  182. package/dist/web/bridges/mcp-app/use-mcp-app-context.js.map +1 -1
  183. package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js +1 -1
  184. package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js.map +1 -1
  185. package/dist/web/bridges/mcp-app/view-tools.test.js +1 -1
  186. package/dist/web/bridges/mcp-app/view-tools.test.js.map +1 -1
  187. package/dist/web/bridges/types.d.ts +74 -16
  188. package/dist/web/bridges/types.js +1 -1
  189. package/dist/web/bridges/types.js.map +1 -1
  190. package/dist/web/create-store.test.js +2 -2
  191. package/dist/web/create-store.test.js.map +1 -1
  192. package/dist/web/data-llm.js +3 -2
  193. package/dist/web/data-llm.js.map +1 -1
  194. package/dist/web/data-llm.test.js +11 -4
  195. package/dist/web/data-llm.test.js.map +1 -1
  196. package/dist/web/generate-helpers.d.ts +23 -19
  197. package/dist/web/generate-helpers.js +21 -17
  198. package/dist/web/generate-helpers.js.map +1 -1
  199. package/dist/web/generate-helpers.test-d.js +3 -3
  200. package/dist/web/generate-helpers.test-d.js.map +1 -1
  201. package/dist/web/generate-helpers.test.js +2 -2
  202. package/dist/web/generate-helpers.test.js.map +1 -1
  203. package/dist/web/hooks/index.d.ts +6 -2
  204. package/dist/web/hooks/index.js +6 -2
  205. package/dist/web/hooks/index.js.map +1 -1
  206. package/dist/web/hooks/openai-extensions.test.d.ts +1 -0
  207. package/dist/web/hooks/openai-extensions.test.js +107 -0
  208. package/dist/web/hooks/openai-extensions.test.js.map +1 -0
  209. package/dist/web/hooks/use-call-tool.d.ts +2 -2
  210. package/dist/web/hooks/use-call-tool.js +15 -10
  211. package/dist/web/hooks/use-call-tool.js.map +1 -1
  212. package/dist/web/hooks/use-call-tool.test.js +15 -4
  213. package/dist/web/hooks/use-call-tool.test.js.map +1 -1
  214. package/dist/web/hooks/use-deep-link.d.ts +22 -0
  215. package/dist/web/hooks/use-deep-link.js +34 -0
  216. package/dist/web/hooks/use-deep-link.js.map +1 -0
  217. package/dist/web/hooks/use-display-mode.d.ts +1 -1
  218. package/dist/web/hooks/use-display-mode.js +1 -1
  219. package/dist/web/hooks/use-display-mode.js.map +1 -1
  220. package/dist/web/hooks/use-display-mode.test.js +1 -1
  221. package/dist/web/hooks/use-display-mode.test.js.map +1 -1
  222. package/dist/web/hooks/use-download.d.ts +1 -3
  223. package/dist/web/hooks/use-download.js +1 -2
  224. package/dist/web/hooks/use-download.js.map +1 -1
  225. package/dist/web/hooks/use-download.test.js +7 -7
  226. package/dist/web/hooks/use-download.test.js.map +1 -1
  227. package/dist/web/hooks/use-file-resource.d.ts +37 -0
  228. package/dist/web/hooks/use-file-resource.js +98 -0
  229. package/dist/web/hooks/use-file-resource.js.map +1 -0
  230. package/dist/web/hooks/use-file-resource.test.d.ts +1 -0
  231. package/dist/web/hooks/use-file-resource.test.js +65 -0
  232. package/dist/web/hooks/use-file-resource.test.js.map +1 -0
  233. package/dist/web/hooks/use-files.test.js +1 -1
  234. package/dist/web/hooks/use-files.test.js.map +1 -1
  235. package/dist/web/hooks/use-host.d.ts +44 -0
  236. package/dist/web/hooks/use-host.js +45 -0
  237. package/dist/web/hooks/use-host.js.map +1 -0
  238. package/dist/web/hooks/use-host.test.d.ts +1 -0
  239. package/dist/web/hooks/{use-host-info.test.js → use-host.test.js} +7 -7
  240. package/dist/web/hooks/use-host.test.js.map +1 -0
  241. package/dist/web/hooks/use-model-context.d.ts +44 -0
  242. package/dist/web/hooks/use-model-context.js +63 -0
  243. package/dist/web/hooks/use-model-context.js.map +1 -0
  244. package/dist/web/hooks/use-open-external.test.js +2 -2
  245. package/dist/web/hooks/use-open-external.test.js.map +1 -1
  246. package/dist/web/hooks/use-open-file.d.ts +20 -0
  247. package/dist/web/hooks/use-open-file.js +25 -0
  248. package/dist/web/hooks/use-open-file.js.map +1 -0
  249. package/dist/web/hooks/use-register-view-tool.d.ts +3 -4
  250. package/dist/web/hooks/use-register-view-tool.js +1 -1
  251. package/dist/web/hooks/use-register-view-tool.js.map +1 -1
  252. package/dist/web/hooks/use-request-close.test.js +1 -1
  253. package/dist/web/hooks/use-request-close.test.js.map +1 -1
  254. package/dist/web/hooks/use-request-modal.test.js +1 -1
  255. package/dist/web/hooks/use-request-modal.test.js.map +1 -1
  256. package/dist/web/hooks/use-request-size.d.ts +1 -1
  257. package/dist/web/hooks/use-request-size.js +1 -1
  258. package/dist/web/hooks/use-request-size.js.map +1 -1
  259. package/dist/web/hooks/use-request-size.test.js +1 -1
  260. package/dist/web/hooks/use-request-size.test.js.map +1 -1
  261. package/dist/web/hooks/use-send-follow-up-message.d.ts +8 -2
  262. package/dist/web/hooks/use-send-follow-up-message.js +6 -0
  263. package/dist/web/hooks/use-send-follow-up-message.js.map +1 -1
  264. package/dist/web/hooks/use-set-open-in-app-url.test.js +2 -8
  265. package/dist/web/hooks/use-set-open-in-app-url.test.js.map +1 -1
  266. package/dist/web/hooks/use-tool-info.d.ts +1 -20
  267. package/dist/web/hooks/use-tool-info.js +0 -1
  268. package/dist/web/hooks/use-tool-info.js.map +1 -1
  269. package/dist/web/hooks/use-tool-info.test-d.js +0 -5
  270. package/dist/web/hooks/use-tool-info.test-d.js.map +1 -1
  271. package/dist/web/hooks/use-tool-info.test.js +2 -7
  272. package/dist/web/hooks/use-tool-info.test.js.map +1 -1
  273. package/dist/web/hooks/use-user.d.ts +3 -2
  274. package/dist/web/hooks/use-user.js +4 -3
  275. package/dist/web/hooks/use-user.js.map +1 -1
  276. package/dist/web/hooks/use-user.test.js +5 -3
  277. package/dist/web/hooks/use-user.test.js.map +1 -1
  278. package/dist/web/hooks/use-view-state.js +19 -9
  279. package/dist/web/hooks/use-view-state.js.map +1 -1
  280. package/dist/web/hooks/use-view-state.test.js +33 -2
  281. package/dist/web/hooks/use-view-state.test.js.map +1 -1
  282. package/dist/web/hooks/use-viewport.d.ts +20 -0
  283. package/dist/web/hooks/use-viewport.js +21 -0
  284. package/dist/web/hooks/use-viewport.js.map +1 -0
  285. package/dist/web/hooks/use-viewport.test.d.ts +1 -0
  286. package/dist/web/hooks/{use-layout.test.js → use-viewport.test.js} +12 -32
  287. package/dist/web/hooks/use-viewport.test.js.map +1 -0
  288. package/dist/web/mount-view.d.ts +3 -2
  289. package/dist/web/mount-view.js +5 -8
  290. package/dist/web/mount-view.js.map +1 -1
  291. package/package.json +17 -13
  292. package/dist/web/hooks/use-host-info.d.ts +0 -22
  293. package/dist/web/hooks/use-host-info.js +0 -30
  294. package/dist/web/hooks/use-host-info.js.map +0 -1
  295. package/dist/web/hooks/use-host-info.test.js.map +0 -1
  296. package/dist/web/hooks/use-layout.d.ts +0 -24
  297. package/dist/web/hooks/use-layout.js +0 -25
  298. package/dist/web/hooks/use-layout.js.map +0 -1
  299. package/dist/web/hooks/use-layout.test.js.map +0 -1
  300. package/dist/web/plugin/data-llm.test.js +0 -81
  301. package/dist/web/plugin/data-llm.test.js.map +0 -1
  302. package/dist/web/plugin/plugin.d.ts +0 -39
  303. package/dist/web/plugin/plugin.js +0 -189
  304. package/dist/web/plugin/plugin.js.map +0 -1
  305. package/dist/web/plugin/scan-views.js.map +0 -1
  306. package/dist/web/plugin/scan-views.test.js.map +0 -1
  307. package/dist/web/plugin/transform-data-llm.d.ts +0 -12
  308. package/dist/web/plugin/transform-data-llm.js +0 -96
  309. package/dist/web/plugin/transform-data-llm.js.map +0 -1
  310. package/dist/web/plugin/transform-data-llm.test.js +0 -81
  311. package/dist/web/plugin/transform-data-llm.test.js.map +0 -1
  312. package/dist/web/plugin/validate-view.d.ts +0 -1
  313. package/dist/web/plugin/validate-view.js.map +0 -1
  314. package/dist/web/plugin/validate-view.test.js.map +0 -1
  315. /package/dist/{web/hooks/use-host-info.test.d.ts → context-warnings.test.d.ts} +0 -0
  316. /package/dist/{web/hooks/use-layout.test.d.ts → server/app.test.d.ts} +0 -0
  317. /package/dist/{web/plugin/scan-views.test.d.ts → server/auth/providers/authplane.test.d.ts} +0 -0
  318. /package/dist/{web/plugin/data-llm.test.d.ts → server/auth-extra.test-d.d.ts} +0 -0
  319. /package/dist/{web/plugin/transform-data-llm.test.d.ts → server/events.test.d.ts} +0 -0
  320. /package/dist/{web/plugin/validate-view.test.d.ts → server/mcp-errors.test.d.ts} +0 -0
  321. /package/dist/{web/plugin → views}/scan-views.d.ts +0 -0
  322. /package/dist/{web/plugin → views}/scan-views.test.js +0 -0
  323. /package/dist/{web/plugin → views}/validate-view.test.js +0 -0
@@ -1,6 +1,7 @@
1
1
  import http from "node:http";
2
+ import { Client, StreamableHTTPClientTransport, } from "@modelcontextprotocol/client";
2
3
  import { afterEach, describe, expect, it, vi } from "vitest";
3
- import { McpServer } from "./server.js";
4
+ import { Skybridge } from "./app.js";
4
5
  vi.mock("@skybridge/devtools", () => ({
5
6
  devtoolsStaticServer: () => ((_req, _res, next) => next()),
6
7
  }));
@@ -25,36 +26,49 @@ async function postMcp(port) {
25
26
  async function postApi(port) {
26
27
  return fetch(`http://localhost:${port}/api/test`, { method: "POST" });
27
28
  }
28
- describe("McpServer.express", () => {
29
+ describe("Skybridge.express", () => {
29
30
  it("exposes a ready Express app immediately after construction", () => {
30
- const server = new McpServer({ name: "t", version: "0.0.0" });
31
- expect(server.express).toBeDefined();
32
- expect(typeof server.express.use).toBe("function");
33
- expect(typeof server.express.get).toBe("function");
31
+ const app = new Skybridge({
32
+ name: "t",
33
+ version: "0.0.0",
34
+ handler: (server) => server,
35
+ });
36
+ expect(app.express).toBeDefined();
37
+ expect(typeof app.express.use).toBe("function");
38
+ expect(typeof app.express.get).toBe("function");
34
39
  });
35
- it("server.express.get registers a route reachable alongside /mcp", async () => {
40
+ it("app.express.get registers a route reachable alongside /mcp", async () => {
36
41
  const { createApp } = await import("./express.js");
37
- const server = new McpServer({ name: "t", version: "0.0.0" });
38
- server.express.get("/health", (_req, res) => {
42
+ const app = new Skybridge({
43
+ name: "t",
44
+ version: "0.0.0",
45
+ handler: (server) => server,
46
+ });
47
+ app.express.get("/health", (_req, res) => {
39
48
  res.json({ status: "ok" });
40
49
  });
41
50
  const httpServer = http.createServer();
42
- await createApp({ mcpServer: server, httpServer });
43
- const { port, server: listening } = await listen(server.express);
51
+ await createApp({ app, httpServer });
52
+ const { port, server: listening } = await listen(app.express);
44
53
  openServer = listening;
45
54
  const health = await fetch(`http://localhost:${port}/health`);
46
55
  expect(health.status).toBe(200);
56
+ expect(health.headers.get("x-powered-by")).toBe("skybridge");
47
57
  expect(await health.json()).toEqual({ status: "ok" });
48
58
  // /mcp still works (POST returns 200/4xx, not 404)
49
59
  const mcp = await postMcp(port);
50
60
  expect(mcp.status).not.toBe(404);
51
61
  });
52
- it("server.use and server.express.use produce the same registration order", async () => {
62
+ it("app.use and app.express.use produce the same registration order", async () => {
53
63
  const { createApp } = await import("./express.js");
54
64
  const callsA = [];
55
65
  const callsB = [];
56
- const buildServer = () => new McpServer({ name: "t", version: "0.0.0" });
57
- const sA = buildServer();
66
+ const buildApp = () => new Skybridge({
67
+ name: "t",
68
+ version: "0.0.0",
69
+ handler: (server) => server,
70
+ });
71
+ const sA = buildApp();
58
72
  sA.use((_req, _res, next) => {
59
73
  callsA.push("first");
60
74
  next();
@@ -63,7 +77,7 @@ describe("McpServer.express", () => {
63
77
  callsA.push("second");
64
78
  next();
65
79
  });
66
- const sB = buildServer();
80
+ const sB = buildApp();
67
81
  sB.express.use((_req, _res, next) => {
68
82
  callsB.push("first");
69
83
  next();
@@ -75,7 +89,7 @@ describe("McpServer.express", () => {
75
89
  for (const s of [sA, sB]) {
76
90
  s.express.get("/probe", (_req, res) => res.json({ ok: true }));
77
91
  const httpServer = http.createServer();
78
- await createApp({ mcpServer: s, httpServer });
92
+ await createApp({ app: s, httpServer });
79
93
  const { port, server: listening } = await listen(s.express);
80
94
  openServer = listening;
81
95
  await fetch(`http://localhost:${port}/probe`);
@@ -86,26 +100,32 @@ describe("McpServer.express", () => {
86
100
  });
87
101
  it("useOnError still wraps thrown /mcp errors after the route is mounted", async () => {
88
102
  const { createApp } = await import("./express.js");
89
- const server = new McpServer({ name: "t", version: "0.0.0" });
103
+ const app = new Skybridge({
104
+ name: "t",
105
+ version: "0.0.0",
106
+ handler: (server) => server,
107
+ });
90
108
  // Register the error handler BEFORE createApp — useOnError should still
91
109
  // apply it after /mcp, so /mcp errors hit it.
92
110
  const seen = [];
93
- server.useOnError((_err, _req, res, _next) => {
111
+ app.useOnError((_err, _req, res, _next) => {
94
112
  seen.push("useOnError");
95
113
  res.status(503).json({ from: "useOnError" });
96
114
  });
97
115
  // Force the /mcp handler to throw so the error pipeline runs.
98
- vi.spyOn(server, "connectStatelessTransport").mockRejectedValue(new Error("boom"));
116
+ app.use("/mcp", () => {
117
+ throw new Error("boom");
118
+ });
99
119
  const httpServer = http.createServer();
100
120
  await createApp({
101
- mcpServer: server,
121
+ app,
102
122
  httpServer,
103
- // Mirror what run() does: forward the McpServer's useOnError handlers
123
+ // Mirror what run() does: forward the app's useOnError handlers
104
124
  // to createApp so they get applied after /mcp.
105
125
  // biome-ignore lint/complexity/useLiteralKeys: test mirrors run() internals to verify useOnError ordering
106
- errorMiddleware: server["customErrorMiddleware"],
126
+ errorMiddleware: app["errorMiddleware"],
107
127
  });
108
- const { port, server: listening } = await listen(server.express);
128
+ const { port, server: listening } = await listen(app.express);
109
129
  openServer = listening;
110
130
  const res = await postMcp(port);
111
131
  expect(seen).toEqual(["useOnError"]);
@@ -113,7 +133,7 @@ describe("McpServer.express", () => {
113
133
  expect(await res.json()).toEqual({ from: "useOnError" });
114
134
  });
115
135
  });
116
- describe("McpServer JSON body parser options", () => {
136
+ describe("Skybridge JSON body parser options", () => {
117
137
  const largeBody = JSON.stringify({ data: "x".repeat(200 * 1024) });
118
138
  async function postEcho(port, body) {
119
139
  return fetch(`http://localhost:${port}/echo`, {
@@ -123,22 +143,31 @@ describe("McpServer JSON body parser options", () => {
123
143
  });
124
144
  }
125
145
  it("forwards json options to express.json", async () => {
126
- const server = new McpServer({ name: "t", version: "0.0.0" }, {}, { json: { limit: "10mb" } });
127
- server.express.post("/echo", (req, res) => {
146
+ const app = new Skybridge({
147
+ name: "t",
148
+ version: "0.0.0",
149
+ json: { limit: "10mb" },
150
+ handler: (server) => server,
151
+ });
152
+ app.express.post("/echo", (req, res) => {
128
153
  res.json({ received: req.body.data.length });
129
154
  });
130
- const { port, server: listening } = await listen(server.express);
155
+ const { port, server: listening } = await listen(app.express);
131
156
  openServer = listening;
132
157
  const res = await postEcho(port, largeBody);
133
158
  expect(res.status).toBe(200);
134
159
  expect(await res.json()).toEqual({ received: 200 * 1024 });
135
160
  });
136
161
  it("keeps the default 100kb limit when no options are passed", async () => {
137
- const server = new McpServer({ name: "t", version: "0.0.0" });
138
- server.express.post("/echo", (_req, res) => {
162
+ const app = new Skybridge({
163
+ name: "t",
164
+ version: "0.0.0",
165
+ handler: (server) => server,
166
+ });
167
+ app.express.post("/echo", (_req, res) => {
139
168
  res.json({ ok: true });
140
169
  });
141
- const { port, server: listening } = await listen(server.express);
170
+ const { port, server: listening } = await listen(app.express);
142
171
  openServer = listening;
143
172
  const res = await postEcho(port, largeBody);
144
173
  expect(res.status).toBe(413);
@@ -152,11 +181,15 @@ describe("createApp", () => {
152
181
  calls.push("custom");
153
182
  next();
154
183
  };
155
- const server = new McpServer({ name: "t", version: "0.0.0" });
156
- server.use(mw);
184
+ const app = new Skybridge({
185
+ name: "t",
186
+ version: "0.0.0",
187
+ handler: (server) => server,
188
+ });
189
+ app.use(mw);
157
190
  const httpServer = http.createServer();
158
- const app = await createApp({ mcpServer: server, httpServer });
159
- const { port, server: httpListening } = await listen(app);
191
+ const expressApp = await createApp({ app, httpServer });
192
+ const { port, server: httpListening } = await listen(expressApp);
160
193
  openServer = httpListening;
161
194
  await postMcp(port);
162
195
  expect(calls).toEqual(["custom"]);
@@ -168,11 +201,15 @@ describe("createApp", () => {
168
201
  calls.push("auth");
169
202
  next();
170
203
  };
171
- const server = new McpServer({ name: "t", version: "0.0.0" });
172
- server.use("/mcp", mw);
204
+ const app = new Skybridge({
205
+ name: "t",
206
+ version: "0.0.0",
207
+ handler: (server) => server,
208
+ });
209
+ app.use("/mcp", mw);
173
210
  const httpServer = http.createServer();
174
- const app = await createApp({ mcpServer: server, httpServer });
175
- const { port, server: httpListening } = await listen(app);
211
+ const expressApp = await createApp({ app, httpServer });
212
+ const { port, server: httpListening } = await listen(expressApp);
176
213
  openServer = httpListening;
177
214
  await postMcp(port);
178
215
  expect(calls).toEqual(["auth"]);
@@ -184,11 +221,15 @@ describe("createApp", () => {
184
221
  calls.push("reject");
185
222
  res.status(401).json({ error: "Unauthorized" });
186
223
  };
187
- const server = new McpServer({ name: "t", version: "0.0.0" });
188
- server.use("/mcp", reject);
224
+ const app = new Skybridge({
225
+ name: "t",
226
+ version: "0.0.0",
227
+ handler: (server) => server,
228
+ });
229
+ app.use("/mcp", reject);
189
230
  const httpServer = http.createServer();
190
- const app = await createApp({ mcpServer: server, httpServer });
191
- const { port, server: httpListening } = await listen(app);
231
+ const expressApp = await createApp({ app, httpServer });
232
+ const { port, server: httpListening } = await listen(expressApp);
192
233
  openServer = httpListening;
193
234
  const res = await postMcp(port);
194
235
  expect(calls).toEqual(["reject"]);
@@ -206,12 +247,16 @@ describe("createApp", () => {
206
247
  calls.push("B");
207
248
  next();
208
249
  };
209
- const server = new McpServer({ name: "t", version: "0.0.0" });
210
- server.use(mwA);
211
- server.use(mwB);
250
+ const app = new Skybridge({
251
+ name: "t",
252
+ version: "0.0.0",
253
+ handler: (server) => server,
254
+ });
255
+ app.use(mwA);
256
+ app.use(mwB);
212
257
  const httpServer = http.createServer();
213
- const app = await createApp({ mcpServer: server, httpServer });
214
- const { port, server: httpListening } = await listen(app);
258
+ const expressApp = await createApp({ app, httpServer });
259
+ const { port, server: httpListening } = await listen(expressApp);
215
260
  openServer = httpListening;
216
261
  await postMcp(port);
217
262
  expect(calls).toEqual(["A", "B"]);
@@ -223,11 +268,15 @@ describe("createApp", () => {
223
268
  calls.push("api");
224
269
  next();
225
270
  };
226
- const server = new McpServer({ name: "t", version: "0.0.0" });
227
- server.use("/api", apiMw);
271
+ const app = new Skybridge({
272
+ name: "t",
273
+ version: "0.0.0",
274
+ handler: (server) => server,
275
+ });
276
+ app.use("/api", apiMw);
228
277
  const httpServer = http.createServer();
229
- const app = await createApp({ mcpServer: server, httpServer });
230
- const { port, server: httpListening } = await listen(app);
278
+ const expressApp = await createApp({ app, httpServer });
279
+ const { port, server: httpListening } = await listen(expressApp);
231
280
  openServer = httpListening;
232
281
  // Hit /mcp — the /api middleware should NOT fire
233
282
  await postMcp(port);
@@ -240,11 +289,15 @@ describe("createApp", () => {
240
289
  router.get("/health", (_req, res) => {
241
290
  res.json({ status: "ok" });
242
291
  });
243
- const server = new McpServer({ name: "t", version: "0.0.0" });
244
- server.use(router);
292
+ const app = new Skybridge({
293
+ name: "t",
294
+ version: "0.0.0",
295
+ handler: (server) => server,
296
+ });
297
+ app.use(router);
245
298
  const httpServer = http.createServer();
246
- const app = await createApp({ mcpServer: server, httpServer });
247
- const { port, server: httpListening } = await listen(app);
299
+ const expressApp = await createApp({ app, httpServer });
300
+ const { port, server: httpListening } = await listen(expressApp);
248
301
  openServer = httpListening;
249
302
  const res = await fetch(`http://localhost:${port}/health`);
250
303
  expect(res.status).toBe(200);
@@ -257,11 +310,15 @@ describe("createApp", () => {
257
310
  router.get("/data", (_req, res) => {
258
311
  res.json({ value: 42 });
259
312
  });
260
- const server = new McpServer({ name: "t", version: "0.0.0" });
261
- server.use("/api", router);
313
+ const app = new Skybridge({
314
+ name: "t",
315
+ version: "0.0.0",
316
+ handler: (server) => server,
317
+ });
318
+ app.use("/api", router);
262
319
  const httpServer = http.createServer();
263
- const app = await createApp({ mcpServer: server, httpServer });
264
- const { port, server: httpListening } = await listen(app);
320
+ const expressApp = await createApp({ app, httpServer });
321
+ const { port, server: httpListening } = await listen(expressApp);
265
322
  openServer = httpListening;
266
323
  const res = await fetch(`http://localhost:${port}/api/data`);
267
324
  expect(res.status).toBe(200);
@@ -272,11 +329,15 @@ describe("createApp", () => {
272
329
  const throwing = () => {
273
330
  throw new Error("boom");
274
331
  };
275
- const server = new McpServer({ name: "t", version: "0.0.0" });
276
- server.use("/explode", throwing);
332
+ const app = new Skybridge({
333
+ name: "t",
334
+ version: "0.0.0",
335
+ handler: (server) => server,
336
+ });
337
+ app.use("/explode", throwing);
277
338
  const httpServer = http.createServer();
278
- const app = await createApp({ mcpServer: server, httpServer });
279
- const { port, server: httpListening } = await listen(app);
339
+ const expressApp = await createApp({ app, httpServer });
340
+ const { port, server: httpListening } = await listen(expressApp);
280
341
  openServer = httpListening;
281
342
  const res = await fetch(`http://localhost:${port}/explode`);
282
343
  expect(res.status).toBe(500);
@@ -287,14 +348,19 @@ describe("createApp", () => {
287
348
  it("returns 500 JSON-RPC error when the MCP handler throws and no error middleware is registered", async () => {
288
349
  const { createApp } = await import("./express.js");
289
350
  const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
290
- const mcpServer = new McpServer({ name: "t", version: "0.0.0" });
291
- // Force the express-level error path: make connectStatelessTransport
292
- // reject so the request handler hits its try/catch and calls next(error),
293
- // which lands in the default /mcp error handler.
294
- vi.spyOn(mcpServer, "connectStatelessTransport").mockRejectedValue(new Error("boom"));
351
+ const app = new Skybridge({
352
+ name: "t",
353
+ version: "0.0.0",
354
+ handler: (server) => server,
355
+ });
356
+ // Force the express-level error path: make a /mcp middleware throw so the
357
+ // error pipeline runs and lands in the default /mcp error handler.
358
+ app.use("/mcp", () => {
359
+ throw new Error("boom");
360
+ });
295
361
  const httpServer = http.createServer();
296
- const app = await createApp({ mcpServer, httpServer });
297
- const { port, server: httpListening } = await listen(app);
362
+ const expressApp = await createApp({ app, httpServer });
363
+ const { port, server: httpListening } = await listen(expressApp);
298
364
  openServer = httpListening;
299
365
  const res = await postMcp(port);
300
366
  expect(res.status).toBe(500);
@@ -313,15 +379,21 @@ describe("createApp", () => {
313
379
  calls.push("error-handler");
314
380
  res.status(503).json({ custom: true });
315
381
  };
316
- const mcpServer = new McpServer({ name: "t", version: "0.0.0" });
317
- vi.spyOn(mcpServer, "connectStatelessTransport").mockRejectedValue(new Error("boom"));
382
+ const app = new Skybridge({
383
+ name: "t",
384
+ version: "0.0.0",
385
+ handler: (server) => server,
386
+ });
387
+ app.use("/mcp", () => {
388
+ throw new Error("boom");
389
+ });
318
390
  const httpServer = http.createServer();
319
- const app = await createApp({
320
- mcpServer,
391
+ const expressApp = await createApp({
392
+ app,
321
393
  httpServer,
322
394
  errorMiddleware: [{ handlers: [errorHandler] }],
323
395
  });
324
- const { port, server: httpListening } = await listen(app);
396
+ const { port, server: httpListening } = await listen(expressApp);
325
397
  openServer = httpListening;
326
398
  const res = await postMcp(port);
327
399
  expect(calls).toEqual(["error-handler"]);
@@ -338,16 +410,22 @@ describe("createApp", () => {
338
410
  const throwingApiRoute = (_req, _res, next) => {
339
411
  next(new Error("api error"));
340
412
  };
341
- const mcpServer = new McpServer({ name: "t", version: "0.0.0" });
342
- vi.spyOn(mcpServer, "connectStatelessTransport").mockRejectedValue(new Error("boom"));
343
- mcpServer.use("/api/test", throwingApiRoute);
413
+ const app = new Skybridge({
414
+ name: "t",
415
+ version: "0.0.0",
416
+ handler: (server) => server,
417
+ });
418
+ app.use("/mcp", () => {
419
+ throw new Error("boom");
420
+ });
421
+ app.use("/api/test", throwingApiRoute);
344
422
  const httpServer = http.createServer();
345
- const app = await createApp({
346
- mcpServer,
423
+ const expressApp = await createApp({
424
+ app,
347
425
  httpServer,
348
426
  errorMiddleware: [{ path: "/mcp", handlers: [mcpErrorHandler] }],
349
427
  });
350
- const { port, server: httpListening } = await listen(app);
428
+ const { port, server: httpListening } = await listen(expressApp);
351
429
  openServer = httpListening;
352
430
  const mcpRes = await postMcp(port);
353
431
  expect(calls).toEqual(["mcp-error-handler"]);
@@ -361,20 +439,20 @@ describe("createApp", () => {
361
439
  });
362
440
  it("handles concurrent /mcp requests without 'Already connected to a transport'", async () => {
363
441
  const { createApp } = await import("./express.js");
364
- const mcpServer = new McpServer({
365
- name: "concurrent-test",
366
- version: "0.0.0",
367
- });
368
442
  // Slow tool: keeps the underlying transport bound long enough to overlap
369
443
  // with concurrent requests, exposing the shared-McpServer race.
370
- mcpServer.registerTool({ name: "slow", description: "slow" }, async () => {
371
- await new Promise((r) => setTimeout(r, 50));
372
- return { content: [{ type: "text", text: "done" }] };
444
+ const app = new Skybridge({
445
+ name: "concurrent-test",
446
+ version: "0.0.0",
447
+ handler: (server) => server.registerTool({ name: "slow", description: "slow" }, async () => {
448
+ await new Promise((r) => setTimeout(r, 50));
449
+ return { content: [{ type: "text", text: "done" }] };
450
+ }),
373
451
  });
374
452
  const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
375
453
  const httpServer = http.createServer();
376
- const app = await createApp({ mcpServer, httpServer });
377
- const { port, server } = await listen(app);
454
+ const expressApp = await createApp({ app, httpServer });
455
+ const { port, server } = await listen(expressApp);
378
456
  openServer = server;
379
457
  const callBody = (id) => JSON.stringify({
380
458
  jsonrpc: "2.0",
@@ -397,19 +475,23 @@ describe("createApp", () => {
397
475
  });
398
476
  });
399
477
  describe("createApp Vercel mode", () => {
400
- it("server.run() returns the Express app without binding a port when VERCEL=1", async () => {
478
+ it("app.run() returns the Express app without binding a port when VERCEL=1", async () => {
401
479
  const prevVercel = process.env.VERCEL;
402
480
  const prevEnv = process.env.NODE_ENV;
403
481
  process.env.VERCEL = "1";
404
482
  process.env.NODE_ENV = "production";
405
483
  try {
406
484
  vi.resetModules();
407
- const { McpServer: Reloaded } = await import("./server.js");
408
- const server = new Reloaded({ name: "t", version: "0.0.0" });
409
- const result = await server.run();
485
+ const { Skybridge: Reloaded } = await import("./app.js");
486
+ const app = new Reloaded({
487
+ name: "t",
488
+ version: "0.0.0",
489
+ handler: (server) => server,
490
+ });
491
+ const result = await app.run();
410
492
  expect(typeof result).toBe("function");
411
- expect(result).toBe(server.express);
412
- const { port, server: listening } = await listen(server.express);
493
+ expect(result).toBe(app.express);
494
+ const { port, server: listening } = await listen(app.express);
413
495
  openServer = listening;
414
496
  const res = await postMcp(port);
415
497
  expect(res.status).not.toBe(404);
@@ -444,10 +526,14 @@ describe("createApp tunnel routes", () => {
444
526
  process.env.__TUNNEL_CONTROL_PORT = String(controlPort);
445
527
  try {
446
528
  const { createApp } = await import("./express.js");
447
- const mcpServer = new McpServer({ name: "t", version: "0.0.0" });
529
+ const app = new Skybridge({
530
+ name: "t",
531
+ version: "0.0.0",
532
+ handler: (server) => server,
533
+ });
448
534
  const httpServer = http.createServer();
449
- const app = await createApp({ mcpServer, httpServer });
450
- const { port, server } = await listen(app);
535
+ const expressApp = await createApp({ app, httpServer });
536
+ const { port, server } = await listen(expressApp);
451
537
  openServer = server;
452
538
  const res = await fetch(`http://localhost:${port}/__skybridge/tunnel`, {
453
539
  method: "POST",
@@ -471,11 +557,15 @@ describe("createApp tunnel routes", () => {
471
557
  try {
472
558
  vi.resetModules();
473
559
  const { createApp } = await import("./express.js");
474
- const { McpServer: ReloadedMcpServer } = await import("./server.js");
475
- const mcpServer = new ReloadedMcpServer({ name: "t", version: "0.0.0" });
560
+ const { Skybridge: ReloadedSkybridge } = await import("./app.js");
561
+ const app = new ReloadedSkybridge({
562
+ name: "t",
563
+ version: "0.0.0",
564
+ handler: (server) => server,
565
+ });
476
566
  const httpServer = http.createServer();
477
- const app = await createApp({ mcpServer, httpServer });
478
- const { port, server } = await listen(app);
567
+ const expressApp = await createApp({ app, httpServer });
568
+ const { port, server } = await listen(expressApp);
479
569
  openServer = server;
480
570
  const res = await fetch(`http://localhost:${port}/__skybridge/tunnel`, {
481
571
  method: "POST",
@@ -488,4 +578,32 @@ describe("createApp tunnel routes", () => {
488
578
  }
489
579
  });
490
580
  });
581
+ describe("createApp mount path", () => {
582
+ it("serves /mcp with the mount path intact on the request URL", async () => {
583
+ const { createApp } = await import("./express.js");
584
+ const app = new Skybridge({
585
+ name: "t",
586
+ version: "0.0.0",
587
+ handler: (server) => server.registerTool({
588
+ name: "echo-url",
589
+ description: "Echoes the request URL.",
590
+ inputSchema: {},
591
+ }, (_args, extra) => ({
592
+ content: [{ type: "text", text: extra.http?.req?.url ?? "" }],
593
+ })),
594
+ });
595
+ const httpServer = http.createServer();
596
+ const expressApp = await createApp({ app, httpServer });
597
+ const { port, server } = await listen(expressApp);
598
+ openServer = server;
599
+ const client = new Client({ name: "test-client", version: "0.0.0" });
600
+ await client.connect(new StreamableHTTPClientTransport(new URL(`http://localhost:${port}/mcp`)));
601
+ const result = (await client.callTool({
602
+ name: "echo-url",
603
+ arguments: {},
604
+ }));
605
+ await client.close();
606
+ expect(new URL(result.content[0]?.text ?? "").pathname).toBe("/mcp");
607
+ });
608
+ });
491
609
  //# sourceMappingURL=express.test.js.map