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 +1 @@
1
- {"version":3,"file":"verify.test.js","sourceRoot":"","sources":["../../../src/server/auth/verify.test.ts"],"names":[],"mappings":"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","sourcesContent":["// @vitest-environment node\nimport http from \"node:http\";\nimport * as jose from \"jose\";\nimport { afterEach, describe, expect, it } from \"vitest\";\nimport { createJwksVerifier } from \"./verify.js\";\n\nconst ISSUER = \"https://issuer.test\";\nconst AUDIENCE = \"api://default\";\n\nlet jwksServer: http.Server | undefined;\nafterEach(() => jwksServer?.close());\n\nasync function startJwks() {\n const { publicKey, privateKey } = await jose.generateKeyPair(\"RS256\");\n const jwk = {\n ...(await jose.exportJWK(publicKey)),\n kid: \"test-key\",\n alg: \"RS256\",\n use: \"sig\",\n };\n const server = http.createServer((_req, res) => {\n res.setHeader(\"content-type\", \"application/json\");\n res.end(JSON.stringify({ keys: [jwk] }));\n });\n await new Promise<void>((resolve) => server.listen(0, resolve));\n jwksServer = server;\n const port = (server.address() as { port: number }).port;\n return { privateKey, jwksUri: `http://localhost:${port}/jwks` };\n}\n\nfunction sign(\n key: CryptoKey,\n claims: Record<string, unknown>,\n opts: { issuer?: string; audience?: string; expiresAt?: string } = {},\n) {\n return new jose.SignJWT(claims)\n .setProtectedHeader({ alg: \"RS256\", kid: \"test-key\" })\n .setIssuer(opts.issuer ?? ISSUER)\n .setAudience(opts.audience ?? AUDIENCE)\n .setExpirationTime(opts.expiresAt ?? \"1h\")\n .sign(key);\n}\n\nit(\"rejects a config with no issuer\", () => {\n expect(() => createJwksVerifier({ issuer: \"\" })).toThrow(\n /requires an `issuer`/,\n );\n});\n\ndescribe(\"createJwksVerifier\", () => {\n it(\"verifies a valid token and maps claims to AuthInfo\", async () => {\n const { privateKey, jwksUri } = await startJwks();\n const verifier = createJwksVerifier({\n issuer: ISSUER,\n audience: AUDIENCE,\n jwksUri,\n });\n const token = await sign(privateKey, {\n client_id: \"client-1\",\n scope: \"openid email\",\n sub: \"user-1\",\n email: \"a@b.test\",\n });\n\n const auth = await verifier.verifyAccessToken(token);\n\n expect(auth.token).toBe(token);\n expect(auth.clientId).toBe(\"client-1\");\n expect(auth.scopes).toEqual([\"openid\", \"email\"]);\n expect(auth.extra?.subject).toBe(\"user-1\");\n expect(auth.extra?.email).toBe(\"a@b.test\");\n });\n\n it(\"rejects a token with the wrong audience\", async () => {\n const { privateKey, jwksUri } = await startJwks();\n const verifier = createJwksVerifier({\n issuer: ISSUER,\n audience: AUDIENCE,\n jwksUri,\n });\n const token = await sign(\n privateKey,\n { client_id: \"c\" },\n { audience: \"api://other\" },\n );\n\n await expect(verifier.verifyAccessToken(token)).rejects.toThrow(\n /Token verification failed/,\n );\n });\n\n // jose quotes claim names — `\"exp\" claim timestamp check failed`, `unexpected\n // \"aud\" claim value`. Those quotes would close `error_description=\"…\"` early,\n // dropping the `resource_metadata` that MCP clients start discovery from.\n it.each([\n [\n \"an expired token\",\n (key: CryptoKey) => sign(key, {}, { expiresAt: \"-1h\" }),\n // jose: `\"exp\" claim timestamp check failed`\n \"Token verification failed: exp claim timestamp check failed\",\n ],\n [\n \"a token issued for another resource\",\n (key: CryptoKey) => sign(key, {}, { audience: \"api://other\" }),\n // jose: `unexpected \"aud\" claim value`\n \"Token verification failed: unexpected aud claim value\",\n ],\n [\n \"a token from another issuer\",\n (key: CryptoKey) => sign(key, {}, { issuer: \"https://other.test\" }),\n // jose: `unexpected \"iss\" claim value`\n \"Token verification failed: unexpected iss claim value\",\n ],\n [\n \"a token carrying no aud claim\",\n (key: CryptoKey) =>\n new jose.SignJWT({})\n .setProtectedHeader({ alg: \"RS256\", kid: \"test-key\" })\n .setIssuer(ISSUER)\n .setExpirationTime(\"1h\")\n .sign(key),\n // jose: `missing required \"aud\" claim`\n \"Token verification failed: missing required aud claim\",\n ],\n ])(\n \"keeps the message safe inside the challenge for %s\",\n async (_, mint, expected) => {\n const { privateKey, jwksUri } = await startJwks();\n const verifier = createJwksVerifier({\n issuer: ISSUER,\n audience: AUDIENCE,\n jwksUri,\n });\n\n const error = await verifier\n .verifyAccessToken(await mint(privateKey))\n .then(\n () => undefined,\n (e: Error) => e,\n );\n\n expect(error?.message).toBe(expected);\n // OAuth 2.1 §5.3.1: %x20-21 / %x23-5B / %x5D-7E and nothing else.\n expect(error?.message).not.toMatch(/[^\\x20-\\x21\\x23-\\x5B\\x5D-\\x7E]/);\n },\n );\n\n it(\"skips the aud check when no audience is configured (e.g. Clerk)\", async () => {\n const { privateKey, jwksUri } = await startJwks();\n const verifier = createJwksVerifier({ issuer: ISSUER, jwksUri });\n // Clerk-shaped access token: no `aud` claim at all.\n const token = await new jose.SignJWT({ client_id: \"c\", sub: \"u\" })\n .setProtectedHeader({ alg: \"RS256\", kid: \"test-key\" })\n .setIssuer(ISSUER)\n .setExpirationTime(\"1h\")\n .sign(privateKey);\n\n const auth = await verifier.verifyAccessToken(token);\n expect(auth.clientId).toBe(\"c\");\n expect(auth.extra?.subject).toBe(\"u\");\n });\n\n it(\"parses array scope claims and trims extra whitespace\", async () => {\n const { privateKey, jwksUri } = await startJwks();\n const verifier = createJwksVerifier({\n issuer: ISSUER,\n audience: AUDIENCE,\n jwksUri,\n });\n\n const arrayToken = await sign(privateKey, {\n scope: [\"openid\", \"email\"],\n });\n expect((await verifier.verifyAccessToken(arrayToken)).scopes).toEqual([\n \"openid\",\n \"email\",\n ]);\n\n const messyToken = await sign(privateKey, { scope: \" openid email \" });\n expect((await verifier.verifyAccessToken(messyToken)).scopes).toEqual([\n \"openid\",\n \"email\",\n ]);\n });\n});\n"]}
1
+ {"version":3,"file":"verify.test.js","sourceRoot":"","sources":["../../../src/server/auth/verify.test.ts"],"names":[],"mappings":"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","sourcesContent":["// @vitest-environment node\nimport http from \"node:http\";\nimport * as jose from \"jose\";\nimport { afterEach, describe, expect, it } from \"vitest\";\nimport { createJwksVerifier } from \"./verify.js\";\n\nconst ISSUER = \"https://issuer.test\";\nconst AUDIENCE = \"api://default\";\n\nlet jwksServer: http.Server | undefined;\nafterEach(() => jwksServer?.close());\n\nasync function startJwks() {\n const { publicKey, privateKey } = await jose.generateKeyPair(\"RS256\");\n const jwk = {\n ...(await jose.exportJWK(publicKey)),\n kid: \"test-key\",\n alg: \"RS256\",\n use: \"sig\",\n };\n const server = http.createServer((_req, res) => {\n res.setHeader(\"content-type\", \"application/json\");\n res.end(JSON.stringify({ keys: [jwk] }));\n });\n await new Promise<void>((resolve) => server.listen(0, resolve));\n jwksServer = server;\n const port = (server.address() as { port: number }).port;\n return { privateKey, jwksUri: `http://localhost:${port}/jwks` };\n}\n\nfunction sign(\n key: CryptoKey,\n claims: Record<string, unknown>,\n opts: { issuer?: string; audience?: string; expiresAt?: string } = {},\n) {\n return new jose.SignJWT(claims)\n .setProtectedHeader({ alg: \"RS256\", kid: \"test-key\" })\n .setIssuer(opts.issuer ?? ISSUER)\n .setAudience(opts.audience ?? AUDIENCE)\n .setExpirationTime(opts.expiresAt ?? \"1h\")\n .sign(key);\n}\n\nit(\"rejects a config with no issuer\", () => {\n expect(() => createJwksVerifier({ issuer: \"\" })).toThrow(\n /requires an `issuer`/,\n );\n});\n\ndescribe(\"createJwksVerifier\", () => {\n it(\"verifies a valid token and maps claims to AuthInfo\", async () => {\n const { privateKey, jwksUri } = await startJwks();\n const verifier = createJwksVerifier({\n issuer: ISSUER,\n audience: AUDIENCE,\n jwksUri,\n });\n const token = await sign(privateKey, {\n client_id: \"client-1\",\n scope: \"openid email\",\n sub: \"user-1\",\n email: \"a@b.test\",\n });\n\n const auth = await verifier.verifyAccessToken(token);\n\n expect(auth.token).toBe(token);\n expect(auth.clientId).toBe(\"client-1\");\n expect(auth.scopes).toEqual([\"openid\", \"email\"]);\n expect(auth.extra?.subject).toBe(\"user-1\");\n expect(auth.extra?.email).toBe(\"a@b.test\");\n });\n\n it(\"rejects a token with the wrong audience\", async () => {\n const { privateKey, jwksUri } = await startJwks();\n const verifier = createJwksVerifier({\n issuer: ISSUER,\n audience: AUDIENCE,\n jwksUri,\n });\n const token = await sign(\n privateKey,\n { client_id: \"c\" },\n { audience: \"api://other\" },\n );\n\n await expect(verifier.verifyAccessToken(token)).rejects.toThrow(\n /Token verification failed/,\n );\n });\n\n // jose quotes claim names — `\"exp\" claim timestamp check failed`, `unexpected\n // \"aud\" claim value`. Those quotes would close `error_description=\"…\"` early,\n // dropping the `resource_metadata` that MCP clients start discovery from.\n it.each([\n [\n \"an expired token\",\n (key: CryptoKey) => sign(key, {}, { expiresAt: \"-1h\" }),\n // jose: `\"exp\" claim timestamp check failed`\n \"Token verification failed: exp claim timestamp check failed\",\n ],\n [\n \"a token issued for another resource\",\n (key: CryptoKey) => sign(key, {}, { audience: \"api://other\" }),\n // jose: `unexpected \"aud\" claim value`\n \"Token verification failed: unexpected aud claim value\",\n ],\n [\n \"a token from another issuer\",\n (key: CryptoKey) => sign(key, {}, { issuer: \"https://other.test\" }),\n // jose: `unexpected \"iss\" claim value`\n \"Token verification failed: unexpected iss claim value\",\n ],\n [\n \"a token carrying no aud claim\",\n (key: CryptoKey) =>\n new jose.SignJWT({})\n .setProtectedHeader({ alg: \"RS256\", kid: \"test-key\" })\n .setIssuer(ISSUER)\n .setExpirationTime(\"1h\")\n .sign(key),\n // jose: `missing required \"aud\" claim`\n \"Token verification failed: missing required aud claim\",\n ],\n ])(\n \"keeps the message safe inside the challenge for %s\",\n async (_, mint, expected) => {\n const { privateKey, jwksUri } = await startJwks();\n const verifier = createJwksVerifier({\n issuer: ISSUER,\n audience: AUDIENCE,\n jwksUri,\n });\n\n const error = await verifier\n .verifyAccessToken(await mint(privateKey))\n .then(\n () => undefined,\n (e: Error) => e,\n );\n\n expect(error?.message).toBe(expected);\n // OAuth 2.1 §5.3.1: %x20-21 / %x23-5B / %x5D-7E and nothing else.\n expect(error?.message).not.toMatch(/[^\\x20-\\x21\\x23-\\x5B\\x5D-\\x7E]/);\n },\n );\n\n it(\"accepts a token minted for any of several audiences\", async () => {\n const { privateKey, jwksUri } = await startJwks();\n // A server reached at a local port and through a dev tunnel: tokens carry\n // whichever resource the client discovered.\n const verifier = createJwksVerifier({\n issuer: ISSUER,\n audience: [AUDIENCE, \"https://tunnel.test\"],\n jwksUri,\n });\n\n const tunnelToken = await sign(\n privateKey,\n { client_id: \"c\" },\n { audience: \"https://tunnel.test\" },\n );\n expect((await verifier.verifyAccessToken(tunnelToken)).clientId).toBe(\"c\");\n\n const localToken = await sign(privateKey, { client_id: \"c\" });\n expect((await verifier.verifyAccessToken(localToken)).clientId).toBe(\"c\");\n\n const otherToken = await sign(privateKey, {}, { audience: \"api://other\" });\n await expect(verifier.verifyAccessToken(otherToken)).rejects.toThrow(\n /unexpected {2}aud {2}claim value/,\n );\n });\n\n it(\"skips the aud check when no audience is configured (e.g. Clerk)\", async () => {\n const { privateKey, jwksUri } = await startJwks();\n const verifier = createJwksVerifier({ issuer: ISSUER, jwksUri });\n // Clerk-shaped access token: no `aud` claim at all.\n const token = await new jose.SignJWT({ client_id: \"c\", sub: \"u\" })\n .setProtectedHeader({ alg: \"RS256\", kid: \"test-key\" })\n .setIssuer(ISSUER)\n .setExpirationTime(\"1h\")\n .sign(privateKey);\n\n const auth = await verifier.verifyAccessToken(token);\n expect(auth.clientId).toBe(\"c\");\n expect(auth.extra?.subject).toBe(\"u\");\n });\n\n it(\"parses array scope claims and trims extra whitespace\", async () => {\n const { privateKey, jwksUri } = await startJwks();\n const verifier = createJwksVerifier({\n issuer: ISSUER,\n audience: AUDIENCE,\n jwksUri,\n });\n\n const arrayToken = await sign(privateKey, {\n scope: [\"openid\", \"email\"],\n });\n expect((await verifier.verifyAccessToken(arrayToken)).scopes).toEqual([\n \"openid\",\n \"email\",\n ]);\n\n const messyToken = await sign(privateKey, { scope: \" openid email \" });\n expect((await verifier.verifyAccessToken(messyToken)).scopes).toEqual([\n \"openid\",\n \"email\",\n ]);\n });\n});\n"]}
@@ -1,38 +1,55 @@
1
1
  import { expectTypeOf, test } from "vitest";
2
2
  import { z } from "zod";
3
+ import { Skybridge } from "./app.js";
3
4
  import { customProvider } from "./auth/providers/custom.js";
4
5
  import { workosProvider } from "./auth/providers/workos.js";
5
- import { McpServer } from "./server.js";
6
- const workosOAuth = await workosProvider({ domain: "d", audience: "a" });
6
+ const workosOAuth = await workosProvider({
7
+ domain: "d",
8
+ audience: "a",
9
+ }).resolve();
7
10
  const customOAuth = await workosProvider({
8
11
  domain: "d",
9
12
  audience: "a",
10
- });
13
+ }).resolve();
11
14
  test("a server with no oauth keeps the untyped claim bag", () => {
12
- new McpServer({ name: "t", version: "0" }).registerTool({ name: "plain", inputSchema: { q: z.string() } }, (_args, extra) => {
13
- expectTypeOf(extra.http?.authInfo?.extra).toEqualTypeOf();
14
- return { content: "ok" };
15
+ new Skybridge({
16
+ name: "t",
17
+ version: "0",
18
+ handler: (server) => server.registerTool({ name: "plain", inputSchema: { q: z.string() } }, (_args, extra) => {
19
+ expectTypeOf(extra.http?.authInfo?.extra).toEqualTypeOf();
20
+ return { content: "ok" };
21
+ }),
15
22
  });
16
23
  });
17
24
  test("provider claims reach tool handlers", () => {
18
- new McpServer({ name: "t", version: "0" }, {}, { oauth: workosOAuth })
19
- .registerTool({ name: "a", inputSchema: {} }, (_args, extra) => {
20
- expectTypeOf(extra.http?.authInfo?.extra?.org_id).toEqualTypeOf();
21
- expectTypeOf(extra.http?.authInfo?.extra?.permissions).toEqualTypeOf();
22
- // @ts-expect-error not a WorkOS claim
23
- extra.http?.authInfo?.extra?.nope;
24
- return { content: "a" };
25
- })
26
- .registerTool({ name: "b", inputSchema: {} }, (_args, extra) => {
27
- expectTypeOf(extra.http?.authInfo?.extra?.sid).toEqualTypeOf();
28
- return { content: "b" };
25
+ new Skybridge({
26
+ name: "t",
27
+ version: "0",
28
+ oauth: workosOAuth,
29
+ handler: (server) => server
30
+ .registerTool({ name: "a", inputSchema: {} }, (_args, extra) => {
31
+ expectTypeOf(extra.http?.authInfo?.extra?.org_id).toEqualTypeOf();
32
+ expectTypeOf(extra.http?.authInfo?.extra?.permissions).toEqualTypeOf();
33
+ // @ts-expect-error not a WorkOS claim
34
+ extra.http?.authInfo?.extra?.nope;
35
+ return { content: "a" };
36
+ })
37
+ .registerTool({ name: "b", inputSchema: {} }, (_args, extra) => {
38
+ expectTypeOf(extra.http?.authInfo?.extra?.sid).toEqualTypeOf();
39
+ return { content: "b" };
40
+ }),
29
41
  });
30
42
  });
31
43
  test("registered claims survive the mapping into extra", () => {
32
- new McpServer({ name: "t", version: "0" }, {}, { oauth: workosOAuth }).registerTool({ name: "a", inputSchema: {} }, (_args, extra) => {
33
- expectTypeOf(extra.http?.authInfo?.extra?.iss).toEqualTypeOf();
34
- expectTypeOf(extra.http?.authInfo?.extra?.iat).toEqualTypeOf();
35
- return { content: "a" };
44
+ new Skybridge({
45
+ name: "t",
46
+ version: "0",
47
+ oauth: workosOAuth,
48
+ handler: (server) => server.registerTool({ name: "a", inputSchema: {} }, (_args, extra) => {
49
+ expectTypeOf(extra.http?.authInfo?.extra?.iss).toEqualTypeOf();
50
+ expectTypeOf(extra.http?.authInfo?.extra?.iat).toEqualTypeOf();
51
+ return { content: "a" };
52
+ }),
36
53
  });
37
54
  });
38
55
  test("a hand-written verifier carries its own claims", async () => {
@@ -43,10 +60,15 @@ test("a hand-written verifier carries its own claims", async () => {
43
60
  };
44
61
  const { oauthMetadata } = await customProvider({
45
62
  issuer: "https://idp.example.com",
46
- });
47
- new McpServer({ name: "t", version: "0" }, {}, { oauth: { oauthMetadata, verifier } }).registerTool({ name: "a", inputSchema: {} }, (_args, extra) => {
48
- expectTypeOf(extra.http?.authInfo?.extra?.email).toEqualTypeOf();
49
- return { content: "a" };
63
+ }).resolve();
64
+ new Skybridge({
65
+ name: "t",
66
+ version: "0",
67
+ oauth: { oauthMetadata, verifier },
68
+ handler: (server) => server.registerTool({ name: "a", inputSchema: {} }, (_args, extra) => {
69
+ expectTypeOf(extra.http?.authInfo?.extra?.email).toEqualTypeOf();
70
+ return { content: "a" };
71
+ }),
50
72
  });
51
73
  });
52
74
  test("a config must carry a verifier", () => {
@@ -57,15 +79,52 @@ test("a config must carry a verifier", () => {
57
79
  void missing;
58
80
  });
59
81
  test("a provider override adds claims without dropping the provider's", () => {
60
- new McpServer({ name: "t", version: "0" }, {}, { oauth: customOAuth })
61
- .registerTool({ name: "a", inputSchema: {} }, (_args, extra) => {
62
- expectTypeOf(extra.http?.authInfo?.extra?.tenant).toEqualTypeOf();
63
- expectTypeOf(extra.http?.authInfo?.extra?.org_id).toEqualTypeOf();
64
- return { content: "a" };
65
- })
66
- .mcpMiddleware("tools/call", (_request, extra, next) => {
67
- expectTypeOf(extra.http?.authInfo?.extra?.tenant).toEqualTypeOf();
68
- return next();
82
+ new Skybridge({
83
+ name: "t",
84
+ version: "0",
85
+ oauth: customOAuth,
86
+ handler: (server) => server
87
+ .registerTool({ name: "a", inputSchema: {} }, (_args, extra) => {
88
+ expectTypeOf(extra.http?.authInfo?.extra?.tenant).toEqualTypeOf();
89
+ expectTypeOf(extra.http?.authInfo?.extra?.org_id).toEqualTypeOf();
90
+ return { content: "a" };
91
+ })
92
+ .mcpMiddleware("tools/call", (_request, extra, next) => {
93
+ expectTypeOf(extra.http?.authInfo?.extra?.tenant).toEqualTypeOf();
94
+ return next();
95
+ }),
96
+ });
97
+ });
98
+ test("bag oauth claims reach tool handlers through the function form", () => {
99
+ new Skybridge({
100
+ name: "t",
101
+ version: "0",
102
+ oauth: workosProvider({ domain: "d", audience: "a" }),
103
+ handler: (server) => server.registerTool({ name: "a", inputSchema: {} }, (_args, extra) => {
104
+ expectTypeOf(extra.http?.authInfo?.extra?.org_id).toEqualTypeOf();
105
+ // @ts-expect-error not a WorkOS claim
106
+ extra.http?.authInfo?.extra?.nope;
107
+ return { content: "a" };
108
+ }),
109
+ });
110
+ });
111
+ test("the setup config flows into oauth and handler, and the app carries the registry", () => {
112
+ const app = new Skybridge({
113
+ name: "t",
114
+ version: "0",
115
+ setup: async () => ({ apiKey: "k" }),
116
+ oauth: (config) => {
117
+ expectTypeOf(config).toEqualTypeOf();
118
+ return workosOAuth;
119
+ },
120
+ handler: (server, config) => {
121
+ expectTypeOf(config).toEqualTypeOf();
122
+ return server.registerTool({ name: "a", inputSchema: {} }, (_args, extra) => {
123
+ expectTypeOf(extra.http?.authInfo?.extra?.org_id).toEqualTypeOf();
124
+ return { content: "a" };
125
+ });
126
+ },
69
127
  });
128
+ expectTypeOf().toEqualTypeOf();
70
129
  });
71
130
  //# sourceMappingURL=auth-extra.test-d.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth-extra.test-d.js","sourceRoot":"","sources":["../../src/server/auth-extra.test-d.ts"],"names":[],"mappings":"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","sourcesContent":["import { expectTypeOf, test } from \"vitest\";\nimport { z } from \"zod\";\nimport type { OAuthConfig } from \"./auth/index.js\";\nimport { customProvider } from \"./auth/providers/custom.js\";\nimport { workosProvider } from \"./auth/providers/workos.js\";\nimport type { TokenVerifier } from \"./auth.js\";\nimport { McpServer } from \"./server.js\";\n\nconst workosOAuth = await workosProvider({ domain: \"d\", audience: \"a\" });\nconst customOAuth = await workosProvider<{ tenant: string }>({\n domain: \"d\",\n audience: \"a\",\n});\n\ntest(\"a server with no oauth keeps the untyped claim bag\", () => {\n new McpServer({ name: \"t\", version: \"0\" }).registerTool(\n { name: \"plain\", inputSchema: { q: z.string() } },\n (_args, extra) => {\n expectTypeOf(extra.http?.authInfo?.extra).toEqualTypeOf<\n Record<string, unknown> | undefined\n >();\n return { content: \"ok\" };\n },\n );\n});\n\ntest(\"provider claims reach tool handlers\", () => {\n new McpServer({ name: \"t\", version: \"0\" }, {}, { oauth: workosOAuth })\n .registerTool({ name: \"a\", inputSchema: {} }, (_args, extra) => {\n expectTypeOf(extra.http?.authInfo?.extra?.org_id).toEqualTypeOf<\n string | undefined\n >();\n expectTypeOf(extra.http?.authInfo?.extra?.permissions).toEqualTypeOf<\n string[] | undefined\n >();\n // @ts-expect-error not a WorkOS claim\n extra.http?.authInfo?.extra?.nope;\n return { content: \"a\" };\n })\n .registerTool({ name: \"b\", inputSchema: {} }, (_args, extra) => {\n expectTypeOf(extra.http?.authInfo?.extra?.sid).toEqualTypeOf<\n string | undefined\n >();\n return { content: \"b\" };\n });\n});\n\ntest(\"registered claims survive the mapping into extra\", () => {\n new McpServer(\n { name: \"t\", version: \"0\" },\n {},\n { oauth: workosOAuth },\n ).registerTool({ name: \"a\", inputSchema: {} }, (_args, extra) => {\n expectTypeOf(extra.http?.authInfo?.extra?.iss).toEqualTypeOf<\n string | undefined\n >();\n expectTypeOf(extra.http?.authInfo?.extra?.iat).toEqualTypeOf<\n number | undefined\n >();\n return { content: \"a\" };\n });\n});\n\ntest(\"a hand-written verifier carries its own claims\", async () => {\n type Claims = { subject?: string; email?: string };\n const verifier: TokenVerifier<Claims> = {\n async verifyAccessToken(token) {\n return { token, clientId: \"c\", scopes: [], expiresAt: 1, extra: {} };\n },\n };\n const { oauthMetadata } = await customProvider({\n issuer: \"https://idp.example.com\",\n });\n new McpServer(\n { name: \"t\", version: \"0\" },\n {},\n { oauth: { oauthMetadata, verifier } },\n ).registerTool({ name: \"a\", inputSchema: {} }, (_args, extra) => {\n expectTypeOf(extra.http?.authInfo?.extra?.email).toEqualTypeOf<\n string | undefined\n >();\n return { content: \"a\" };\n });\n});\n\ntest(\"a config must carry a verifier\", () => {\n // @ts-expect-error a verifier is required\n const missing: OAuthConfig = {\n oauthMetadata: workosOAuth.oauthMetadata,\n };\n void missing;\n});\n\ntest(\"a provider override adds claims without dropping the provider's\", () => {\n new McpServer({ name: \"t\", version: \"0\" }, {}, { oauth: customOAuth })\n .registerTool({ name: \"a\", inputSchema: {} }, (_args, extra) => {\n expectTypeOf(extra.http?.authInfo?.extra?.tenant).toEqualTypeOf<\n string | undefined\n >();\n expectTypeOf(extra.http?.authInfo?.extra?.org_id).toEqualTypeOf<\n string | undefined\n >();\n return { content: \"a\" };\n })\n .mcpMiddleware(\"tools/call\", (_request, extra, next) => {\n expectTypeOf(extra.http?.authInfo?.extra?.tenant).toEqualTypeOf<\n string | undefined\n >();\n return next();\n });\n});\n"]}
1
+ {"version":3,"file":"auth-extra.test-d.js","sourceRoot":"","sources":["../../src/server/auth-extra.test-d.ts"],"names":[],"mappings":"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","sourcesContent":["import { expectTypeOf, test } from \"vitest\";\nimport { z } from \"zod\";\nimport { Skybridge } from \"./app.js\";\nimport type { OAuthConfig } from \"./auth/index.js\";\nimport { customProvider } from \"./auth/providers/custom.js\";\nimport { workosProvider } from \"./auth/providers/workos.js\";\nimport type { TokenVerifier } from \"./auth.js\";\nimport type { ToolNames } from \"./inferUtilityTypes.js\";\n\nconst workosOAuth = await workosProvider({\n domain: \"d\",\n audience: \"a\",\n}).resolve();\nconst customOAuth = await workosProvider<{ tenant: string }>({\n domain: \"d\",\n audience: \"a\",\n}).resolve();\n\ntest(\"a server with no oauth keeps the untyped claim bag\", () => {\n new Skybridge({\n name: \"t\",\n version: \"0\",\n handler: (server) =>\n server.registerTool(\n { name: \"plain\", inputSchema: { q: z.string() } },\n (_args, extra) => {\n expectTypeOf(extra.http?.authInfo?.extra).toEqualTypeOf<\n Record<string, unknown> | undefined\n >();\n return { content: \"ok\" };\n },\n ),\n });\n});\n\ntest(\"provider claims reach tool handlers\", () => {\n new Skybridge({\n name: \"t\",\n version: \"0\",\n oauth: workosOAuth,\n handler: (server) =>\n server\n .registerTool({ name: \"a\", inputSchema: {} }, (_args, extra) => {\n expectTypeOf(extra.http?.authInfo?.extra?.org_id).toEqualTypeOf<\n string | undefined\n >();\n expectTypeOf(extra.http?.authInfo?.extra?.permissions).toEqualTypeOf<\n string[] | undefined\n >();\n // @ts-expect-error not a WorkOS claim\n extra.http?.authInfo?.extra?.nope;\n return { content: \"a\" };\n })\n .registerTool({ name: \"b\", inputSchema: {} }, (_args, extra) => {\n expectTypeOf(extra.http?.authInfo?.extra?.sid).toEqualTypeOf<\n string | undefined\n >();\n return { content: \"b\" };\n }),\n });\n});\n\ntest(\"registered claims survive the mapping into extra\", () => {\n new Skybridge({\n name: \"t\",\n version: \"0\",\n oauth: workosOAuth,\n handler: (server) =>\n server.registerTool({ name: \"a\", inputSchema: {} }, (_args, extra) => {\n expectTypeOf(extra.http?.authInfo?.extra?.iss).toEqualTypeOf<\n string | undefined\n >();\n expectTypeOf(extra.http?.authInfo?.extra?.iat).toEqualTypeOf<\n number | undefined\n >();\n return { content: \"a\" };\n }),\n });\n});\n\ntest(\"a hand-written verifier carries its own claims\", async () => {\n type Claims = { subject?: string; email?: string };\n const verifier: TokenVerifier<Claims> = {\n async verifyAccessToken(token) {\n return { token, clientId: \"c\", scopes: [], expiresAt: 1, extra: {} };\n },\n };\n const { oauthMetadata } = await customProvider({\n issuer: \"https://idp.example.com\",\n }).resolve();\n new Skybridge({\n name: \"t\",\n version: \"0\",\n oauth: { oauthMetadata, verifier },\n handler: (server) =>\n server.registerTool({ name: \"a\", inputSchema: {} }, (_args, extra) => {\n expectTypeOf(extra.http?.authInfo?.extra?.email).toEqualTypeOf<\n string | undefined\n >();\n return { content: \"a\" };\n }),\n });\n});\n\ntest(\"a config must carry a verifier\", () => {\n // @ts-expect-error a verifier is required\n const missing: OAuthConfig = {\n oauthMetadata: workosOAuth.oauthMetadata,\n };\n void missing;\n});\n\ntest(\"a provider override adds claims without dropping the provider's\", () => {\n new Skybridge({\n name: \"t\",\n version: \"0\",\n oauth: customOAuth,\n handler: (server) =>\n server\n .registerTool({ name: \"a\", inputSchema: {} }, (_args, extra) => {\n expectTypeOf(extra.http?.authInfo?.extra?.tenant).toEqualTypeOf<\n string | undefined\n >();\n expectTypeOf(extra.http?.authInfo?.extra?.org_id).toEqualTypeOf<\n string | undefined\n >();\n return { content: \"a\" };\n })\n .mcpMiddleware(\"tools/call\", (_request, extra, next) => {\n expectTypeOf(extra.http?.authInfo?.extra?.tenant).toEqualTypeOf<\n string | undefined\n >();\n return next();\n }),\n });\n});\n\ntest(\"bag oauth claims reach tool handlers through the function form\", () => {\n new Skybridge({\n name: \"t\",\n version: \"0\",\n oauth: workosProvider({ domain: \"d\", audience: \"a\" }),\n handler: (server) =>\n server.registerTool({ name: \"a\", inputSchema: {} }, (_args, extra) => {\n expectTypeOf(extra.http?.authInfo?.extra?.org_id).toEqualTypeOf<\n string | undefined\n >();\n // @ts-expect-error not a WorkOS claim\n extra.http?.authInfo?.extra?.nope;\n return { content: \"a\" };\n }),\n });\n});\n\ntest(\"the setup config flows into oauth and handler, and the app carries the registry\", () => {\n const app = new Skybridge({\n name: \"t\",\n version: \"0\",\n setup: async () => ({ apiKey: \"k\" }),\n oauth: (config) => {\n expectTypeOf(config).toEqualTypeOf<{ apiKey: string }>();\n return workosOAuth;\n },\n handler: (server, config) => {\n expectTypeOf(config).toEqualTypeOf<{ apiKey: string }>();\n return server.registerTool(\n { name: \"a\", inputSchema: {} },\n (_args, extra) => {\n expectTypeOf(extra.http?.authInfo?.extra?.org_id).toEqualTypeOf<\n string | undefined\n >();\n return { content: \"a\" };\n },\n );\n },\n });\n expectTypeOf<ToolNames<typeof app>>().toEqualTypeOf<\"a\">();\n});\n"]}
@@ -2,13 +2,13 @@ import { type BearerAuthMiddlewareOptions } from "@modelcontextprotocol/express"
2
2
  import type { AuthInfo as SdkAuthInfo } from "@modelcontextprotocol/server";
3
3
  import type { RequestHandler } from "express";
4
4
  export { type AuthMetadataOptions, type BearerAuthMiddlewareOptions, mcpAuthMetadataRouter, requireBearerAuth, } from "@modelcontextprotocol/express";
5
- export { OAuthError } from "@modelcontextprotocol/server";
5
+ export { OAuthError, OAuthErrorCode } from "@modelcontextprotocol/server";
6
6
  /** Claims a verifier puts in `AuthInfo["extra"]`: any JSON-ish bag of them. */
7
7
  export type ExtraClaims = Record<string, unknown>;
8
8
  /**
9
9
  * A validated access token, as resolved by a
10
10
  * [verifier](https://docs.skybridge.tech/api-reference/verifier) and handed to
11
- * handlers on `extra.authInfo`.
11
+ * handlers on `extra.http?.authInfo`.
12
12
  *
13
13
  * Unparameterized, `extra` stays the SDK's `Record<string, unknown>` bag. The
14
14
  * claims are owned by whoever verifies the token: parameterize the verifier and
@@ -30,7 +30,7 @@ export type AuthInfo<TExtra extends ExtraClaims = ExtraClaims> = Omit<SdkAuthInf
30
30
  };
31
31
  /**
32
32
  * Checks a bearer token and resolves the claims it carries. The type parameter
33
- * is what makes `extra.authInfo.extra` typed downstream, so a verifier is the
33
+ * is what makes `extra.http?.authInfo.extra` typed downstream, so a verifier is the
34
34
  * single source for the claim shape.
35
35
  *
36
36
  * Pass one to {@link requireBearerAuth} or {@link optionalBearerAuth} directly,
@@ -45,7 +45,7 @@ export type TokenVerifier<TExtra extends ExtraClaims = ExtraClaims> = {
45
45
  * Like `requireBearerAuth`, but lets requests through when no
46
46
  * `Authorization` header is present. Used for mixed-auth servers where some
47
47
  * tools are public and others require sign-in: each tool enforces its own
48
- * `securitySchemes` against `extra.authInfo`.
48
+ * `securitySchemes` against `extra.http?.authInfo`.
49
49
  *
50
50
  * Behavior:
51
51
  * - No `Authorization` header → `next()` without `req.auth`.
@@ -1,11 +1,11 @@
1
1
  import { requireBearerAuth, } from "@modelcontextprotocol/express";
2
2
  export { mcpAuthMetadataRouter, requireBearerAuth, } from "@modelcontextprotocol/express";
3
- export { OAuthError } from "@modelcontextprotocol/server";
3
+ export { OAuthError, OAuthErrorCode } from "@modelcontextprotocol/server";
4
4
  /**
5
5
  * Like `requireBearerAuth`, but lets requests through when no
6
6
  * `Authorization` header is present. Used for mixed-auth servers where some
7
7
  * tools are public and others require sign-in: each tool enforces its own
8
- * `securitySchemes` against `extra.authInfo`.
8
+ * `securitySchemes` against `extra.http?.authInfo`.
9
9
  *
10
10
  * Behavior:
11
11
  * - No `Authorization` header → `next()` without `req.auth`.
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/server/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,iBAAiB,GAClB,MAAM,+BAA+B,CAAC;AAKvC,OAAO,EAGL,qBAAqB,EACrB,iBAAiB,GAClB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AA2C1D;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,kBAAkB,CAChC,OAAoC;IAEpC,MAAM,QAAQ,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAC5C,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACxB,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;YAC/B,IAAI,EAAE,CAAC;YACP,OAAO;QACT,CAAC;QACD,OAAO,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;IAClC,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import {\n type BearerAuthMiddlewareOptions,\n requireBearerAuth,\n} from \"@modelcontextprotocol/express\";\nimport type { AuthInfo as SdkAuthInfo } from \"@modelcontextprotocol/server\";\n\nimport type { RequestHandler } from \"express\";\n\nexport {\n type AuthMetadataOptions,\n type BearerAuthMiddlewareOptions,\n mcpAuthMetadataRouter,\n requireBearerAuth,\n} from \"@modelcontextprotocol/express\";\nexport { OAuthError } from \"@modelcontextprotocol/server\";\n/** Claims a verifier puts in `AuthInfo[\"extra\"]`: any JSON-ish bag of them. */\nexport type ExtraClaims = Record<string, unknown>;\n\n/**\n * A validated access token, as resolved by a\n * [verifier](https://docs.skybridge.tech/api-reference/verifier) and handed to\n * handlers on `extra.authInfo`.\n *\n * Unparameterized, `extra` stays the SDK's `Record<string, unknown>` bag. The\n * claims are owned by whoever verifies the token: parameterize the verifier and\n * the shape flows through {@link OAuthConfig} to every handler.\n *\n * @typeParam TExtra - Claims populated in `extra`.\n *\n * @example\n * ```ts\n * type Claims = { subject?: string; email?: string };\n *\n * async function verifyAccessToken(token: string): Promise<AuthInfo<Claims>> {\n * // ...\n * }\n * ```\n */\nexport type AuthInfo<TExtra extends ExtraClaims = ExtraClaims> = Omit<\n SdkAuthInfo,\n \"extra\"\n> & { extra?: TExtra };\n\n/**\n * Checks a bearer token and resolves the claims it carries. The type parameter\n * is what makes `extra.authInfo.extra` typed downstream, so a verifier is the\n * single source for the claim shape.\n *\n * Pass one to {@link requireBearerAuth} or {@link optionalBearerAuth} directly,\n * or hand it to the `oauth` server option inside an {@link OAuthConfig}.\n *\n * @typeParam TExtra - Claims this verifier populates in `AuthInfo[\"extra\"]`.\n */\nexport type TokenVerifier<TExtra extends ExtraClaims = ExtraClaims> = {\n verifyAccessToken(token: string): Promise<AuthInfo<TExtra>>;\n};\n\n/**\n * Like `requireBearerAuth`, but lets requests through when no\n * `Authorization` header is present. Used for mixed-auth servers where some\n * tools are public and others require sign-in: each tool enforces its own\n * `securitySchemes` against `extra.authInfo`.\n *\n * Behavior:\n * - No `Authorization` header → `next()` without `req.auth`.\n * - Valid Bearer token → `req.auth` set, same as `requireBearerAuth`.\n * - Invalid / malformed / expired / insufficient-scope → same error response\n * as `requireBearerAuth` (401/403). Sending a bad token is still a client\n * error.\n */\nexport function optionalBearerAuth(\n options: BearerAuthMiddlewareOptions,\n): RequestHandler {\n const required = requireBearerAuth(options);\n return (req, res, next) => {\n if (!req.headers.authorization) {\n next();\n return;\n }\n return required(req, res, next);\n };\n}\n"]}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/server/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,iBAAiB,GAClB,MAAM,+BAA+B,CAAC;AAKvC,OAAO,EAGL,qBAAqB,EACrB,iBAAiB,GAClB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AA2C1E;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,kBAAkB,CAChC,OAAoC;IAEpC,MAAM,QAAQ,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAC5C,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACxB,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;YAC/B,IAAI,EAAE,CAAC;YACP,OAAO;QACT,CAAC;QACD,OAAO,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;IAClC,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import {\n type BearerAuthMiddlewareOptions,\n requireBearerAuth,\n} from \"@modelcontextprotocol/express\";\nimport type { AuthInfo as SdkAuthInfo } from \"@modelcontextprotocol/server\";\n\nimport type { RequestHandler } from \"express\";\n\nexport {\n type AuthMetadataOptions,\n type BearerAuthMiddlewareOptions,\n mcpAuthMetadataRouter,\n requireBearerAuth,\n} from \"@modelcontextprotocol/express\";\nexport { OAuthError, OAuthErrorCode } from \"@modelcontextprotocol/server\";\n/** Claims a verifier puts in `AuthInfo[\"extra\"]`: any JSON-ish bag of them. */\nexport type ExtraClaims = Record<string, unknown>;\n\n/**\n * A validated access token, as resolved by a\n * [verifier](https://docs.skybridge.tech/api-reference/verifier) and handed to\n * handlers on `extra.http?.authInfo`.\n *\n * Unparameterized, `extra` stays the SDK's `Record<string, unknown>` bag. The\n * claims are owned by whoever verifies the token: parameterize the verifier and\n * the shape flows through {@link OAuthConfig} to every handler.\n *\n * @typeParam TExtra - Claims populated in `extra`.\n *\n * @example\n * ```ts\n * type Claims = { subject?: string; email?: string };\n *\n * async function verifyAccessToken(token: string): Promise<AuthInfo<Claims>> {\n * // ...\n * }\n * ```\n */\nexport type AuthInfo<TExtra extends ExtraClaims = ExtraClaims> = Omit<\n SdkAuthInfo,\n \"extra\"\n> & { extra?: TExtra };\n\n/**\n * Checks a bearer token and resolves the claims it carries. The type parameter\n * is what makes `extra.http?.authInfo.extra` typed downstream, so a verifier is the\n * single source for the claim shape.\n *\n * Pass one to {@link requireBearerAuth} or {@link optionalBearerAuth} directly,\n * or hand it to the `oauth` server option inside an {@link OAuthConfig}.\n *\n * @typeParam TExtra - Claims this verifier populates in `AuthInfo[\"extra\"]`.\n */\nexport type TokenVerifier<TExtra extends ExtraClaims = ExtraClaims> = {\n verifyAccessToken(token: string): Promise<AuthInfo<TExtra>>;\n};\n\n/**\n * Like `requireBearerAuth`, but lets requests through when no\n * `Authorization` header is present. Used for mixed-auth servers where some\n * tools are public and others require sign-in: each tool enforces its own\n * `securitySchemes` against `extra.http?.authInfo`.\n *\n * Behavior:\n * - No `Authorization` header → `next()` without `req.auth`.\n * - Valid Bearer token → `req.auth` set, same as `requireBearerAuth`.\n * - Invalid / malformed / expired / insufficient-scope → same error response\n * as `requireBearerAuth` (401/403). Sending a bad token is still a client\n * error.\n */\nexport function optionalBearerAuth(\n options: BearerAuthMiddlewareOptions,\n): RequestHandler {\n const required = requireBearerAuth(options);\n return (req, res, next) => {\n if (!req.headers.authorization) {\n next();\n return;\n }\n return required(req, res, next);\n };\n}\n"]}
@@ -4,7 +4,7 @@ function manifestOf(server) {
4
4
  return server.viteManifest;
5
5
  }
6
6
  function makeServer() {
7
- return new McpServer({ name: "test", version: "0.0.1" }, { capabilities: {} });
7
+ return new McpServer({ name: "test", version: "0.0.1" });
8
8
  }
9
9
  describe("__setBuildManifest", () => {
10
10
  it("primes the Vite manifest for the next McpServer constructed", () => {
@@ -16,12 +16,13 @@ describe("__setBuildManifest", () => {
16
16
  // generated `dist/__entry.js` relies on.
17
17
  expect(manifestOf(makeServer())).toEqual(manifest);
18
18
  });
19
- it("is consume-once: a second McpServer built without re-priming gets no manifest", () => {
20
- __setBuildManifest({
19
+ it("keeps priming every McpServer the app factory builds per request", () => {
20
+ const manifest = {
21
21
  "src/views/index.tsx": { file: "assets/index-CAFEBABE.js" },
22
- });
23
- makeServer(); // consumes the primed manifest
24
- expect(manifestOf(makeServer())).toBeNull();
22
+ };
23
+ __setBuildManifest(manifest);
24
+ makeServer();
25
+ expect(manifestOf(makeServer())).toEqual(manifest);
25
26
  });
26
27
  });
27
28
  //# sourceMappingURL=build-manifest.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"build-manifest.test.js","sourceRoot":"","sources":["../../src/server/build-manifest.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE3D,SAAS,UAAU,CACjB,MAAiB;IAEjB,OACE,MAGD,CAAC,YAAY,CAAC;AACjB,CAAC;AAED,SAAS,UAAU;IACjB,OAAO,IAAI,SAAS,CAClB,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,EAClC,EAAE,YAAY,EAAE,EAAE,EAAE,CACrB,CAAC;AACJ,CAAC;AAED,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACrE,MAAM,QAAQ,GAAG;YACf,qBAAqB,EAAE,EAAE,IAAI,EAAE,0BAA0B,EAAE;SAC5D,CAAC;QACF,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QAE7B,uEAAuE;QACvE,yCAAyC;QACzC,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+EAA+E,EAAE,GAAG,EAAE;QACvF,kBAAkB,CAAC;YACjB,qBAAqB,EAAE,EAAE,IAAI,EAAE,0BAA0B,EAAE;SAC5D,CAAC,CAAC;QAEH,UAAU,EAAE,CAAC,CAAC,+BAA+B;QAC7C,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC9C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { __setBuildManifest, McpServer } from \"./index.js\";\n\nfunction manifestOf(\n server: McpServer,\n): Record<string, { file: string }> | null {\n return (\n server as unknown as {\n viteManifest: Record<string, { file: string }> | null;\n }\n ).viteManifest;\n}\n\nfunction makeServer(): McpServer {\n return new McpServer(\n { name: \"test\", version: \"0.0.1\" },\n { capabilities: {} },\n );\n}\n\ndescribe(\"__setBuildManifest\", () => {\n it(\"primes the Vite manifest for the next McpServer constructed\", () => {\n const manifest = {\n \"src/views/index.tsx\": { file: \"assets/index-DEADBEEF.js\" },\n };\n __setBuildManifest(manifest);\n\n // viteManifest is private; reach into it to lock the contract that the\n // generated `dist/__entry.js` relies on.\n expect(manifestOf(makeServer())).toEqual(manifest);\n });\n\n it(\"is consume-once: a second McpServer built without re-priming gets no manifest\", () => {\n __setBuildManifest({\n \"src/views/index.tsx\": { file: \"assets/index-CAFEBABE.js\" },\n });\n\n makeServer(); // consumes the primed manifest\n expect(manifestOf(makeServer())).toBeNull();\n });\n});\n"]}
1
+ {"version":3,"file":"build-manifest.test.js","sourceRoot":"","sources":["../../src/server/build-manifest.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE3D,SAAS,UAAU,CACjB,MAAiB;IAEjB,OACE,MAGD,CAAC,YAAY,CAAC;AACjB,CAAC;AAED,SAAS,UAAU;IACjB,OAAO,IAAI,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;AAC3D,CAAC;AAED,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACrE,MAAM,QAAQ,GAAG;YACf,qBAAqB,EAAE,EAAE,IAAI,EAAE,0BAA0B,EAAE;SAC5D,CAAC;QACF,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QAE7B,uEAAuE;QACvE,yCAAyC;QACzC,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;QAC1E,MAAM,QAAQ,GAAG;YACf,qBAAqB,EAAE,EAAE,IAAI,EAAE,0BAA0B,EAAE;SAC5D,CAAC;QACF,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QAE7B,UAAU,EAAE,CAAC;QACb,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { __setBuildManifest, McpServer } from \"./index.js\";\n\nfunction manifestOf(\n server: McpServer,\n): Record<string, { file: string }> | null {\n return (\n server as unknown as {\n viteManifest: Record<string, { file: string }> | null;\n }\n ).viteManifest;\n}\n\nfunction makeServer(): McpServer {\n return new McpServer({ name: \"test\", version: \"0.0.1\" });\n}\n\ndescribe(\"__setBuildManifest\", () => {\n it(\"primes the Vite manifest for the next McpServer constructed\", () => {\n const manifest = {\n \"src/views/index.tsx\": { file: \"assets/index-DEADBEEF.js\" },\n };\n __setBuildManifest(manifest);\n\n // viteManifest is private; reach into it to lock the contract that the\n // generated `dist/__entry.js` relies on.\n expect(manifestOf(makeServer())).toEqual(manifest);\n });\n\n it(\"keeps priming every McpServer the app factory builds per request\", () => {\n const manifest = {\n \"src/views/index.tsx\": { file: \"assets/index-CAFEBABE.js\" },\n };\n __setBuildManifest(manifest);\n\n makeServer();\n expect(manifestOf(makeServer())).toEqual(manifest);\n });\n});\n"]}
@@ -0,0 +1,113 @@
1
+ import { type McpServer as SdkMcpServer, type StandardSchemaV1, type StandardSchemaWithJSON } from "@modelcontextprotocol/server";
2
+ /**
3
+ * A webhook subscription, as passed to `onSubscribe`. Whatever delivers the
4
+ * events POSTs them to `url`, signed with `secret`, until `expiresAt`.
5
+ */
6
+ export interface EventSubscription {
7
+ /** Stable across refreshes: the same user subscribing to the same event with the same arguments and callback gets the same `id`. */
8
+ id: string;
9
+ /** Callback URL deliveries are POSTed to. */
10
+ url: string;
11
+ /** Standard Webhooks signing secret (`whsec_…`). A refresh may carry a new one. */
12
+ secret: string;
13
+ /** When the subscription lapses unless the host refreshes it. */
14
+ expiresAt: Date;
15
+ }
16
+ /** An event occurrence, as passed to {@link deliverEvent}. */
17
+ export interface EventOccurrence {
18
+ /** Event type name, as registered with `registerEvent`. */
19
+ name: string;
20
+ /** Stable identifier the host uses to drop duplicates, ideally the upstream's. Reuse it when retrying. */
21
+ id: string;
22
+ /** When the event happened. Defaults to now. */
23
+ timestamp?: Date;
24
+ /** Payload matching the event's `payloadSchema`. */
25
+ data: unknown;
26
+ }
27
+ /** Outcome of {@link deliverEvent}. Retry with the same event `id` when `retryable`. */
28
+ export type DeliveryResult = {
29
+ ok: true;
30
+ } | {
31
+ ok: false;
32
+ reason: string;
33
+ retryable: boolean;
34
+ status?: number;
35
+ };
36
+ type EventSchema = Record<string, StandardSchemaWithJSON> | StandardSchemaWithJSON;
37
+ export type InferEventSchema<T extends EventSchema> = T extends StandardSchemaWithJSON ? StandardSchemaV1.InferOutput<T> : T extends Record<string, StandardSchemaWithJSON> ? {
38
+ [K in keyof T as undefined extends StandardSchemaV1.InferOutput<T[K]> ? never : K]: StandardSchemaV1.InferOutput<T[K]>;
39
+ } & {
40
+ [K in keyof T as undefined extends StandardSchemaV1.InferOutput<T[K]> ? K : never]?: StandardSchemaV1.InferOutput<T[K]>;
41
+ } : never;
42
+ /** The `registerEvent` config: how the event type is described in `events/list`. */
43
+ export interface EventConfig<TInput extends EventSchema> {
44
+ /** Stable, specific name such as `comment.created`. */
45
+ name: string;
46
+ /** What the event is and when it fires. */
47
+ description?: string;
48
+ /** Subscription arguments (filters): a Zod shape or a Standard Schema object. */
49
+ inputSchema?: TInput;
50
+ /** Shape of the delivered `data`: a Zod shape or a Standard Schema object. */
51
+ payloadSchema: EventSchema;
52
+ _meta?: Record<string, unknown>;
53
+ }
54
+ /** What `registerEvent` does when the host subscribes and unsubscribes. */
55
+ export interface EventHooks<TArguments, TExtra> {
56
+ /**
57
+ * Runs on every `events/subscribe`, including the host's refreshes, once
58
+ * the callback URL is verified. Hand the subscription to whatever delivers
59
+ * the events, keyed by `subscription.id`. Throw (e.g. a `ProtocolError`) to
60
+ * reject it, for instance when the user may not access what the arguments
61
+ * point to.
62
+ */
63
+ onSubscribe(args: TArguments, context: {
64
+ subscription: EventSubscription;
65
+ extra: TExtra;
66
+ }): void | Promise<void>;
67
+ /** Runs on `events/unsubscribe`. Stop delivering to `subscription.id`. */
68
+ onUnsubscribe(args: TArguments, context: {
69
+ subscription: Pick<EventSubscription, "id">;
70
+ extra: TExtra;
71
+ }): void | Promise<void>;
72
+ }
73
+ /**
74
+ * @experimental POST one event to a subscription handed out by `onSubscribe`,
75
+ * as MCP Events expects: the event envelope, Standard Webhooks signature
76
+ * headers, a 10 second deadline and, outside development, no requests to
77
+ * private addresses. Pass the old and new secrets during a rotation so both
78
+ * sign the delivery. A subscription past `expiresAt` is not posted to.
79
+ * Retrying is up to the caller. API may change.
80
+ *
81
+ * @example
82
+ * ```ts
83
+ * const result = await deliverEvent(subscription, {
84
+ * name: "comment.created",
85
+ * id: comment.id,
86
+ * data: { documentId: comment.documentId, excerpt: comment.text.slice(0, 280) },
87
+ * });
88
+ * if (!result.ok && result.retryable) {
89
+ * await queue.retryLater(subscription, comment);
90
+ * }
91
+ * ```
92
+ *
93
+ * @see https://docs.skybridge.tech/api-reference/register-event
94
+ */
95
+ export declare function deliverEvent(subscription: Pick<EventSubscription, "id" | "url"> & {
96
+ secret: string | string[];
97
+ expiresAt: Date | string;
98
+ }, event: EventOccurrence): Promise<DeliveryResult>;
99
+ /**
100
+ * The event types registered on one server, and the `events/*` handlers that
101
+ * serve them.
102
+ *
103
+ * @internal
104
+ */
105
+ export declare class EventRegistry {
106
+ private readonly server;
107
+ private readonly events;
108
+ constructor(server: Pick<SdkMcpServer["server"], "setRequestHandler">);
109
+ add(config: EventConfig<EventSchema>, hooks: EventHooks<never, never>): void;
110
+ private install;
111
+ private resolve;
112
+ }
113
+ export {};