alepha 0.20.2 → 0.20.4

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 (304) hide show
  1. package/README.md +0 -1
  2. package/assets/swagger-ui/swagger-ui-bundle.js +1 -1
  3. package/assets/swagger-ui/swagger-ui.css +1 -1
  4. package/dist/api/audits/index.browser.js +49 -0
  5. package/dist/api/audits/index.browser.js.map +1 -1
  6. package/dist/api/audits/index.js +49 -0
  7. package/dist/api/audits/index.js.map +1 -1
  8. package/dist/api/files/index.js.map +1 -1
  9. package/dist/api/jobs/index.d.ts +2 -61
  10. package/dist/api/jobs/index.d.ts.map +1 -1
  11. package/dist/api/jobs/index.js.map +1 -1
  12. package/dist/api/keys/index.d.ts +4 -4
  13. package/dist/api/keys/index.js.map +1 -1
  14. package/dist/api/notifications/index.d.ts +1 -10
  15. package/dist/api/notifications/index.d.ts.map +1 -1
  16. package/dist/api/parameters/index.browser.js +37 -0
  17. package/dist/api/parameters/index.browser.js.map +1 -1
  18. package/dist/api/parameters/index.d.ts +12 -68
  19. package/dist/api/parameters/index.d.ts.map +1 -1
  20. package/dist/api/parameters/index.js +57 -4
  21. package/dist/api/parameters/index.js.map +1 -1
  22. package/dist/api/payments/index.js.map +1 -1
  23. package/dist/api/users/index.browser.js +6 -0
  24. package/dist/api/users/index.browser.js.map +1 -1
  25. package/dist/api/users/index.d.ts +148 -227
  26. package/dist/api/users/index.d.ts.map +1 -1
  27. package/dist/api/users/index.js +60 -14
  28. package/dist/api/users/index.js.map +1 -1
  29. package/dist/api/verifications/index.d.ts.map +1 -1
  30. package/dist/api/verifications/index.js +2 -1
  31. package/dist/api/verifications/index.js.map +1 -1
  32. package/dist/bucket/index.d.ts +77 -107
  33. package/dist/bucket/index.d.ts.map +1 -1
  34. package/dist/bucket/index.js +153 -5
  35. package/dist/bucket/index.js.map +1 -1
  36. package/dist/bucket/index.workerd.js +12 -2
  37. package/dist/bucket/index.workerd.js.map +1 -1
  38. package/dist/cache/core/index.d.ts +26 -0
  39. package/dist/cache/core/index.d.ts.map +1 -1
  40. package/dist/cache/core/index.js +11 -1
  41. package/dist/cache/core/index.js.map +1 -1
  42. package/dist/cache/core/index.workerd.js +11 -1
  43. package/dist/cache/core/index.workerd.js.map +1 -1
  44. package/dist/captcha/index.js.map +1 -1
  45. package/dist/cli/config/index.d.ts +7 -5
  46. package/dist/cli/config/index.d.ts.map +1 -1
  47. package/dist/cli/config/index.js +2 -3
  48. package/dist/cli/config/index.js.map +1 -1
  49. package/dist/cli/core/index.d.ts +637 -11660
  50. package/dist/cli/core/index.d.ts.map +1 -1
  51. package/dist/cli/core/index.js +707 -532
  52. package/dist/cli/core/index.js.map +1 -1
  53. package/dist/cli/devtools/index.d.ts +4 -8
  54. package/dist/cli/devtools/index.d.ts.map +1 -1
  55. package/dist/cli/devtools/index.js +20 -16
  56. package/dist/cli/devtools/index.js.map +1 -1
  57. package/dist/cli/platform/index.d.ts +51 -77
  58. package/dist/cli/platform/index.d.ts.map +1 -1
  59. package/dist/cli/platform/index.js +65 -15
  60. package/dist/cli/platform/index.js.map +1 -1
  61. package/dist/cli/vendor/index.d.ts +10 -13
  62. package/dist/cli/vendor/index.d.ts.map +1 -1
  63. package/dist/cli/vendor/index.js +30 -12
  64. package/dist/cli/vendor/index.js.map +1 -1
  65. package/dist/command/index.js +1 -1
  66. package/dist/command/index.js.map +1 -1
  67. package/dist/core/index.browser.js +27 -3
  68. package/dist/core/index.browser.js.map +1 -1
  69. package/dist/core/index.d.ts +8 -11
  70. package/dist/core/index.d.ts.map +1 -1
  71. package/dist/core/index.js +27 -3
  72. package/dist/core/index.js.map +1 -1
  73. package/dist/core/index.native.js +27 -3
  74. package/dist/core/index.native.js.map +1 -1
  75. package/dist/core/index.workerd.js +27 -3
  76. package/dist/core/index.workerd.js.map +1 -1
  77. package/dist/crypto/index.js.map +1 -1
  78. package/dist/datetime/index.d.ts +69 -10
  79. package/dist/datetime/index.d.ts.map +1 -1
  80. package/dist/datetime/index.js +135 -13
  81. package/dist/datetime/index.js.map +1 -1
  82. package/dist/email/core/index.js.map +1 -1
  83. package/dist/email/smtp/index.js +130 -16
  84. package/dist/email/smtp/index.js.map +1 -1
  85. package/dist/fake/index.js.map +1 -1
  86. package/dist/lock/core/index.d.ts +30 -2
  87. package/dist/lock/core/index.d.ts.map +1 -1
  88. package/dist/lock/core/index.js +35 -12
  89. package/dist/lock/core/index.js.map +1 -1
  90. package/dist/lock/redis/index.js.map +1 -1
  91. package/dist/logger/index.js +32 -1
  92. package/dist/logger/index.js.map +1 -1
  93. package/dist/mcp/index.d.ts +238 -31
  94. package/dist/mcp/index.d.ts.map +1 -1
  95. package/dist/mcp/index.js +198 -67
  96. package/dist/mcp/index.js.map +1 -1
  97. package/dist/orm/core/index.browser.js +2 -362
  98. package/dist/orm/core/index.browser.js.map +1 -1
  99. package/dist/orm/core/index.bun.js +18 -409
  100. package/dist/orm/core/index.bun.js.map +1 -1
  101. package/dist/orm/core/index.d.ts +41 -194
  102. package/dist/orm/core/index.d.ts.map +1 -1
  103. package/dist/orm/core/index.js +27 -422
  104. package/dist/orm/core/index.js.map +1 -1
  105. package/dist/orm/postgres/index.bun.js +17 -20
  106. package/dist/orm/postgres/index.bun.js.map +1 -1
  107. package/dist/orm/postgres/index.d.ts +1 -5
  108. package/dist/orm/postgres/index.d.ts.map +1 -1
  109. package/dist/orm/postgres/index.js +17 -20
  110. package/dist/orm/postgres/index.js.map +1 -1
  111. package/dist/react/core/index.d.ts +102 -1
  112. package/dist/react/core/index.d.ts.map +1 -1
  113. package/dist/react/core/index.js +65 -1
  114. package/dist/react/core/index.js.map +1 -1
  115. package/dist/react/form/index.d.ts +6 -0
  116. package/dist/react/form/index.d.ts.map +1 -1
  117. package/dist/react/form/index.js +7 -7
  118. package/dist/react/form/index.js.map +1 -1
  119. package/dist/react/i18n/index.d.ts +7 -1
  120. package/dist/react/i18n/index.d.ts.map +1 -1
  121. package/dist/react/i18n/index.js +6 -0
  122. package/dist/react/i18n/index.js.map +1 -1
  123. package/dist/react/intro/index.js +22 -17
  124. package/dist/react/intro/index.js.map +1 -1
  125. package/dist/react/router/index.browser.js +98 -4
  126. package/dist/react/router/index.browser.js.map +1 -1
  127. package/dist/react/router/index.d.ts +58 -5
  128. package/dist/react/router/index.d.ts.map +1 -1
  129. package/dist/react/router/index.js +122 -6
  130. package/dist/react/router/index.js.map +1 -1
  131. package/dist/react/testing/{chunk-DBEY4PJZ.js → chunk-6Ep1yQYe.js} +1 -1
  132. package/dist/react/testing/index.js +1 -1
  133. package/dist/react/testing/index.js.map +1 -1
  134. package/dist/react/ui/index.d.ts +195 -1
  135. package/dist/react/ui/index.d.ts.map +1 -1
  136. package/dist/react/ui/index.js +64 -1
  137. package/dist/react/ui/index.js.map +1 -1
  138. package/dist/react/websocket/index.js.map +1 -1
  139. package/dist/redis/index.js.map +1 -1
  140. package/dist/scheduler/index.d.ts +1 -2
  141. package/dist/scheduler/index.d.ts.map +1 -1
  142. package/dist/scheduler/index.js +1 -1
  143. package/dist/scheduler/index.js.map +1 -1
  144. package/dist/scheduler/index.workerd.js +1 -1
  145. package/dist/scheduler/index.workerd.js.map +1 -1
  146. package/dist/security/index.browser.js.map +1 -1
  147. package/dist/security/index.d.ts.map +1 -1
  148. package/dist/security/index.js +2 -2
  149. package/dist/security/index.js.map +1 -1
  150. package/dist/server/auth/index.d.ts.map +1 -1
  151. package/dist/server/auth/index.js +24 -10
  152. package/dist/server/auth/index.js.map +1 -1
  153. package/dist/server/cookies/index.js.map +1 -1
  154. package/dist/server/core/index.browser.js +10 -3
  155. package/dist/server/core/index.browser.js.map +1 -1
  156. package/dist/server/core/index.d.ts +1 -4
  157. package/dist/server/core/index.d.ts.map +1 -1
  158. package/dist/server/core/index.js +47 -9
  159. package/dist/server/core/index.js.map +1 -1
  160. package/dist/server/links/index.browser.js.map +1 -1
  161. package/dist/server/links/index.js.map +1 -1
  162. package/dist/server/metrics/index.js +19 -1
  163. package/dist/server/metrics/index.js.map +1 -1
  164. package/dist/server/rate-limit/index.js.map +1 -1
  165. package/dist/server/static/index.js.map +1 -1
  166. package/dist/server/swagger/index.d.ts.map +1 -1
  167. package/dist/server/swagger/index.js +4 -5
  168. package/dist/server/swagger/index.js.map +1 -1
  169. package/dist/sms/index.js.map +1 -1
  170. package/dist/system/index.browser.js.map +1 -1
  171. package/dist/system/index.js.map +1 -1
  172. package/dist/system/index.workerd.js.map +1 -1
  173. package/dist/topic/core/index.js.map +1 -1
  174. package/dist/websocket/index.browser.js +32 -5
  175. package/dist/websocket/index.browser.js.map +1 -1
  176. package/dist/websocket/index.d.ts +3 -1
  177. package/dist/websocket/index.d.ts.map +1 -1
  178. package/dist/websocket/index.js +42 -6
  179. package/dist/websocket/index.js.map +1 -1
  180. package/package.json +685 -274
  181. package/src/api/files/__tests__/FileController.spec.ts +1 -1
  182. package/src/api/jobs/__tests__/$job.spec.ts +5 -1
  183. package/src/api/parameters/services/ParameterProvider.ts +21 -4
  184. package/src/api/users/__tests__/SessionService.spec.ts +99 -0
  185. package/src/api/users/__tests__/UserJobs.spec.ts +67 -0
  186. package/src/api/users/atoms/realmAuthSettingsAtom.ts +15 -0
  187. package/src/api/users/entities/sessions.ts +6 -0
  188. package/src/api/users/jobs/UserJobs.ts +44 -17
  189. package/src/api/users/providers/RealmProvider.ts +4 -0
  190. package/src/api/users/schemas/userQuerySchema.ts +0 -1
  191. package/src/api/users/services/SessionService.ts +27 -0
  192. package/src/api/users/services/UserService.ts +1 -5
  193. package/src/api/verifications/__tests__/CodeVerification.spec.ts +14 -0
  194. package/src/api/verifications/__tests__/LinkVerification.spec.ts +14 -0
  195. package/src/api/verifications/services/VerificationService.ts +1 -0
  196. package/src/bucket/__tests__/NodeS3BucketProvider.spec.ts +74 -0
  197. package/src/bucket/index.ts +19 -2
  198. package/src/bucket/primitives/$bucket.ts +9 -1
  199. package/src/bucket/providers/CloudflareR2Provider.ts +2 -137
  200. package/src/bucket/providers/NodeS3BucketProvider.ts +218 -0
  201. package/src/cache/core/index.ts +29 -0
  202. package/src/cache/core/primitives/$cache.ts +14 -1
  203. package/src/cli/config/defineConfig.ts +13 -15
  204. package/src/cli/core/__tests__/init.spec.ts +214 -7
  205. package/src/cli/core/commands/init.ts +12 -0
  206. package/src/cli/core/services/PackageManagerUtils.ts +23 -6
  207. package/src/cli/core/services/ProjectScaffolder.ts +315 -33
  208. package/src/cli/core/tasks/BuildCloudflareTask.ts +5 -0
  209. package/src/cli/core/tasks/BuildDockerTask.ts +9 -10
  210. package/src/cli/core/tasks/BuildServerTask.ts +8 -0
  211. package/src/cli/core/templates/agentMd.ts +2 -10
  212. package/src/cli/core/templates/apiIndexTs.ts +23 -1
  213. package/src/cli/core/templates/componentsJsonTs.ts +39 -0
  214. package/src/cli/core/templates/mainCss.ts +1 -0
  215. package/src/cli/core/templates/saasAdminLayoutTsx.ts +77 -0
  216. package/src/cli/core/templates/saasAdminPagesTsx.ts +26 -0
  217. package/src/cli/core/templates/saasAuthLayoutTsx.ts +20 -0
  218. package/src/cli/core/templates/saasAuthPagesTsx.ts +62 -0
  219. package/src/cli/core/templates/saasRealmProviderTs.ts +46 -0
  220. package/src/cli/core/templates/webAppRouterTs.ts +104 -1
  221. package/src/cli/core/templates/webIndexTs.ts +23 -1
  222. package/src/cli/devtools/index.ts +12 -26
  223. package/src/cli/platform/__tests__/SecretsCommand.spec.ts +2 -0
  224. package/src/cli/platform/index.ts +15 -24
  225. package/src/cli/vendor/atoms/vendorOptions.ts +1 -1
  226. package/src/cli/vendor/index.ts +14 -23
  227. package/src/command/providers/CliProvider.ts +1 -1
  228. package/src/core/Alepha.ts +11 -1
  229. package/src/core/helpers/ref.ts +18 -0
  230. package/src/core/index.shared.ts +1 -0
  231. package/src/core/interfaces/Service.ts +3 -1
  232. package/src/core/providers/SchemaValidator.ts +9 -1
  233. package/src/core/providers/TypeProvider.ts +2 -3
  234. package/src/datetime/REFACTORING.md +118 -0
  235. package/src/datetime/providers/DateTimeProvider.ts +203 -24
  236. package/src/lock/core/index.ts +31 -0
  237. package/src/lock/core/primitives/$lock.ts +14 -1
  238. package/src/logger/services/Logger.ts +1 -1
  239. package/src/mcp/__tests__/$resource.spec.ts +1 -1
  240. package/src/mcp/__tests__/$tool.spec.ts +1 -1
  241. package/src/mcp/__tests__/McpServerProvider.spec.ts +1 -1
  242. package/src/mcp/__tests__/jsonrpc.spec.ts +1 -1
  243. package/src/mcp/helpers/jsonrpc.ts +26 -1
  244. package/src/mcp/index.ts +10 -5
  245. package/src/mcp/interfaces/McpTypes.ts +83 -6
  246. package/src/mcp/primitives/$prompt.ts +18 -1
  247. package/src/mcp/primitives/$resource.ts +18 -1
  248. package/src/mcp/primitives/$tool.ts +83 -7
  249. package/src/mcp/providers/McpServerProvider.ts +74 -16
  250. package/src/mcp/transports/StreamableHttpMcpTransport.ts +226 -0
  251. package/src/orm/REFACTORING.md +330 -0
  252. package/src/orm/__tests__/$repository-tests.ts +1 -0
  253. package/src/orm/__tests__/orm-next-tests.ts +2 -67
  254. package/src/orm/__tests__/orm-next.spec.ts +0 -21
  255. package/src/orm/core/index.shared.ts +0 -2
  256. package/src/orm/core/index.ts +1 -2
  257. package/src/orm/core/primitives/$repository.ts +3 -6
  258. package/src/orm/core/primitives/$transactional.ts +11 -0
  259. package/src/orm/core/providers/drivers/DatabaseProvider.ts +0 -5
  260. package/src/orm/core/providers/drivers/NodeSqliteProvider.ts +11 -13
  261. package/src/orm/core/schemas/updateSchema.ts +1 -1
  262. package/src/orm/core/services/ModelBuilder.ts +1 -13
  263. package/src/orm/core/services/PgRelationManager.ts +4 -2
  264. package/src/orm/core/services/Repository.ts +1 -42
  265. package/src/orm/core/services/SqliteModelBuilder.ts +2 -33
  266. package/src/orm/postgres/services/PostgresModelBuilder.ts +10 -45
  267. package/src/react/core/__tests__/useQuery.browser.spec.tsx +86 -0
  268. package/src/react/core/hooks/useQuery.ts +153 -0
  269. package/src/react/core/index.ts +1 -0
  270. package/src/react/form/services/FormModel.ts +15 -6
  271. package/src/react/form/services/parseField.ts +8 -0
  272. package/src/react/i18n/providers/I18nProvider.ts +8 -2
  273. package/src/react/intro/components/GettingStartedAuthSlide.tsx +11 -4
  274. package/src/react/router/__tests__/$page.spec.tsx +0 -16
  275. package/src/react/router/__tests__/ReactBrowserProvider.browser.spec.ts +213 -2
  276. package/src/react/router/__tests__/ssr.spec.tsx +339 -0
  277. package/src/react/router/primitives/$page.ts +28 -4
  278. package/src/react/router/providers/ReactBrowserProvider.ts +73 -0
  279. package/src/react/router/providers/ReactBrowserRouterProvider.ts +1 -1
  280. package/src/react/router/providers/ReactPageProvider.ts +27 -9
  281. package/src/react/router/providers/ReactPreloadProvider.ts +1 -1
  282. package/src/react/router/providers/ReactServerProvider.ts +1 -0
  283. package/src/react/ui/atoms/uiThemeListAtom.ts +36 -0
  284. package/src/react/ui/index.ts +6 -0
  285. package/src/react/ui/services/SchemaControl.ts +209 -0
  286. package/src/scheduler/providers/CronProvider.ts +1 -1
  287. package/src/security/primitives/$basicAuth.ts +1 -1
  288. package/src/security/primitives/$issuer.ts +6 -3
  289. package/src/server/auth/providers/ServerAuthProvider.ts +5 -1
  290. package/src/server/core/__tests__/ServerRouterProvider-serializationError.spec.ts +75 -0
  291. package/src/server/core/__tests__/ServerRouterProvider-validationError.spec.ts +306 -0
  292. package/src/server/core/errors/ValidationError.ts +13 -1
  293. package/src/server/core/interfaces/ServerRequest.ts +1 -0
  294. package/src/server/core/primitives/$action.ts +16 -5
  295. package/src/server/core/providers/ServerProvider.ts +1 -1
  296. package/src/server/core/providers/ServerRouterProvider.ts +28 -6
  297. package/src/server/core/services/HttpClient.ts +1 -1
  298. package/src/server/swagger/providers/ServerSwaggerProvider.ts +6 -8
  299. package/src/websocket/providers/NodeWebSocketServerProvider.ts +10 -4
  300. package/src/websocket/services/WebSocketClient.ts +11 -5
  301. package/src/mcp/transports/SseMcpTransport.ts +0 -182
  302. package/src/orm/core/__tests__/parseQueryString.spec.ts +0 -196
  303. package/src/orm/core/helpers/parseQueryString.ts +0 -502
  304. package/src/orm/core/primitives/$view.ts +0 -88
package/dist/mcp/index.js CHANGED
@@ -1,9 +1,25 @@
1
- import { $atom, $inject, $module, $state, Alepha, AlephaError, KIND, Primitive, createPrimitive, t } from "alepha";
1
+ import { $atom, $inject, $module, $state, Alepha, AlephaError, KIND, Primitive, TypeBoxError, createPrimitive, t } from "alepha";
2
2
  import { $logger } from "alepha/logger";
3
3
  import { $route } from "alepha/server";
4
4
  //#region ../../src/mcp/helpers/jsonrpc.ts
5
5
  const JSONRPC_VERSION = "2.0";
6
- const MCP_PROTOCOL_VERSION = "2024-11-05";
6
+ /**
7
+ * The latest MCP protocol revision Alepha targets.
8
+ * See {@link SUPPORTED_PROTOCOL_VERSIONS} for the full negotiation list.
9
+ */
10
+ const MCP_PROTOCOL_VERSION = "2025-11-25";
11
+ /**
12
+ * Protocol versions Alepha will accept during `initialize` negotiation,
13
+ * highest preference first. The server echoes back whichever version the
14
+ * client requested if it appears here, otherwise picks the first entry.
15
+ */
16
+ const SUPPORTED_PROTOCOL_VERSIONS = [
17
+ "2025-11-25",
18
+ "2025-06-18",
19
+ "2025-03-26",
20
+ "2024-11-05"
21
+ ];
22
+ const isSupportedProtocolVersion = (v) => typeof v === "string" && SUPPORTED_PROTOCOL_VERSIONS.includes(v);
7
23
  const JsonRpcErrorCodes = {
8
24
  PARSE_ERROR: -32700,
9
25
  INVALID_REQUEST: -32600,
@@ -170,6 +186,18 @@ var McpServerProvider = class {
170
186
  resources = /* @__PURE__ */ new Map();
171
187
  prompts = /* @__PURE__ */ new Map();
172
188
  initialized = false;
189
+ /**
190
+ * Protocol version negotiated with the client during `initialize`.
191
+ * Used by transports to validate the `MCP-Protocol-Version` header on
192
+ * subsequent HTTP requests (per spec 2025-06-18+).
193
+ */
194
+ negotiatedVersion = MCP_PROTOCOL_VERSION;
195
+ /**
196
+ * Server identity returned during `initialize`. Consumers may override
197
+ * fields directly (e.g. `mcpServer.serverInfo = { name: "roadmap-mcp",
198
+ * version: "0.20.3", description: "..." }`) — the `description` field
199
+ * is supported per spec 2025-11-25 (minor change #2).
200
+ */
173
201
  serverInfo = {
174
202
  name: "alepha-mcp",
175
203
  version: "1.0.0"
@@ -298,13 +326,17 @@ var McpServerProvider = class {
298
326
  }
299
327
  }
300
328
  handleInitialize(params) {
329
+ const requested = params.protocolVersion;
330
+ const negotiated = isSupportedProtocolVersion(requested) ? requested : SUPPORTED_PROTOCOL_VERSIONS[0];
301
331
  this.log.info("MCP client initializing", {
302
332
  clientInfo: params.clientInfo,
303
- protocolVersion: params.protocolVersion
333
+ requestedProtocolVersion: requested,
334
+ negotiatedProtocolVersion: negotiated
304
335
  });
305
336
  this.initialized = true;
337
+ this.negotiatedVersion = negotiated;
306
338
  return {
307
- protocolVersion: MCP_PROTOCOL_VERSION,
339
+ protocolVersion: negotiated,
308
340
  capabilities: this.getCapabilities(),
309
341
  serverInfo: this.serverInfo
310
342
  };
@@ -322,11 +354,28 @@ var McpServerProvider = class {
322
354
  if (!tool) throw new McpToolNotFoundError(name);
323
355
  try {
324
356
  const result = await tool.execute(args, context);
325
- return { content: [{
357
+ const callResult = { content: [{
326
358
  type: "text",
327
359
  text: typeof result === "string" ? result : JSON.stringify(result ?? null)
328
360
  }] };
361
+ if (tool.hasOutputSchema() && result !== void 0) callResult.structuredContent = result;
362
+ return callResult;
329
363
  } catch (error) {
364
+ if (error instanceof TypeBoxError) {
365
+ const path = error.value?.path || "/";
366
+ const message = error.value?.message || error.message;
367
+ return {
368
+ content: [{
369
+ type: "text",
370
+ text: `Validation error at ${path}: ${message}`
371
+ }],
372
+ structuredContent: { errors: [{
373
+ path,
374
+ message
375
+ }] },
376
+ isError: true
377
+ };
378
+ }
330
379
  return {
331
380
  content: [{
332
381
  type: "text",
@@ -456,11 +505,14 @@ var PromptPrimitive = class extends Primitive {
456
505
  * Convert the prompt to an MCP prompt descriptor for protocol messages.
457
506
  */
458
507
  toDescriptor() {
459
- return {
508
+ const descriptor = {
460
509
  name: this.name,
461
510
  description: this.description,
462
511
  arguments: this.options.args ? this.schemaToArguments(this.options.args) : []
463
512
  };
513
+ if (this.options.title) descriptor.title = this.options.title;
514
+ if (this.options.icons && this.options.icons.length > 0) descriptor.icons = this.options.icons;
515
+ return descriptor;
464
516
  }
465
517
  /**
466
518
  * Convert a TypeBox schema to an array of prompt arguments.
@@ -561,12 +613,15 @@ var ResourcePrimitive = class extends Primitive {
561
613
  * Convert the resource to an MCP resource descriptor for protocol messages.
562
614
  */
563
615
  toDescriptor() {
564
- return {
616
+ const descriptor = {
565
617
  uri: this.uri,
566
618
  name: this.name,
567
619
  description: this.description,
568
620
  mimeType: this.mimeType
569
621
  };
622
+ if (this.options.title) descriptor.title = this.options.title;
623
+ if (this.options.icons && this.options.icons.length > 0) descriptor.icons = this.options.icons;
624
+ return descriptor;
570
625
  }
571
626
  };
572
627
  $resource[KIND] = ResourcePrimitive;
@@ -633,6 +688,14 @@ var ToolPrimitive = class extends Primitive {
633
688
  get description() {
634
689
  return this.options.description;
635
690
  }
691
+ /**
692
+ * Whether the tool declared a result schema. When true, `tools/call`
693
+ * responses include `structuredContent` populated with the validated
694
+ * result (spec 2025-06-18).
695
+ */
696
+ hasOutputSchema() {
697
+ return !!this.options.schema?.result;
698
+ }
636
699
  onInit() {
637
700
  this.mcpServer.registerTool(this);
638
701
  }
@@ -655,33 +718,57 @@ var ToolPrimitive = class extends Primitive {
655
718
  }
656
719
  /**
657
720
  * Convert the tool to an MCP tool descriptor for protocol messages.
721
+ *
722
+ * Emits the spec 2025-11-25 surface: `title`, `annotations`, `icons`,
723
+ * and (when `schema.result` is defined) `outputSchema` so the server
724
+ * can populate `structuredContent` on call results.
658
725
  */
659
726
  toDescriptor() {
660
- return {
727
+ const inputSchema = this.options.schema?.params ? this.schemaToJsonSchema(this.options.schema.params) : {
728
+ type: "object",
729
+ properties: {},
730
+ required: []
731
+ };
732
+ const descriptor = {
661
733
  name: this.name,
662
734
  description: this.description,
663
- inputSchema: this.options.schema?.params ? this.schemaToJsonSchema(this.options.schema.params) : {
735
+ inputSchema
736
+ };
737
+ if (this.options.title) descriptor.title = this.options.title;
738
+ if (this.options.annotations) descriptor.annotations = this.options.annotations;
739
+ if (this.options.icons && this.options.icons.length > 0) descriptor.icons = this.options.icons;
740
+ if (this.options.schema?.result) {
741
+ const out = this.propertyToJsonSchema(this.options.schema.result);
742
+ descriptor.outputSchema = typeof out === "object" && out !== null && "type" in out ? out : {
664
743
  type: "object",
665
744
  properties: {},
666
745
  required: []
667
- }
668
- };
746
+ };
747
+ }
748
+ return descriptor;
669
749
  }
670
750
  /**
671
751
  * Convert a TypeBox schema to JSON Schema format.
752
+ *
753
+ * Emits the 2020-12 dialect annotation at the root (spec 2025-11-25 /
754
+ * SEP-1613 — JSON Schema 2020-12 is the default dialect for MCP).
755
+ * The TypeBox shapes Alepha emits today are already 2020-12-compatible;
756
+ * this is just the dialect declaration.
672
757
  */
673
- schemaToJsonSchema(schema) {
758
+ schemaToJsonSchema(schema, options) {
674
759
  const properties = {};
675
760
  const required = [];
676
761
  for (const [key, propSchema] of Object.entries(schema.properties)) {
677
762
  properties[key] = this.propertyToJsonSchema(propSchema);
678
763
  if (!t.schema.isOptional(propSchema)) required.push(key);
679
764
  }
680
- return {
765
+ const result = {
681
766
  type: "object",
682
767
  properties,
683
768
  required
684
769
  };
770
+ if (options?.root !== false) result.$schema = "https://json-schema.org/draft/2020-12/schema";
771
+ return result;
685
772
  }
686
773
  /**
687
774
  * Convert a single property schema to JSON Schema format.
@@ -707,7 +794,7 @@ var ToolPrimitive = class extends Primitive {
707
794
  else if (t.schema.isArray(schema)) {
708
795
  result.type = "array";
709
796
  if ("items" in schema) result.items = this.propertyToJsonSchema(schema.items);
710
- } else if (t.schema.isObject(schema)) Object.assign(result, this.schemaToJsonSchema(schema));
797
+ } else if (t.schema.isObject(schema)) Object.assign(result, this.schemaToJsonSchema(schema, { root: false }));
711
798
  else if (t.schema.isUnsafe(schema) || t.schema.isOptional(schema)) {
712
799
  const schemaAny = schema;
713
800
  if (schemaAny.type === "string") {
@@ -726,28 +813,59 @@ var ToolPrimitive = class extends Primitive {
726
813
  };
727
814
  $tool[KIND] = ToolPrimitive;
728
815
  //#endregion
729
- //#region ../../src/mcp/transports/SseMcpTransport.ts
730
- const mcpSseOptions = $atom({
731
- name: "alepha.mcp.sse.options",
732
- description: "Configuration options for the MCP SSE transport.",
733
- schema: t.object({ path: t.text({ default: "/mcp" }) }),
734
- default: { path: "/mcp" }
816
+ //#region ../../src/mcp/transports/StreamableHttpMcpTransport.ts
817
+ const mcpStreamableHttpOptions = $atom({
818
+ name: "alepha.mcp.streamableHttp.options",
819
+ description: "Configuration options for the MCP Streamable HTTP transport.",
820
+ schema: t.object({
821
+ /**
822
+ * Path for the MCP endpoint. Single endpoint for both requests and
823
+ * (optional) server-streamed responses, per spec 2025-03-26+.
824
+ */
825
+ path: t.text({ default: "/mcp" }),
826
+ /**
827
+ * Allow-list of `Origin` header values accepted on incoming requests.
828
+ * Empty array (default) means "allow any". When set, browser-originated
829
+ * requests with a non-matching `Origin` are rejected with 403 Forbidden,
830
+ * blocking DNS-rebinding attacks against localhost MCP servers.
831
+ *
832
+ * Server-to-server callers (no `Origin` header) are always allowed.
833
+ *
834
+ * Spec 2025-11-25, PR #1439.
835
+ */
836
+ allowedOrigins: t.array(t.text(), { default: [] })
837
+ }),
838
+ default: {
839
+ path: "/mcp",
840
+ allowedOrigins: []
841
+ }
735
842
  });
843
+ const mcpSseOptions = mcpStreamableHttpOptions;
736
844
  /**
737
- * SSE (Server-Sent Events) transport for MCP communication.
845
+ * Streamable HTTP transport for MCP communication.
846
+ *
847
+ * Implements the 2025-03-26+ Streamable HTTP transport: a single `/mcp`
848
+ * endpoint that accepts JSON-RPC over POST and returns either
849
+ * `application/json` (single response, the default) or
850
+ * `text/event-stream` (when the server wants to stream multiple messages).
738
851
  *
739
- * This transport uses HTTP with SSE for server-to-client messages
740
- * and POST requests for client-to-server messages.
852
+ * Designed for serverless deployment (Cloudflare Workers, etc.) there is
853
+ * no long-lived GET stream. GET on the endpoint returns 405 Method Not
854
+ * Allowed; clients that want server-initiated push must rely on the POST
855
+ * response stream when the server upgrades to SSE for that particular call.
741
856
  *
742
- * Endpoints:
743
- * - GET /mcp - SSE stream for server events
744
- * - POST /mcp - JSON-RPC request endpoint
857
+ * Spec compliance:
858
+ * - 2025-06-18: validates `MCP-Protocol-Version` header on every request
859
+ * after `initialize` against the version negotiated and stored on
860
+ * `McpServerProvider`.
861
+ * - 2025-11-25: rejects requests with a non-allow-listed `Origin` header
862
+ * (PR #1439). See {@link mcpStreamableHttpOptions.allowedOrigins}.
745
863
  *
746
864
  * @example
747
865
  * ```ts
748
866
  * import { Alepha, run } from "alepha";
749
867
  * import { AlephaServer } from "alepha/server";
750
- * import { AlephaMcp, AlephaMcpSse } from "alepha/mcp";
868
+ * import { AlephaMcp, StreamableHttpMcpTransport } from "alepha/mcp";
751
869
  *
752
870
  * class MyTools {
753
871
  * // ... tool definitions
@@ -757,50 +875,36 @@ const mcpSseOptions = $atom({
757
875
  * Alepha.create()
758
876
  * .with(AlephaServer)
759
877
  * .with(AlephaMcp)
760
- * .with(AlephaMcpSse)
878
+ * .with(StreamableHttpMcpTransport)
761
879
  * .with(MyTools)
762
880
  * );
763
881
  * ```
764
882
  */
765
- var SseMcpTransport = class {
883
+ var StreamableHttpMcpTransport = class {
766
884
  log = $logger();
767
- options = $state(mcpSseOptions);
885
+ options = $state(mcpStreamableHttpOptions);
768
886
  mcpServer = $inject(McpServerProvider);
769
887
  /**
770
- * SSE endpoint for server-to-client messages.
771
- *
772
- * Returns a text/event-stream response with server capabilities
773
- * and keeps the connection open for notifications.
888
+ * GET on the MCP endpoint is not supported in this transport. Returning
889
+ * 405 (rather than serving the legacy two-endpoint SSE pattern) is the
890
+ * spec-allowed response for servers that don't offer server-initiated
891
+ * push outside of an active POST.
774
892
  */
775
- sse = $route({
893
+ notAllowed = $route({
776
894
  method: "GET",
777
895
  path: this.options.path,
778
- handler: async (request) => {
779
- this.log.debug("MCP SSE connection established");
780
- const encoder = new TextEncoder();
781
- const stream = new ReadableStream({
782
- start: (controller) => {
783
- const endpointEvent = this.formatSseEvent("endpoint", `${this.options.path}`);
784
- controller.enqueue(encoder.encode(endpointEvent));
785
- const capabilitiesNotification = createNotification("notifications/capabilities", { capabilities: this.mcpServer.getCapabilities() });
786
- const capabilitiesEvent = this.formatSseEvent("message", JSON.stringify(capabilitiesNotification));
787
- controller.enqueue(encoder.encode(capabilitiesEvent));
788
- },
789
- cancel: () => {
790
- this.log.debug("MCP SSE connection closed");
791
- }
792
- });
793
- request.reply.status = 200;
794
- request.reply.headers = {
795
- "content-type": "text/event-stream",
796
- "cache-control": "no-cache",
797
- connection: "keep-alive"
798
- };
799
- request.reply.body = stream;
896
+ handler: (request) => {
897
+ request.reply.status = 405;
898
+ request.reply.headers.allow = "POST";
899
+ request.reply.headers["content-type"] = "application/json";
900
+ request.reply.body = JSON.stringify({ error: "Method Not Allowed. Use POST for MCP messages." });
800
901
  }
801
902
  });
802
903
  /**
803
904
  * POST endpoint for client-to-server JSON-RPC messages.
905
+ * Returns `application/json` for single responses; tools that need to
906
+ * stream progress would upgrade to `text/event-stream` (deferred until a
907
+ * concrete need exists).
804
908
  */
805
909
  message = $route({
806
910
  method: "POST",
@@ -808,13 +912,40 @@ var SseMcpTransport = class {
808
912
  schema: { body: t.json() },
809
913
  handler: async (request) => {
810
914
  try {
915
+ const originRaw = request.headers.origin;
916
+ const origin = Array.isArray(originRaw) ? originRaw[0] : originRaw;
917
+ if (origin && this.options.allowedOrigins.length > 0 && !this.options.allowedOrigins.includes(origin)) {
918
+ this.log.warn("Rejected MCP request with non-allowed Origin", {
919
+ origin,
920
+ allowed: this.options.allowedOrigins
921
+ });
922
+ request.reply.status = 403;
923
+ request.reply.headers["content-type"] = "application/json";
924
+ request.reply.body = JSON.stringify({ error: "Forbidden: Origin not allowed" });
925
+ return;
926
+ }
811
927
  const body = typeof request.body === "string" ? request.body : JSON.stringify(request.body);
812
928
  this.log.debug("MCP request body", {
813
929
  body,
814
930
  bodyType: typeof request.body
815
931
  });
816
932
  const rpcRequest = parseMessage(body);
817
- const context = { headers: { ...request.headers } };
933
+ const headers = { ...request.headers };
934
+ if (rpcRequest.method !== "initialize") {
935
+ const headerRaw = headers["mcp-protocol-version"];
936
+ const headerVersion = Array.isArray(headerRaw) ? headerRaw[0] : headerRaw;
937
+ if (headerVersion && headerVersion !== this.mcpServer.negotiatedVersion) {
938
+ this.log.warn("MCP-Protocol-Version header mismatch", {
939
+ header: headerVersion,
940
+ negotiated: this.mcpServer.negotiatedVersion
941
+ });
942
+ request.reply.status = 400;
943
+ request.reply.headers["content-type"] = "application/json";
944
+ request.reply.body = JSON.stringify({ error: `MCP-Protocol-Version mismatch: expected ${this.mcpServer.negotiatedVersion}, got ${headerVersion}` });
945
+ return;
946
+ }
947
+ }
948
+ const context = { headers };
818
949
  const response = await this.mcpServer.handleMessage(rpcRequest, context);
819
950
  if (response) {
820
951
  request.reply.headers["content-type"] = "application/json";
@@ -833,13 +964,13 @@ var SseMcpTransport = class {
833
964
  }
834
965
  }
835
966
  });
836
- /**
837
- * Format a message as an SSE event.
838
- */
839
- formatSseEvent(event, data) {
840
- return `event: ${event}\ndata: ${data}\n\n`;
841
- }
842
967
  };
968
+ /**
969
+ * @deprecated Use {@link StreamableHttpMcpTransport}. The 2024-11-05
970
+ * two-endpoint HTTP+SSE pattern was replaced by Streamable HTTP in spec
971
+ * 2025-03-26. This alias is preserved for one release to ease migration.
972
+ */
973
+ const SseMcpTransport = StreamableHttpMcpTransport;
843
974
  //#endregion
844
975
  //#region ../../src/mcp/index.ts
845
976
  /**
@@ -850,7 +981,7 @@ var SseMcpTransport = class {
850
981
  * - MCP tool definitions
851
982
  * - MCP prompt definitions
852
983
  * - JSON-RPC protocol
853
- * - SSE and Stdio transports
984
+ * - Streamable HTTP transport (spec 2025-03-26+)
854
985
  *
855
986
  * @module alepha.mcp
856
987
  */
@@ -862,9 +993,9 @@ const AlephaMcp = $module({
862
993
  $prompt
863
994
  ],
864
995
  services: [McpServerProvider],
865
- variants: [SseMcpTransport]
996
+ variants: [StreamableHttpMcpTransport]
866
997
  });
867
998
  //#endregion
868
- export { $prompt, $resource, $tool, AlephaMcp, JSONRPC_VERSION, JsonRpcErrorCodes, JsonRpcParseError, MCP_PROTOCOL_VERSION, McpError, McpErrorCodes, McpForbiddenError, McpInvalidParamsError, McpMethodNotFoundError, McpPromptNotFoundError, McpResourceNotFoundError, McpServerProvider, McpToolNotFoundError, McpUnauthorizedError, PromptPrimitive, ResourcePrimitive, SseMcpTransport, ToolPrimitive, createErrorResponse, createInternalError, createInvalidParamsError, createInvalidRequestError, createMethodNotFoundError, createNotification, createParseError, createResponse, isNotification, isValidJsonRpcRequest, mcpSseOptions, parseMessage };
999
+ export { $prompt, $resource, $tool, AlephaMcp, JSONRPC_VERSION, JsonRpcErrorCodes, JsonRpcParseError, MCP_PROTOCOL_VERSION, McpError, McpErrorCodes, McpForbiddenError, McpInvalidParamsError, McpMethodNotFoundError, McpPromptNotFoundError, McpResourceNotFoundError, McpServerProvider, McpToolNotFoundError, McpUnauthorizedError, PromptPrimitive, ResourcePrimitive, SUPPORTED_PROTOCOL_VERSIONS, SseMcpTransport, StreamableHttpMcpTransport, ToolPrimitive, createErrorResponse, createInternalError, createInvalidParamsError, createInvalidRequestError, createMethodNotFoundError, createNotification, createParseError, createResponse, isNotification, isSupportedProtocolVersion, isValidJsonRpcRequest, mcpSseOptions, mcpStreamableHttpOptions, parseMessage };
869
1000
 
870
1001
  //# sourceMappingURL=index.js.map