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
@@ -25,7 +25,7 @@ describe("jsonrpc constants", () => {
25
25
  });
26
26
 
27
27
  test("MCP_PROTOCOL_VERSION should be defined", () => {
28
- expect(MCP_PROTOCOL_VERSION).toBe("2024-11-05");
28
+ expect(MCP_PROTOCOL_VERSION).toBe("2025-11-25");
29
29
  });
30
30
 
31
31
  test("JsonRpcErrorCodes should have correct values", () => {
@@ -12,7 +12,32 @@ import type {
12
12
 
13
13
  export const JSONRPC_VERSION = "2.0" as const;
14
14
 
15
- export const MCP_PROTOCOL_VERSION = "2024-11-05" as const;
15
+ /**
16
+ * The latest MCP protocol revision Alepha targets.
17
+ * See {@link SUPPORTED_PROTOCOL_VERSIONS} for the full negotiation list.
18
+ */
19
+ export const MCP_PROTOCOL_VERSION = "2025-11-25" as const;
20
+
21
+ /**
22
+ * Protocol versions Alepha will accept during `initialize` negotiation,
23
+ * highest preference first. The server echoes back whichever version the
24
+ * client requested if it appears here, otherwise picks the first entry.
25
+ */
26
+ export const SUPPORTED_PROTOCOL_VERSIONS = [
27
+ "2025-11-25",
28
+ "2025-06-18",
29
+ "2025-03-26",
30
+ "2024-11-05",
31
+ ] as const;
32
+
33
+ export type SupportedProtocolVersion =
34
+ (typeof SUPPORTED_PROTOCOL_VERSIONS)[number];
35
+
36
+ export const isSupportedProtocolVersion = (
37
+ v: unknown,
38
+ ): v is SupportedProtocolVersion =>
39
+ typeof v === "string" &&
40
+ (SUPPORTED_PROTOCOL_VERSIONS as readonly string[]).includes(v);
16
41
 
17
42
  export const JsonRpcErrorCodes = {
18
43
  PARSE_ERROR: -32700,
package/src/mcp/index.ts CHANGED
@@ -3,7 +3,7 @@ import { $prompt } from "./primitives/$prompt.ts";
3
3
  import { $resource } from "./primitives/$resource.ts";
4
4
  import { $tool } from "./primitives/$tool.ts";
5
5
  import { McpServerProvider } from "./providers/McpServerProvider.ts";
6
- import { SseMcpTransport } from "./transports/SseMcpTransport.ts";
6
+ import { StreamableHttpMcpTransport } from "./transports/StreamableHttpMcpTransport.ts";
7
7
 
8
8
  // ---------------------------------------------------------------------------------------------------------------------
9
9
 
@@ -28,12 +28,15 @@ export {
28
28
  createParseError,
29
29
  createResponse,
30
30
  isNotification,
31
+ isSupportedProtocolVersion,
31
32
  isValidJsonRpcRequest,
32
33
  JSONRPC_VERSION,
33
34
  JsonRpcErrorCodes,
34
35
  JsonRpcParseError,
35
36
  MCP_PROTOCOL_VERSION,
36
37
  parseMessage,
38
+ SUPPORTED_PROTOCOL_VERSIONS,
39
+ type SupportedProtocolVersion,
37
40
  } from "./helpers/jsonrpc.ts";
38
41
  export type {
39
42
  JsonRpcError,
@@ -88,8 +91,10 @@ export { $tool, ToolPrimitive } from "./primitives/$tool.ts";
88
91
  export { McpServerProvider } from "./providers/McpServerProvider.ts";
89
92
  export {
90
93
  mcpSseOptions,
94
+ mcpStreamableHttpOptions,
91
95
  SseMcpTransport,
92
- } from "./transports/SseMcpTransport.ts";
96
+ StreamableHttpMcpTransport,
97
+ } from "./transports/StreamableHttpMcpTransport.ts";
93
98
 
94
99
  // ---------------------------------------------------------------------------------------------------------------------
95
100
 
@@ -101,7 +106,7 @@ export {
101
106
  * - MCP tool definitions
102
107
  * - MCP prompt definitions
103
108
  * - JSON-RPC protocol
104
- * - SSE and Stdio transports
109
+ * - Streamable HTTP transport (spec 2025-03-26+)
105
110
  *
106
111
  * @module alepha.mcp
107
112
  */
@@ -109,6 +114,6 @@ export const AlephaMcp = $module({
109
114
  name: "alepha.mcp",
110
115
  primitives: [$tool, $resource, $prompt],
111
116
  services: [McpServerProvider],
112
- // Transports are opt-in — user wires the one(s) they need via alepha.with(SseMcpTransport).
113
- variants: [SseMcpTransport],
117
+ // Transports are opt-in — user wires the one(s) they need via alepha.with(StreamableHttpMcpTransport).
118
+ variants: [StreamableHttpMcpTransport],
114
119
  });
@@ -40,14 +40,48 @@ export interface McpCapabilities {
40
40
  prompts?: Record<string, never>;
41
41
  }
42
42
 
43
+ /**
44
+ * Spec 2025-11-25: optional `description` aligns with the MCP registry's
45
+ * `server.json` format and provides human-readable context during init.
46
+ */
43
47
  export interface McpServerInfo {
44
48
  name: string;
45
49
  version: string;
50
+ description?: string;
46
51
  }
47
52
 
48
53
  export interface McpClientInfo {
49
54
  name: string;
50
55
  version: string;
56
+ description?: string;
57
+ }
58
+
59
+ /**
60
+ * Icon descriptor (spec 2025-11-25 / SEP-973). Mirrors web app manifest
61
+ * icon shape — clients render these in tool palettes / picker UIs.
62
+ */
63
+ export interface McpIcon {
64
+ src: string;
65
+ mimeType?: string;
66
+ sizes?: string;
67
+ }
68
+
69
+ /**
70
+ * Tool annotations (spec 2025-03-26+). Hints to the client about how to
71
+ * present and gate the tool. None are guarantees — the client uses these
72
+ * heuristically (e.g. to show a confirmation prompt for destructive tools).
73
+ */
74
+ export interface McpToolAnnotations {
75
+ /** Human-friendly display title (distinct from `name`, the programmatic id). */
76
+ title?: string;
77
+ /** Tool reads only; safe to auto-approve. */
78
+ readOnlyHint?: boolean;
79
+ /** Tool may delete or overwrite data; client should require confirmation. */
80
+ destructiveHint?: boolean;
81
+ /** Calling the tool with the same args twice yields the same end state. */
82
+ idempotentHint?: boolean;
83
+ /** Tool interacts with the open world (network, etc.) vs. a closed system. */
84
+ openWorldHint?: boolean;
51
85
  }
52
86
 
53
87
  export interface McpInitializeParams {
@@ -68,14 +102,27 @@ export interface McpInitializeResult {
68
102
 
69
103
  export interface McpToolDescriptor {
70
104
  name: string;
105
+ /** Human-friendly display label (spec 2025-11-25). Distinct from `name`. */
106
+ title?: string;
71
107
  description: string;
72
108
  inputSchema: McpJsonSchema;
109
+ /** Output schema enabling `structuredContent` on call results (spec 2025-06-18). */
110
+ outputSchema?: McpJsonSchema;
111
+ /** Behavior hints (spec 2025-03-26+). */
112
+ annotations?: McpToolAnnotations;
113
+ /** Optional icons (spec 2025-11-25 / SEP-973). */
114
+ icons?: McpIcon[];
115
+ /** Arbitrary metadata passthrough (spec 2025-06-18+). */
116
+ _meta?: Record<string, unknown>;
73
117
  }
74
118
 
75
119
  export interface McpJsonSchema {
76
120
  type: string;
77
121
  properties?: Record<string, unknown>;
78
122
  required?: string[];
123
+ /** JSON Schema dialect (spec 2025-11-25 / SEP-1613 — defaults to 2020-12). */
124
+ $schema?: string;
125
+ [key: string]: unknown;
79
126
  }
80
127
 
81
128
  export interface McpToolCallParams {
@@ -85,15 +132,33 @@ export interface McpToolCallParams {
85
132
 
86
133
  export interface McpToolCallResult {
87
134
  content: McpContent[];
135
+ /**
136
+ * Structured tool output (spec 2025-06-18). When the tool declares an
137
+ * `outputSchema`, the server MUST populate `structuredContent`; the
138
+ * `content` array carrying a JSON-stringified text block is kept as
139
+ * a back-compat fallback for older clients.
140
+ */
141
+ structuredContent?: unknown;
88
142
  isError?: boolean;
143
+ _meta?: Record<string, unknown>;
89
144
  }
90
145
 
91
- export interface McpContent {
92
- type: "text" | "image" | "resource";
93
- text?: string;
94
- data?: string;
95
- mimeType?: string;
96
- }
146
+ /**
147
+ * Discriminated content union covering text, image, audio (added 2025-03-26),
148
+ * inlined resources, and resource links (added 2025-06-18).
149
+ */
150
+ export type McpContent =
151
+ | { type: "text"; text: string }
152
+ | { type: "image"; data: string; mimeType: string }
153
+ | { type: "audio"; data: string; mimeType: string }
154
+ | { type: "resource"; resource: McpResourceContent }
155
+ | {
156
+ type: "resource_link";
157
+ uri: string;
158
+ name: string;
159
+ description?: string;
160
+ mimeType?: string;
161
+ };
97
162
 
98
163
  // ---------------------------------------------------------------------------------------------------------------------
99
164
  // Resource Types
@@ -102,8 +167,14 @@ export interface McpContent {
102
167
  export interface McpResourceDescriptor {
103
168
  uri: string;
104
169
  name: string;
170
+ /** Human-friendly display label (spec 2025-11-25). Distinct from `name`. */
171
+ title?: string;
105
172
  description?: string;
106
173
  mimeType?: string;
174
+ /** Optional icons (spec 2025-11-25 / SEP-973). */
175
+ icons?: McpIcon[];
176
+ /** Arbitrary metadata passthrough (spec 2025-06-18+). */
177
+ _meta?: Record<string, unknown>;
107
178
  }
108
179
 
109
180
  export interface McpResourceReadParams {
@@ -127,8 +198,14 @@ export interface McpResourceContent {
127
198
 
128
199
  export interface McpPromptDescriptor {
129
200
  name: string;
201
+ /** Human-friendly display label (spec 2025-11-25). Distinct from `name`. */
202
+ title?: string;
130
203
  description?: string;
131
204
  arguments?: McpPromptArgument[];
205
+ /** Optional icons (spec 2025-11-25 / SEP-973). */
206
+ icons?: McpIcon[];
207
+ /** Arbitrary metadata passthrough (spec 2025-06-18+). */
208
+ _meta?: Record<string, unknown>;
132
209
  }
133
210
 
134
211
  export interface McpPromptArgument {
@@ -10,6 +10,7 @@ import {
10
10
  } from "alepha";
11
11
  import type {
12
12
  McpContext,
13
+ McpIcon,
13
14
  McpPromptArgument,
14
15
  McpPromptDescriptor,
15
16
  PromptHandlerArgs,
@@ -80,6 +81,12 @@ export interface PromptPrimitiveOptions<T extends TObject> {
80
81
  */
81
82
  name?: string;
82
83
 
84
+ /**
85
+ * Human-friendly display title (spec 2025-11-25). Distinct from `name`,
86
+ * which remains the programmatic identifier.
87
+ */
88
+ title?: string;
89
+
83
90
  /**
84
91
  * Description of what this prompt does.
85
92
  *
@@ -89,6 +96,11 @@ export interface PromptPrimitiveOptions<T extends TObject> {
89
96
  */
90
97
  description?: string;
91
98
 
99
+ /**
100
+ * Optional icons surfaced in client UIs (spec 2025-11-25 / SEP-973).
101
+ */
102
+ icons?: McpIcon[];
103
+
92
104
  /**
93
105
  * TypeBox schema defining the prompt arguments.
94
106
  *
@@ -157,13 +169,18 @@ export class PromptPrimitive<T extends TObject> extends Primitive<
157
169
  * Convert the prompt to an MCP prompt descriptor for protocol messages.
158
170
  */
159
171
  public toDescriptor(): McpPromptDescriptor {
160
- return {
172
+ const descriptor: McpPromptDescriptor = {
161
173
  name: this.name,
162
174
  description: this.description,
163
175
  arguments: this.options.args
164
176
  ? this.schemaToArguments(this.options.args)
165
177
  : [],
166
178
  };
179
+ if (this.options.title) descriptor.title = this.options.title;
180
+ if (this.options.icons && this.options.icons.length > 0) {
181
+ descriptor.icons = this.options.icons;
182
+ }
183
+ return descriptor;
167
184
  }
168
185
 
169
186
  /**
@@ -1,6 +1,7 @@
1
1
  import { $inject, createPrimitive, KIND, Primitive } from "alepha";
2
2
  import type {
3
3
  McpContext,
4
+ McpIcon,
4
5
  McpResourceDescriptor,
5
6
  ResourceContent,
6
7
  ResourceHandler,
@@ -78,6 +79,17 @@ export interface ResourcePrimitiveOptions {
78
79
  */
79
80
  name?: string;
80
81
 
82
+ /**
83
+ * Human-friendly display title (spec 2025-11-25). Distinct from `name`,
84
+ * which remains the programmatic identifier.
85
+ */
86
+ title?: string;
87
+
88
+ /**
89
+ * Optional icons surfaced in client UIs (spec 2025-11-25 / SEP-973).
90
+ */
91
+ icons?: McpIcon[];
92
+
81
93
  /**
82
94
  * Description of what this resource contains.
83
95
  *
@@ -159,12 +171,17 @@ export class ResourcePrimitive extends Primitive<ResourcePrimitiveOptions> {
159
171
  * Convert the resource to an MCP resource descriptor for protocol messages.
160
172
  */
161
173
  public toDescriptor(): McpResourceDescriptor {
162
- return {
174
+ const descriptor: McpResourceDescriptor = {
163
175
  uri: this.uri,
164
176
  name: this.name,
165
177
  description: this.description,
166
178
  mimeType: this.mimeType,
167
179
  };
180
+ if (this.options.title) descriptor.title = this.options.title;
181
+ if (this.options.icons && this.options.icons.length > 0) {
182
+ descriptor.icons = this.options.icons;
183
+ }
184
+ return descriptor;
168
185
  }
169
186
  }
170
187
 
@@ -10,7 +10,9 @@ import {
10
10
  } from "alepha";
11
11
  import type {
12
12
  McpContext,
13
+ McpIcon,
13
14
  McpJsonSchema,
15
+ McpToolAnnotations,
14
16
  McpToolDescriptor,
15
17
  ToolHandlerArgs,
16
18
  ToolHandlerResult,
@@ -84,6 +86,15 @@ export interface ToolPrimitiveOptions<T extends ToolPrimitiveSchema> {
84
86
  */
85
87
  name?: string;
86
88
 
89
+ /**
90
+ * Human-friendly display title (spec 2025-11-25). Distinct from `name`,
91
+ * which remains the programmatic identifier. Clients use `title` in
92
+ * tool palettes / picker UIs.
93
+ *
94
+ * @example "Search Lore"
95
+ */
96
+ title?: string;
97
+
87
98
  /**
88
99
  * A human-readable description of what the tool does.
89
100
  *
@@ -95,6 +106,18 @@ export interface ToolPrimitiveOptions<T extends ToolPrimitiveSchema> {
95
106
  */
96
107
  description: string;
97
108
 
109
+ /**
110
+ * Behavior hints (spec 2025-03-26+). Clients use these to gate UI prompts
111
+ * (e.g. require confirmation before a tool with `destructiveHint: true`).
112
+ * None are guarantees — they are heuristics for the client, not the model.
113
+ */
114
+ annotations?: McpToolAnnotations;
115
+
116
+ /**
117
+ * Icons surfaced in client tool palettes / picker UIs (spec 2025-11-25).
118
+ */
119
+ icons?: McpIcon[];
120
+
98
121
  /**
99
122
  * TypeBox schema defining the tool's parameters and result type.
100
123
  *
@@ -141,6 +164,15 @@ export class ToolPrimitive<T extends ToolPrimitiveSchema> extends Primitive<
141
164
  return this.options.description;
142
165
  }
143
166
 
167
+ /**
168
+ * Whether the tool declared a result schema. When true, `tools/call`
169
+ * responses include `structuredContent` populated with the validated
170
+ * result (spec 2025-06-18).
171
+ */
172
+ public hasOutputSchema(): boolean {
173
+ return !!this.options.schema?.result;
174
+ }
175
+
144
176
  protected onInit(): void {
145
177
  this.mcpServer.registerTool(this);
146
178
  }
@@ -184,21 +216,57 @@ export class ToolPrimitive<T extends ToolPrimitiveSchema> extends Primitive<
184
216
 
185
217
  /**
186
218
  * Convert the tool to an MCP tool descriptor for protocol messages.
219
+ *
220
+ * Emits the spec 2025-11-25 surface: `title`, `annotations`, `icons`,
221
+ * and (when `schema.result` is defined) `outputSchema` so the server
222
+ * can populate `structuredContent` on call results.
187
223
  */
188
224
  public toDescriptor(): McpToolDescriptor {
189
- return {
225
+ const inputSchema: McpJsonSchema = this.options.schema?.params
226
+ ? this.schemaToJsonSchema(this.options.schema.params)
227
+ : { type: "object", properties: {}, required: [] };
228
+
229
+ const descriptor: McpToolDescriptor = {
190
230
  name: this.name,
191
231
  description: this.description,
192
- inputSchema: this.options.schema?.params
193
- ? this.schemaToJsonSchema(this.options.schema.params)
194
- : { type: "object", properties: {}, required: [] },
232
+ inputSchema,
195
233
  };
234
+
235
+ if (this.options.title) descriptor.title = this.options.title;
236
+ if (this.options.annotations)
237
+ descriptor.annotations = this.options.annotations;
238
+ if (this.options.icons && this.options.icons.length > 0) {
239
+ descriptor.icons = this.options.icons;
240
+ }
241
+
242
+ // Output schema is emitted when the tool declares `schema.result`,
243
+ // unlocking structured content on tools/call responses.
244
+ if (this.options.schema?.result) {
245
+ const out = this.propertyToJsonSchema(this.options.schema.result);
246
+ // The result schema may be a primitive — wrap so the descriptor
247
+ // value is always a JSON Schema object with `type`.
248
+ descriptor.outputSchema = (
249
+ typeof out === "object" && out !== null && "type" in out
250
+ ? out
251
+ : { type: "object", properties: {}, required: [] }
252
+ ) as McpJsonSchema;
253
+ }
254
+
255
+ return descriptor;
196
256
  }
197
257
 
198
258
  /**
199
259
  * Convert a TypeBox schema to JSON Schema format.
260
+ *
261
+ * Emits the 2020-12 dialect annotation at the root (spec 2025-11-25 /
262
+ * SEP-1613 — JSON Schema 2020-12 is the default dialect for MCP).
263
+ * The TypeBox shapes Alepha emits today are already 2020-12-compatible;
264
+ * this is just the dialect declaration.
200
265
  */
201
- protected schemaToJsonSchema(schema: TObject): McpJsonSchema {
266
+ protected schemaToJsonSchema(
267
+ schema: TObject,
268
+ options?: { root?: boolean },
269
+ ): McpJsonSchema {
202
270
  const properties: Record<string, unknown> = {};
203
271
  const required: string[] = [];
204
272
 
@@ -211,11 +279,19 @@ export class ToolPrimitive<T extends ToolPrimitiveSchema> extends Primitive<
211
279
  }
212
280
  }
213
281
 
214
- return {
282
+ const result: McpJsonSchema = {
215
283
  type: "object",
216
284
  properties,
217
285
  required,
218
286
  };
287
+
288
+ // Annotate the dialect on the root schema only (avoid noise on nested
289
+ // sub-schemas where MCP doesn't expect $schema).
290
+ if (options?.root !== false) {
291
+ result.$schema = "https://json-schema.org/draft/2020-12/schema";
292
+ }
293
+
294
+ return result;
219
295
  }
220
296
 
221
297
  /**
@@ -251,7 +327,7 @@ export class ToolPrimitive<T extends ToolPrimitiveSchema> extends Primitive<
251
327
  result.items = this.propertyToJsonSchema(schema.items as TSchema);
252
328
  }
253
329
  } else if (t.schema.isObject(schema)) {
254
- Object.assign(result, this.schemaToJsonSchema(schema));
330
+ Object.assign(result, this.schemaToJsonSchema(schema, { root: false }));
255
331
  } else if (t.schema.isUnsafe(schema) || t.schema.isOptional(schema)) {
256
332
  // Handle Unsafe types (like t.enum) and optional wrappers by checking the underlying type property
257
333
  const schemaAny = schema as { type?: string; enum?: unknown[] };
@@ -1,4 +1,4 @@
1
- import { $inject, Alepha } from "alepha";
1
+ import { $inject, Alepha, TypeBoxError } from "alepha";
2
2
  import { $logger } from "alepha/logger";
3
3
  import {
4
4
  McpError,
@@ -11,13 +11,14 @@ import {
11
11
  createErrorResponse,
12
12
  createInternalError,
13
13
  createResponse,
14
+ isSupportedProtocolVersion,
14
15
  MCP_PROTOCOL_VERSION,
16
+ SUPPORTED_PROTOCOL_VERSIONS,
15
17
  } from "../helpers/jsonrpc.ts";
16
18
  import type {
17
19
  JsonRpcRequest,
18
20
  JsonRpcResponse,
19
21
  McpCapabilities,
20
- McpContent,
21
22
  McpContext,
22
23
  McpInitializeResult,
23
24
  McpPromptDescriptor,
@@ -55,7 +56,20 @@ export class McpServerProvider {
55
56
 
56
57
  protected initialized = false;
57
58
 
58
- protected serverInfo: McpServerInfo = {
59
+ /**
60
+ * Protocol version negotiated with the client during `initialize`.
61
+ * Used by transports to validate the `MCP-Protocol-Version` header on
62
+ * subsequent HTTP requests (per spec 2025-06-18+).
63
+ */
64
+ public negotiatedVersion: string = MCP_PROTOCOL_VERSION;
65
+
66
+ /**
67
+ * Server identity returned during `initialize`. Consumers may override
68
+ * fields directly (e.g. `mcpServer.serverInfo = { name: "roadmap-mcp",
69
+ * version: "0.20.3", description: "..." }`) — the `description` field
70
+ * is supported per spec 2025-11-25 (minor change #2).
71
+ */
72
+ public serverInfo: McpServerInfo = {
59
73
  name: "alepha-mcp",
60
74
  version: "1.0.0",
61
75
  };
@@ -243,15 +257,25 @@ export class McpServerProvider {
243
257
  protected handleInitialize(
244
258
  params: Record<string, unknown>,
245
259
  ): McpInitializeResult {
260
+ const requested = params.protocolVersion;
261
+ // Echo the client's version when supported, otherwise reply with our
262
+ // preferred version (highest entry in SUPPORTED_PROTOCOL_VERSIONS).
263
+ // The client can then decide to retry, downgrade, or disconnect.
264
+ const negotiated = isSupportedProtocolVersion(requested)
265
+ ? requested
266
+ : SUPPORTED_PROTOCOL_VERSIONS[0];
267
+
246
268
  this.log.info("MCP client initializing", {
247
269
  clientInfo: params.clientInfo,
248
- protocolVersion: params.protocolVersion,
270
+ requestedProtocolVersion: requested,
271
+ negotiatedProtocolVersion: negotiated,
249
272
  });
250
273
 
251
274
  this.initialized = true;
275
+ this.negotiatedVersion = negotiated;
252
276
 
253
277
  return {
254
- protocolVersion: MCP_PROTOCOL_VERSION,
278
+ protocolVersion: negotiated,
255
279
  capabilities: this.getCapabilities(),
256
280
  serverInfo: this.serverInfo,
257
281
  };
@@ -276,24 +300,58 @@ export class McpServerProvider {
276
300
 
277
301
  const tool = this.tools.get(name);
278
302
  if (!tool) {
303
+ // McpToolNotFoundError is intentionally a JSON-RPC protocol error,
304
+ // not a tool execution error — see SEP-1303 (only validation/runtime
305
+ // failures of an existing tool are reported via isError: true).
279
306
  throw new McpToolNotFoundError(name);
280
307
  }
281
308
 
282
309
  try {
283
310
  const result = await tool.execute(args, context);
284
311
 
285
- const content: McpContent[] = [
286
- {
287
- type: "text",
288
- text:
289
- typeof result === "string"
290
- ? result
291
- : JSON.stringify(result ?? null),
292
- },
293
- ];
294
-
295
- return { content };
312
+ const callResult: McpToolCallResult = {
313
+ content: [
314
+ {
315
+ type: "text",
316
+ text:
317
+ typeof result === "string"
318
+ ? result
319
+ : JSON.stringify(result ?? null),
320
+ },
321
+ ],
322
+ };
323
+
324
+ // Spec 2025-06-18: when the tool declares an outputSchema, the server
325
+ // MUST populate `structuredContent` with the validated result. The
326
+ // text-stringified `content` block remains as a back-compat fallback.
327
+ if (tool.hasOutputSchema() && result !== undefined) {
328
+ callResult.structuredContent = result;
329
+ }
330
+
331
+ return callResult;
296
332
  } catch (error) {
333
+ // Spec 2025-11-25 / SEP-1303: input-validation failures (and other
334
+ // tool-runtime errors) are returned as Tool Execution Errors, not
335
+ // JSON-RPC protocol errors, so the model can self-correct.
336
+ // For TypeBox validation errors we surface the failing path so the
337
+ // model knows which argument was malformed.
338
+ if (error instanceof TypeBoxError) {
339
+ const path = error.value?.path || "/";
340
+ const message = error.value?.message || error.message;
341
+ return {
342
+ content: [
343
+ {
344
+ type: "text",
345
+ text: `Validation error at ${path}: ${message}`,
346
+ },
347
+ ],
348
+ structuredContent: {
349
+ errors: [{ path, message }],
350
+ },
351
+ isError: true,
352
+ };
353
+ }
354
+
297
355
  return {
298
356
  content: [
299
357
  {