skybridge 0.0.0-dev.81fd90a → 0.0.0-dev.8226541

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