alepha 0.13.8 → 0.14.1

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 (160) hide show
  1. package/dist/api/audits/index.d.ts +418 -338
  2. package/dist/api/audits/index.d.ts.map +1 -0
  3. package/dist/api/files/index.d.ts +81 -1
  4. package/dist/api/files/index.d.ts.map +1 -0
  5. package/dist/api/jobs/index.d.ts +107 -27
  6. package/dist/api/jobs/index.d.ts.map +1 -0
  7. package/dist/api/notifications/index.d.ts +21 -1
  8. package/dist/api/notifications/index.d.ts.map +1 -0
  9. package/dist/api/parameters/index.d.ts +455 -8
  10. package/dist/api/parameters/index.d.ts.map +1 -0
  11. package/dist/api/users/index.d.ts +844 -840
  12. package/dist/api/users/index.d.ts.map +1 -0
  13. package/dist/api/verifications/index.d.ts.map +1 -0
  14. package/dist/batch/index.d.ts.map +1 -0
  15. package/dist/bucket/index.d.ts.map +1 -0
  16. package/dist/cache/core/index.d.ts.map +1 -0
  17. package/dist/cache/redis/index.d.ts.map +1 -0
  18. package/dist/cli/index.d.ts +254 -59
  19. package/dist/cli/index.d.ts.map +1 -0
  20. package/dist/cli/index.js +499 -127
  21. package/dist/cli/index.js.map +1 -1
  22. package/dist/command/index.d.ts +217 -10
  23. package/dist/command/index.d.ts.map +1 -0
  24. package/dist/command/index.js +350 -74
  25. package/dist/command/index.js.map +1 -1
  26. package/dist/core/index.browser.js +1334 -1318
  27. package/dist/core/index.browser.js.map +1 -1
  28. package/dist/core/index.d.ts +76 -72
  29. package/dist/core/index.d.ts.map +1 -0
  30. package/dist/core/index.js +1337 -1321
  31. package/dist/core/index.js.map +1 -1
  32. package/dist/core/index.native.js +1337 -1321
  33. package/dist/core/index.native.js.map +1 -1
  34. package/dist/datetime/index.d.ts.map +1 -0
  35. package/dist/email/index.d.ts.map +1 -0
  36. package/dist/fake/index.d.ts.map +1 -0
  37. package/dist/file/index.d.ts.map +1 -0
  38. package/dist/file/index.js.map +1 -1
  39. package/dist/lock/core/index.d.ts.map +1 -0
  40. package/dist/lock/redis/index.d.ts.map +1 -0
  41. package/dist/logger/index.d.ts +1 -0
  42. package/dist/logger/index.d.ts.map +1 -0
  43. package/dist/mcp/index.d.ts +820 -0
  44. package/dist/mcp/index.d.ts.map +1 -0
  45. package/dist/mcp/index.js +978 -0
  46. package/dist/mcp/index.js.map +1 -0
  47. package/dist/orm/index.d.ts +234 -107
  48. package/dist/orm/index.d.ts.map +1 -0
  49. package/dist/orm/index.js +376 -316
  50. package/dist/orm/index.js.map +1 -1
  51. package/dist/queue/core/index.d.ts +4 -4
  52. package/dist/queue/core/index.d.ts.map +1 -0
  53. package/dist/queue/redis/index.d.ts.map +1 -0
  54. package/dist/queue/redis/index.js +2 -4
  55. package/dist/queue/redis/index.js.map +1 -1
  56. package/dist/redis/index.d.ts +400 -29
  57. package/dist/redis/index.d.ts.map +1 -0
  58. package/dist/redis/index.js +412 -21
  59. package/dist/redis/index.js.map +1 -1
  60. package/dist/retry/index.d.ts.map +1 -0
  61. package/dist/router/index.d.ts.map +1 -0
  62. package/dist/scheduler/index.d.ts +6 -6
  63. package/dist/scheduler/index.d.ts.map +1 -0
  64. package/dist/security/index.d.ts +28 -28
  65. package/dist/security/index.d.ts.map +1 -0
  66. package/dist/server/auth/index.d.ts +155 -155
  67. package/dist/server/auth/index.d.ts.map +1 -0
  68. package/dist/server/cache/index.d.ts.map +1 -0
  69. package/dist/server/compress/index.d.ts.map +1 -0
  70. package/dist/server/cookies/index.d.ts.map +1 -0
  71. package/dist/server/core/index.d.ts +0 -1
  72. package/dist/server/core/index.d.ts.map +1 -0
  73. package/dist/server/core/index.js.map +1 -1
  74. package/dist/server/cors/index.d.ts.map +1 -0
  75. package/dist/server/health/index.d.ts +17 -17
  76. package/dist/server/health/index.d.ts.map +1 -0
  77. package/dist/server/helmet/index.d.ts +4 -1
  78. package/dist/server/helmet/index.d.ts.map +1 -0
  79. package/dist/server/links/index.d.ts +33 -33
  80. package/dist/server/links/index.d.ts.map +1 -0
  81. package/dist/server/metrics/index.d.ts.map +1 -0
  82. package/dist/server/multipart/index.d.ts.map +1 -0
  83. package/dist/server/multipart/index.js.map +1 -1
  84. package/dist/server/proxy/index.d.ts.map +1 -0
  85. package/dist/server/proxy/index.js.map +1 -1
  86. package/dist/server/rate-limit/index.d.ts.map +1 -0
  87. package/dist/server/security/index.d.ts +9 -9
  88. package/dist/server/security/index.d.ts.map +1 -0
  89. package/dist/server/static/index.d.ts.map +1 -0
  90. package/dist/server/swagger/index.d.ts.map +1 -0
  91. package/dist/sms/index.d.ts.map +1 -0
  92. package/dist/thread/index.d.ts.map +1 -0
  93. package/dist/topic/core/index.d.ts.map +1 -0
  94. package/dist/topic/redis/index.d.ts.map +1 -0
  95. package/dist/topic/redis/index.js +3 -3
  96. package/dist/topic/redis/index.js.map +1 -1
  97. package/dist/vite/index.d.ts +10 -2
  98. package/dist/vite/index.d.ts.map +1 -0
  99. package/dist/vite/index.js +45 -20
  100. package/dist/vite/index.js.map +1 -1
  101. package/dist/websocket/index.d.ts.map +1 -0
  102. package/package.json +9 -4
  103. package/src/cli/apps/AlephaCli.ts +10 -3
  104. package/src/cli/apps/AlephaPackageBuilderCli.ts +15 -8
  105. package/src/cli/assets/mainTs.ts +9 -10
  106. package/src/cli/atoms/changelogOptions.ts +45 -0
  107. package/src/cli/commands/ChangelogCommands.ts +259 -0
  108. package/src/cli/commands/DeployCommands.ts +118 -0
  109. package/src/cli/commands/DrizzleCommands.ts +230 -10
  110. package/src/cli/commands/ViteCommands.ts +47 -23
  111. package/src/cli/defineConfig.ts +15 -0
  112. package/src/cli/index.ts +3 -0
  113. package/src/cli/services/AlephaCliUtils.ts +10 -154
  114. package/src/cli/services/GitMessageParser.ts +77 -0
  115. package/src/command/helpers/EnvUtils.ts +37 -0
  116. package/src/command/index.ts +3 -1
  117. package/src/command/primitives/$command.ts +172 -6
  118. package/src/command/providers/CliProvider.ts +499 -95
  119. package/src/core/Alepha.ts +1 -1
  120. package/src/core/providers/SchemaValidator.ts +23 -1
  121. package/src/file/providers/NodeFileSystemProvider.ts +3 -1
  122. package/src/mcp/errors/McpError.ts +72 -0
  123. package/src/mcp/helpers/jsonrpc.ts +163 -0
  124. package/src/mcp/index.ts +132 -0
  125. package/src/mcp/interfaces/McpTypes.ts +248 -0
  126. package/src/mcp/primitives/$prompt.ts +188 -0
  127. package/src/mcp/primitives/$resource.ts +171 -0
  128. package/src/mcp/primitives/$tool.ts +285 -0
  129. package/src/mcp/providers/McpServerProvider.ts +382 -0
  130. package/src/mcp/transports/SseMcpTransport.ts +172 -0
  131. package/src/mcp/transports/StdioMcpTransport.ts +126 -0
  132. package/src/orm/index.ts +20 -4
  133. package/src/orm/interfaces/PgQueryWhere.ts +1 -26
  134. package/src/orm/providers/drivers/BunPostgresProvider.ts +225 -0
  135. package/src/orm/providers/drivers/BunSqliteProvider.ts +180 -0
  136. package/src/orm/providers/drivers/CloudflareD1Provider.ts +164 -0
  137. package/src/orm/providers/drivers/DatabaseProvider.ts +25 -0
  138. package/src/orm/providers/drivers/NodePostgresProvider.ts +0 -25
  139. package/src/orm/providers/drivers/NodeSqliteProvider.ts +3 -1
  140. package/src/orm/services/QueryManager.ts +10 -125
  141. package/src/queue/redis/providers/RedisQueueProvider.ts +2 -7
  142. package/src/redis/index.ts +65 -3
  143. package/src/redis/providers/BunRedisProvider.ts +304 -0
  144. package/src/redis/providers/BunRedisSubscriberProvider.ts +94 -0
  145. package/src/redis/providers/NodeRedisProvider.ts +280 -0
  146. package/src/redis/providers/NodeRedisSubscriberProvider.ts +94 -0
  147. package/src/redis/providers/RedisProvider.ts +134 -140
  148. package/src/redis/providers/RedisSubscriberProvider.ts +58 -49
  149. package/src/server/core/providers/BunHttpServerProvider.ts +0 -3
  150. package/src/server/core/providers/ServerBodyParserProvider.ts +3 -1
  151. package/src/server/core/providers/ServerProvider.ts +7 -4
  152. package/src/server/multipart/providers/ServerMultipartProvider.ts +3 -1
  153. package/src/server/proxy/providers/ServerProxyProvider.ts +1 -1
  154. package/src/topic/redis/providers/RedisTopicProvider.ts +3 -3
  155. package/src/vite/plugins/viteAlephaBuild.ts +8 -2
  156. package/src/vite/plugins/viteAlephaDev.ts +6 -2
  157. package/src/vite/tasks/buildServer.ts +2 -1
  158. package/src/vite/tasks/generateCloudflare.ts +43 -15
  159. package/src/vite/tasks/runAlepha.ts +1 -0
  160. package/src/orm/services/PgJsonQueryManager.ts +0 -511
@@ -0,0 +1,978 @@
1
+ import { $env, $hook, $inject, $module, Alepha, AlephaError, KIND, Primitive, createPrimitive, t } from "alepha";
2
+ import { $logger } from "alepha/logger";
3
+ import { $route } from "alepha/server";
4
+ import * as readline from "node:readline";
5
+
6
+ //#region ../../src/mcp/helpers/jsonrpc.ts
7
+ const JSONRPC_VERSION = "2.0";
8
+ const MCP_PROTOCOL_VERSION = "2024-11-05";
9
+ const JsonRpcErrorCodes = {
10
+ PARSE_ERROR: -32700,
11
+ INVALID_REQUEST: -32600,
12
+ METHOD_NOT_FOUND: -32601,
13
+ INVALID_PARAMS: -32602,
14
+ INTERNAL_ERROR: -32603
15
+ };
16
+ function createResponse(id, result) {
17
+ return {
18
+ jsonrpc: JSONRPC_VERSION,
19
+ id,
20
+ result
21
+ };
22
+ }
23
+ function createErrorResponse(id, error) {
24
+ return {
25
+ jsonrpc: JSONRPC_VERSION,
26
+ id,
27
+ error
28
+ };
29
+ }
30
+ function createNotification(method, params) {
31
+ return {
32
+ jsonrpc: JSONRPC_VERSION,
33
+ method,
34
+ params
35
+ };
36
+ }
37
+ function createParseError(message = "Parse error") {
38
+ return {
39
+ code: JsonRpcErrorCodes.PARSE_ERROR,
40
+ message
41
+ };
42
+ }
43
+ function createInvalidRequestError(message = "Invalid request") {
44
+ return {
45
+ code: JsonRpcErrorCodes.INVALID_REQUEST,
46
+ message
47
+ };
48
+ }
49
+ function createMethodNotFoundError(method) {
50
+ return {
51
+ code: JsonRpcErrorCodes.METHOD_NOT_FOUND,
52
+ message: `Method not found: ${method}`
53
+ };
54
+ }
55
+ function createInvalidParamsError(message) {
56
+ return {
57
+ code: JsonRpcErrorCodes.INVALID_PARAMS,
58
+ message
59
+ };
60
+ }
61
+ function createInternalError(message) {
62
+ return {
63
+ code: JsonRpcErrorCodes.INTERNAL_ERROR,
64
+ message
65
+ };
66
+ }
67
+ function parseMessage(data) {
68
+ let parsed;
69
+ try {
70
+ parsed = JSON.parse(data);
71
+ } catch {
72
+ throw new JsonRpcParseError("Invalid JSON");
73
+ }
74
+ if (!isValidJsonRpcRequest(parsed)) throw new JsonRpcParseError("Invalid JSON-RPC request");
75
+ return parsed;
76
+ }
77
+ function isValidJsonRpcRequest(value) {
78
+ if (typeof value !== "object" || value === null) return false;
79
+ const obj = value;
80
+ if (obj.jsonrpc !== JSONRPC_VERSION) return false;
81
+ if (typeof obj.method !== "string") return false;
82
+ if (obj.id !== void 0 && typeof obj.id !== "string" && typeof obj.id !== "number") return false;
83
+ if (obj.params !== void 0 && typeof obj.params !== "object") return false;
84
+ return true;
85
+ }
86
+ function isNotification(request) {
87
+ return request.id === void 0;
88
+ }
89
+ var JsonRpcParseError = class extends AlephaError {
90
+ name = "JsonRpcParseError";
91
+ };
92
+
93
+ //#endregion
94
+ //#region ../../src/mcp/errors/McpError.ts
95
+ var McpError = class extends Error {
96
+ name = "McpError";
97
+ code;
98
+ constructor(message, code = JsonRpcErrorCodes.INTERNAL_ERROR) {
99
+ super(message);
100
+ this.code = code;
101
+ }
102
+ };
103
+ var McpMethodNotFoundError = class extends McpError {
104
+ name = "McpMethodNotFoundError";
105
+ constructor(method) {
106
+ super(`Method not found: ${method}`, JsonRpcErrorCodes.METHOD_NOT_FOUND);
107
+ }
108
+ };
109
+ var McpToolNotFoundError = class extends McpError {
110
+ name = "McpToolNotFoundError";
111
+ tool;
112
+ constructor(tool) {
113
+ super(`Tool not found: ${tool}`, JsonRpcErrorCodes.METHOD_NOT_FOUND);
114
+ this.tool = tool;
115
+ }
116
+ };
117
+ var McpResourceNotFoundError = class extends McpError {
118
+ name = "McpResourceNotFoundError";
119
+ uri;
120
+ constructor(uri) {
121
+ super(`Resource not found: ${uri}`, JsonRpcErrorCodes.METHOD_NOT_FOUND);
122
+ this.uri = uri;
123
+ }
124
+ };
125
+ var McpPromptNotFoundError = class extends McpError {
126
+ name = "McpPromptNotFoundError";
127
+ prompt;
128
+ constructor(prompt) {
129
+ super(`Prompt not found: ${prompt}`, JsonRpcErrorCodes.METHOD_NOT_FOUND);
130
+ this.prompt = prompt;
131
+ }
132
+ };
133
+ var McpInvalidParamsError = class extends McpError {
134
+ name = "McpInvalidParamsError";
135
+ constructor(message) {
136
+ super(message, JsonRpcErrorCodes.INVALID_PARAMS);
137
+ }
138
+ };
139
+
140
+ //#endregion
141
+ //#region ../../src/mcp/providers/McpServerProvider.ts
142
+ /**
143
+ * Core MCP server provider that handles protocol messages.
144
+ *
145
+ * This provider maintains registries of tools, resources, and prompts,
146
+ * and routes incoming JSON-RPC requests to the appropriate handlers.
147
+ *
148
+ * It is transport-agnostic - actual communication is handled by
149
+ * transport providers like StdioMcpTransport or SseMcpTransport.
150
+ */
151
+ var McpServerProvider = class {
152
+ log = $logger();
153
+ alepha = $inject(Alepha);
154
+ tools = /* @__PURE__ */ new Map();
155
+ resources = /* @__PURE__ */ new Map();
156
+ prompts = /* @__PURE__ */ new Map();
157
+ initialized = false;
158
+ serverInfo = {
159
+ name: "alepha-mcp",
160
+ version: "1.0.0"
161
+ };
162
+ /**
163
+ * Register a tool with the MCP server.
164
+ */
165
+ registerTool(tool) {
166
+ this.log.trace(`Registering MCP tool: ${tool.name}`);
167
+ this.tools.set(tool.name, tool);
168
+ }
169
+ /**
170
+ * Register a resource with the MCP server.
171
+ */
172
+ registerResource(resource) {
173
+ this.log.trace(`Registering MCP resource: ${resource.uri}`);
174
+ this.resources.set(resource.uri, resource);
175
+ }
176
+ /**
177
+ * Register a prompt with the MCP server.
178
+ */
179
+ registerPrompt(prompt) {
180
+ this.log.trace(`Registering MCP prompt: ${prompt.name}`);
181
+ this.prompts.set(prompt.name, prompt);
182
+ }
183
+ /**
184
+ * Get the server capabilities based on registered primitives.
185
+ */
186
+ getCapabilities() {
187
+ return {
188
+ tools: this.tools.size > 0 ? {} : void 0,
189
+ resources: this.resources.size > 0 ? {} : void 0,
190
+ prompts: this.prompts.size > 0 ? {} : void 0
191
+ };
192
+ }
193
+ /**
194
+ * Get all registered tools.
195
+ */
196
+ getTools() {
197
+ return Array.from(this.tools.values());
198
+ }
199
+ /**
200
+ * Get all registered resources.
201
+ */
202
+ getResources() {
203
+ return Array.from(this.resources.values());
204
+ }
205
+ /**
206
+ * Get all registered prompts.
207
+ */
208
+ getPrompts() {
209
+ return Array.from(this.prompts.values());
210
+ }
211
+ /**
212
+ * Get a tool by name.
213
+ */
214
+ getTool(name) {
215
+ return this.tools.get(name);
216
+ }
217
+ /**
218
+ * Get a resource by URI.
219
+ */
220
+ getResource(uri) {
221
+ return this.resources.get(uri);
222
+ }
223
+ /**
224
+ * Get a prompt by name.
225
+ */
226
+ getPrompt(name) {
227
+ return this.prompts.get(name);
228
+ }
229
+ /**
230
+ * Handle an incoming JSON-RPC request.
231
+ *
232
+ * @param request - The parsed JSON-RPC request
233
+ * @param context - Optional context from the transport layer (headers, auth, etc.)
234
+ * @returns The JSON-RPC response, or null for notifications
235
+ */
236
+ async handleMessage(request, context) {
237
+ const id = request.id;
238
+ if (id === void 0) {
239
+ await this.handleNotification(request);
240
+ return null;
241
+ }
242
+ try {
243
+ return createResponse(id, await this.handleRequest(request, context));
244
+ } catch (error) {
245
+ this.log.error("MCP request failed", error);
246
+ if (error instanceof McpError) return createErrorResponse(id, {
247
+ code: error.code,
248
+ message: error.message
249
+ });
250
+ return createErrorResponse(id, createInternalError(error.message));
251
+ }
252
+ }
253
+ /**
254
+ * Handle a JSON-RPC request that expects a response.
255
+ */
256
+ async handleRequest(request, context) {
257
+ const { method, params = {} } = request;
258
+ switch (method) {
259
+ case "initialize": return this.handleInitialize(params);
260
+ case "ping": return this.handlePing();
261
+ case "tools/list": return this.handleToolsList();
262
+ case "tools/call": return this.handleToolsCall(params, context);
263
+ case "resources/list": return this.handleResourcesList();
264
+ case "resources/read": return this.handleResourcesRead(params, context);
265
+ case "prompts/list": return this.handlePromptsList();
266
+ case "prompts/get": return this.handlePromptsGet(params, context);
267
+ default: throw new McpMethodNotFoundError(method);
268
+ }
269
+ }
270
+ /**
271
+ * Handle a notification (no response expected).
272
+ */
273
+ async handleNotification(request) {
274
+ const { method } = request;
275
+ switch (method) {
276
+ case "notifications/initialized":
277
+ this.log.debug("MCP client initialized");
278
+ break;
279
+ case "notifications/cancelled":
280
+ this.log.debug("MCP request cancelled", request.params);
281
+ break;
282
+ default: this.log.debug(`Unknown MCP notification: ${method}`);
283
+ }
284
+ }
285
+ handleInitialize(params) {
286
+ this.log.info("MCP client initializing", {
287
+ clientInfo: params.clientInfo,
288
+ protocolVersion: params.protocolVersion
289
+ });
290
+ this.initialized = true;
291
+ return {
292
+ protocolVersion: MCP_PROTOCOL_VERSION,
293
+ capabilities: this.getCapabilities(),
294
+ serverInfo: this.serverInfo
295
+ };
296
+ }
297
+ handlePing() {
298
+ return {};
299
+ }
300
+ handleToolsList() {
301
+ return { tools: Array.from(this.tools.values()).map((t$1) => t$1.toDescriptor()) };
302
+ }
303
+ async handleToolsCall(params, context) {
304
+ const name = params.name;
305
+ const args = params.arguments ?? {};
306
+ const tool = this.tools.get(name);
307
+ if (!tool) throw new McpToolNotFoundError(name);
308
+ try {
309
+ const result = await tool.execute(args, context);
310
+ return { content: [{
311
+ type: "text",
312
+ text: typeof result === "string" ? result : JSON.stringify(result ?? null)
313
+ }] };
314
+ } catch (error) {
315
+ return {
316
+ content: [{
317
+ type: "text",
318
+ text: `Error: ${error.message}`
319
+ }],
320
+ isError: true
321
+ };
322
+ }
323
+ }
324
+ handleResourcesList() {
325
+ return { resources: Array.from(this.resources.values()).map((r) => r.toDescriptor()) };
326
+ }
327
+ async handleResourcesRead(params, context) {
328
+ const uri = params.uri;
329
+ const resource = this.resources.get(uri);
330
+ if (!resource) throw new McpResourceNotFoundError(uri);
331
+ const content = await resource.read(context);
332
+ const resourceContent = {
333
+ uri,
334
+ mimeType: resource.mimeType
335
+ };
336
+ if (content.text !== void 0) resourceContent.text = content.text;
337
+ if (content.blob !== void 0) resourceContent.blob = Buffer.from(content.blob).toString("base64");
338
+ return { contents: [resourceContent] };
339
+ }
340
+ handlePromptsList() {
341
+ return { prompts: Array.from(this.prompts.values()).map((p) => p.toDescriptor()) };
342
+ }
343
+ async handlePromptsGet(params, context) {
344
+ const name = params.name;
345
+ const args = params.arguments ?? {};
346
+ const prompt = this.prompts.get(name);
347
+ if (!prompt) throw new McpPromptNotFoundError(name);
348
+ const mcpMessages = (await prompt.get(args, context)).map((msg) => ({
349
+ role: msg.role,
350
+ content: {
351
+ type: "text",
352
+ text: msg.content
353
+ }
354
+ }));
355
+ return {
356
+ description: prompt.description,
357
+ messages: mcpMessages
358
+ };
359
+ }
360
+ };
361
+
362
+ //#endregion
363
+ //#region ../../src/mcp/primitives/$prompt.ts
364
+ /**
365
+ * Creates an MCP prompt primitive for defining reusable prompt templates.
366
+ *
367
+ * Prompts allow you to define templated messages that can be filled in
368
+ * with arguments at runtime. They're useful for creating consistent
369
+ * interaction patterns.
370
+ *
371
+ * @example
372
+ * ```ts
373
+ * class Prompts {
374
+ * greeting = $prompt({
375
+ * description: "Generate a personalized greeting",
376
+ * args: t.object({
377
+ * name: t.text({ description: "Name of the person to greet" }),
378
+ * style: t.optional(t.enum(["formal", "casual"])),
379
+ * }),
380
+ * handler: async ({ args }) => [
381
+ * {
382
+ * role: "user",
383
+ * content: args.style === "formal"
384
+ * ? `Please greet ${args.name} in a formal manner.`
385
+ * : `Say hi to ${args.name}!`,
386
+ * },
387
+ * ],
388
+ * });
389
+ *
390
+ * codeReview = $prompt({
391
+ * description: "Request a code review",
392
+ * args: t.object({
393
+ * code: t.text({ description: "The code to review" }),
394
+ * language: t.text({ description: "Programming language" }),
395
+ * }),
396
+ * handler: async ({ args }) => [
397
+ * {
398
+ * role: "user",
399
+ * content: `Please review this ${args.language} code:\n\n${args.code}`,
400
+ * },
401
+ * ],
402
+ * });
403
+ * }
404
+ * ```
405
+ */
406
+ const $prompt = (options) => {
407
+ return createPrimitive(PromptPrimitive, options);
408
+ };
409
+ var PromptPrimitive = class extends Primitive {
410
+ mcpServer = $inject(McpServerProvider);
411
+ /**
412
+ * Returns the name of the prompt.
413
+ */
414
+ get name() {
415
+ return this.options.name ?? this.config.propertyKey;
416
+ }
417
+ /**
418
+ * Returns the description of the prompt.
419
+ */
420
+ get description() {
421
+ return this.options.description;
422
+ }
423
+ onInit() {
424
+ this.mcpServer.registerPrompt(this);
425
+ }
426
+ /**
427
+ * Get the prompt messages with the given arguments.
428
+ *
429
+ * @param rawArgs - Raw arguments to validate and pass to the handler
430
+ * @param context - Optional context from the transport layer
431
+ * @returns Array of prompt messages
432
+ */
433
+ async get(rawArgs, context) {
434
+ let args = rawArgs ?? {};
435
+ if (this.options.args) args = this.alepha.codec.decode(this.options.args, rawArgs ?? {});
436
+ return this.options.handler({
437
+ args,
438
+ context
439
+ });
440
+ }
441
+ /**
442
+ * Convert the prompt to an MCP prompt descriptor for protocol messages.
443
+ */
444
+ toDescriptor() {
445
+ return {
446
+ name: this.name,
447
+ description: this.description,
448
+ arguments: this.options.args ? this.schemaToArguments(this.options.args) : []
449
+ };
450
+ }
451
+ /**
452
+ * Convert a TypeBox schema to an array of prompt arguments.
453
+ */
454
+ schemaToArguments(schema) {
455
+ const args = [];
456
+ for (const [name, propSchema] of Object.entries(schema.properties)) {
457
+ const prop = propSchema;
458
+ args.push({
459
+ name,
460
+ description: prop.description,
461
+ required: !t.schema.isOptional(propSchema)
462
+ });
463
+ }
464
+ return args;
465
+ }
466
+ };
467
+ $prompt[KIND] = PromptPrimitive;
468
+
469
+ //#endregion
470
+ //#region ../../src/mcp/primitives/$resource.ts
471
+ /**
472
+ * Creates an MCP resource primitive for exposing read-only data.
473
+ *
474
+ * Resources represent any kind of data that an LLM might want to read,
475
+ * such as files, database records, API responses, or computed data.
476
+ *
477
+ * **Key Features**
478
+ * - URI-based identification for resources
479
+ * - Support for text and binary content
480
+ * - MIME type specification
481
+ * - Lazy loading via handler function
482
+ *
483
+ * @example
484
+ * ```ts
485
+ * class ProjectResources {
486
+ * readme = $resource({
487
+ * uri: "file:///readme",
488
+ * description: "Project README file",
489
+ * mimeType: "text/markdown",
490
+ * handler: async () => ({
491
+ * text: await fs.readFile("README.md", "utf-8"),
492
+ * }),
493
+ * });
494
+ *
495
+ * config = $resource({
496
+ * uri: "config://app",
497
+ * name: "Application Configuration",
498
+ * mimeType: "application/json",
499
+ * handler: async () => ({
500
+ * text: JSON.stringify(this.configService.getConfig()),
501
+ * }),
502
+ * });
503
+ * }
504
+ * ```
505
+ */
506
+ const $resource = (options) => {
507
+ return createPrimitive(ResourcePrimitive, options);
508
+ };
509
+ var ResourcePrimitive = class extends Primitive {
510
+ mcpServer = $inject(McpServerProvider);
511
+ /**
512
+ * Returns the name of the resource.
513
+ */
514
+ get name() {
515
+ return this.options.name ?? this.config.propertyKey;
516
+ }
517
+ /**
518
+ * Returns the URI of the resource.
519
+ */
520
+ get uri() {
521
+ return this.options.uri;
522
+ }
523
+ /**
524
+ * Returns the description of the resource.
525
+ */
526
+ get description() {
527
+ return this.options.description;
528
+ }
529
+ /**
530
+ * Returns the MIME type of the resource.
531
+ */
532
+ get mimeType() {
533
+ return this.options.mimeType ?? "text/plain";
534
+ }
535
+ onInit() {
536
+ this.mcpServer.registerResource(this);
537
+ }
538
+ /**
539
+ * Read the resource content.
540
+ *
541
+ * @param context - Optional context from the transport layer
542
+ * @returns The resource content
543
+ */
544
+ async read(context) {
545
+ return this.options.handler({ context });
546
+ }
547
+ /**
548
+ * Convert the resource to an MCP resource descriptor for protocol messages.
549
+ */
550
+ toDescriptor() {
551
+ return {
552
+ uri: this.uri,
553
+ name: this.name,
554
+ description: this.description,
555
+ mimeType: this.mimeType
556
+ };
557
+ }
558
+ };
559
+ $resource[KIND] = ResourcePrimitive;
560
+
561
+ //#endregion
562
+ //#region ../../src/mcp/primitives/$tool.ts
563
+ /**
564
+ * Creates an MCP tool primitive for defining callable functions.
565
+ *
566
+ * Tools are the primary way for LLMs to interact with external systems through MCP.
567
+ * Each tool has a name, description, typed parameters, and a handler function.
568
+ *
569
+ * **Key Features**
570
+ * - Full TypeScript inference for parameters and results
571
+ * - Automatic schema validation using TypeBox
572
+ * - JSON Schema generation for MCP protocol
573
+ * - Integration with MCP server provider
574
+ *
575
+ * @example
576
+ * ```ts
577
+ * class CalculatorTools {
578
+ * add = $tool({
579
+ * description: "Add two numbers together",
580
+ * schema: {
581
+ * params: t.object({
582
+ * a: t.number(),
583
+ * b: t.number(),
584
+ * }),
585
+ * result: t.number(),
586
+ * },
587
+ * handler: async ({ params }) => {
588
+ * return params.a + params.b;
589
+ * },
590
+ * });
591
+ *
592
+ * greet = $tool({
593
+ * description: "Generate a greeting message",
594
+ * schema: {
595
+ * params: t.object({
596
+ * name: t.text(),
597
+ * }),
598
+ * result: t.text(),
599
+ * },
600
+ * handler: async ({ params }) => {
601
+ * return `Hello, ${params.name}!`;
602
+ * },
603
+ * });
604
+ * }
605
+ * ```
606
+ */
607
+ const $tool = (options) => {
608
+ return createPrimitive(ToolPrimitive, options);
609
+ };
610
+ var ToolPrimitive = class extends Primitive {
611
+ mcpServer = $inject(McpServerProvider);
612
+ /**
613
+ * Returns the name of the tool.
614
+ */
615
+ get name() {
616
+ return this.options.name ?? this.config.propertyKey;
617
+ }
618
+ /**
619
+ * Returns the description of the tool.
620
+ */
621
+ get description() {
622
+ return this.options.description;
623
+ }
624
+ onInit() {
625
+ this.mcpServer.registerTool(this);
626
+ }
627
+ /**
628
+ * Execute the tool with the given parameters.
629
+ *
630
+ * @param params - Raw parameters to validate and pass to the handler
631
+ * @param context - Optional context from the transport layer
632
+ * @returns The tool result
633
+ */
634
+ async execute(params, context) {
635
+ let validatedParams = params ?? {};
636
+ if (this.options.schema?.params) validatedParams = this.alepha.codec.decode(this.options.schema.params, validatedParams);
637
+ const result = await this.options.handler({
638
+ params: validatedParams,
639
+ context
640
+ });
641
+ if (this.options.schema?.result && result !== void 0) return this.alepha.codec.encode(this.options.schema.result, result);
642
+ return result;
643
+ }
644
+ /**
645
+ * Convert the tool to an MCP tool descriptor for protocol messages.
646
+ */
647
+ toDescriptor() {
648
+ return {
649
+ name: this.name,
650
+ description: this.description,
651
+ inputSchema: this.options.schema?.params ? this.schemaToJsonSchema(this.options.schema.params) : {
652
+ type: "object",
653
+ properties: {},
654
+ required: []
655
+ }
656
+ };
657
+ }
658
+ /**
659
+ * Convert a TypeBox schema to JSON Schema format.
660
+ */
661
+ schemaToJsonSchema(schema) {
662
+ const properties = {};
663
+ const required = [];
664
+ for (const [key, propSchema] of Object.entries(schema.properties)) {
665
+ properties[key] = this.propertyToJsonSchema(propSchema);
666
+ if (!t.schema.isOptional(propSchema)) required.push(key);
667
+ }
668
+ return {
669
+ type: "object",
670
+ properties,
671
+ required
672
+ };
673
+ }
674
+ /**
675
+ * Convert a single property schema to JSON Schema format.
676
+ */
677
+ propertyToJsonSchema(schema) {
678
+ const result = {};
679
+ if ("description" in schema) result.description = schema.description;
680
+ if (t.schema.isString(schema)) {
681
+ result.type = "string";
682
+ if ("minLength" in schema) result.minLength = schema.minLength;
683
+ if ("maxLength" in schema) result.maxLength = schema.maxLength;
684
+ if ("pattern" in schema) result.pattern = schema.pattern;
685
+ if ("enum" in schema) result.enum = schema.enum;
686
+ } else if (t.schema.isNumber(schema)) {
687
+ result.type = "number";
688
+ if ("minimum" in schema) result.minimum = schema.minimum;
689
+ if ("maximum" in schema) result.maximum = schema.maximum;
690
+ } else if (t.schema.isInteger(schema)) {
691
+ result.type = "integer";
692
+ if ("minimum" in schema) result.minimum = schema.minimum;
693
+ if ("maximum" in schema) result.maximum = schema.maximum;
694
+ } else if (t.schema.isBoolean(schema)) result.type = "boolean";
695
+ else if (t.schema.isArray(schema)) {
696
+ result.type = "array";
697
+ if ("items" in schema) result.items = this.propertyToJsonSchema(schema.items);
698
+ } else if (t.schema.isObject(schema)) Object.assign(result, this.schemaToJsonSchema(schema));
699
+ else if (t.schema.isUnsafe(schema) || t.schema.isOptional(schema)) {
700
+ const schemaAny = schema;
701
+ if (schemaAny.type === "string") {
702
+ result.type = "string";
703
+ if ("enum" in schema) result.enum = schema.enum;
704
+ if ("pattern" in schema) result.pattern = schema.pattern;
705
+ } else if (schemaAny.type === "number") result.type = "number";
706
+ else if (schemaAny.type === "integer") result.type = "integer";
707
+ else if (schemaAny.type === "boolean") result.type = "boolean";
708
+ else if (schemaAny.type === "array") result.type = "array";
709
+ else if (schemaAny.type === "object") result.type = "object";
710
+ else result.type = "string";
711
+ } else result.type = "string";
712
+ return result;
713
+ }
714
+ };
715
+ $tool[KIND] = ToolPrimitive;
716
+
717
+ //#endregion
718
+ //#region ../../src/mcp/transports/SseMcpTransport.ts
719
+ const envSchema = t.object({ MCP_SSE_PATH: t.text({
720
+ description: "Path for MCP SSE endpoint",
721
+ default: "/mcp"
722
+ }) });
723
+ /**
724
+ * SSE (Server-Sent Events) transport for MCP communication.
725
+ *
726
+ * This transport uses HTTP with SSE for server-to-client messages
727
+ * and POST requests for client-to-server messages.
728
+ *
729
+ * Endpoints:
730
+ * - GET /mcp - SSE stream for server events
731
+ * - POST /mcp - JSON-RPC request endpoint
732
+ *
733
+ * @example
734
+ * ```ts
735
+ * import { Alepha, run } from "alepha";
736
+ * import { AlephaServer } from "alepha/server";
737
+ * import { AlephaMcp, AlephaMcpSse } from "alepha/mcp";
738
+ *
739
+ * class MyTools {
740
+ * // ... tool definitions
741
+ * }
742
+ *
743
+ * run(
744
+ * Alepha.create()
745
+ * .with(AlephaServer)
746
+ * .with(AlephaMcp)
747
+ * .with(AlephaMcpSse)
748
+ * .with(MyTools)
749
+ * );
750
+ * ```
751
+ */
752
+ var SseMcpTransport = class {
753
+ log = $logger();
754
+ env = $env(envSchema);
755
+ mcpServer = $inject(McpServerProvider);
756
+ /**
757
+ * SSE endpoint for server-to-client messages.
758
+ *
759
+ * Returns a text/event-stream response with server capabilities
760
+ * and keeps the connection open for notifications.
761
+ */
762
+ sse = $route({
763
+ method: "GET",
764
+ path: this.env.MCP_SSE_PATH,
765
+ handler: async (request) => {
766
+ this.log.debug("MCP SSE connection established");
767
+ const encoder = new TextEncoder();
768
+ const stream = new ReadableStream({
769
+ start: (controller) => {
770
+ const endpointEvent = this.formatSseEvent("endpoint", `${this.env.MCP_SSE_PATH}`);
771
+ controller.enqueue(encoder.encode(endpointEvent));
772
+ const capabilitiesNotification = createNotification("notifications/capabilities", { capabilities: this.mcpServer.getCapabilities() });
773
+ const capabilitiesEvent = this.formatSseEvent("message", JSON.stringify(capabilitiesNotification));
774
+ controller.enqueue(encoder.encode(capabilitiesEvent));
775
+ },
776
+ cancel: () => {
777
+ this.log.debug("MCP SSE connection closed");
778
+ }
779
+ });
780
+ request.reply.status = 200;
781
+ request.reply.headers = {
782
+ "content-type": "text/event-stream",
783
+ "cache-control": "no-cache",
784
+ connection: "keep-alive"
785
+ };
786
+ request.reply.body = stream;
787
+ }
788
+ });
789
+ /**
790
+ * POST endpoint for client-to-server JSON-RPC messages.
791
+ */
792
+ message = $route({
793
+ method: "POST",
794
+ path: this.env.MCP_SSE_PATH,
795
+ secure: false,
796
+ schema: { body: t.json() },
797
+ handler: async (request) => {
798
+ try {
799
+ const body = typeof request.body === "string" ? request.body : JSON.stringify(request.body);
800
+ this.log.debug("MCP request body", {
801
+ body,
802
+ bodyType: typeof request.body
803
+ });
804
+ const rpcRequest = parseMessage(body);
805
+ const context = { headers: request.headers };
806
+ const response = await this.mcpServer.handleMessage(rpcRequest, context);
807
+ request.reply.headers["content-type"] = "application/json";
808
+ request.reply.body = response ? JSON.stringify(response) : "";
809
+ } catch (error) {
810
+ if (error instanceof JsonRpcParseError) {
811
+ request.reply.status = 400;
812
+ request.reply.headers["content-type"] = "application/json";
813
+ request.reply.body = JSON.stringify(createErrorResponse(0, createParseError(error.message)));
814
+ } else {
815
+ this.log.error("Failed to process MCP message", error);
816
+ request.reply.status = 500;
817
+ request.reply.body = JSON.stringify({ error: error.message });
818
+ }
819
+ }
820
+ }
821
+ });
822
+ /**
823
+ * Format a message as an SSE event.
824
+ */
825
+ formatSseEvent(event, data) {
826
+ return `event: ${event}\ndata: ${data}\n\n`;
827
+ }
828
+ };
829
+
830
+ //#endregion
831
+ //#region ../../src/mcp/transports/StdioMcpTransport.ts
832
+ /**
833
+ * Stdio transport for MCP communication.
834
+ *
835
+ * This transport uses stdin/stdout for JSON-RPC message exchange,
836
+ * which is the standard transport for local MCP servers.
837
+ *
838
+ * Messages are newline-delimited JSON objects.
839
+ *
840
+ * @example
841
+ * ```ts
842
+ * import { Alepha, run } from "alepha";
843
+ * import { AlephaMcp, AlephaMcpStdio } from "alepha/mcp";
844
+ *
845
+ * class MyTools {
846
+ * // ... tool definitions
847
+ * }
848
+ *
849
+ * run(
850
+ * Alepha.create()
851
+ * .with(AlephaMcp)
852
+ * .with(AlephaMcpStdio)
853
+ * .with(MyTools)
854
+ * );
855
+ * ```
856
+ */
857
+ var StdioMcpTransport = class {
858
+ log = $logger();
859
+ mcpServer = $inject(McpServerProvider);
860
+ rl;
861
+ started = false;
862
+ onStart = $hook({
863
+ on: "start",
864
+ handler: () => this.start()
865
+ });
866
+ onStop = $hook({
867
+ on: "stop",
868
+ handler: () => this.stop()
869
+ });
870
+ /**
871
+ * Start the stdio transport.
872
+ */
873
+ start() {
874
+ if (this.started) return;
875
+ this.started = true;
876
+ this.rl = readline.createInterface({
877
+ input: process.stdin,
878
+ output: process.stdout,
879
+ terminal: false
880
+ });
881
+ this.rl.on("line", (line) => this.handleLine(line));
882
+ this.rl.on("close", () => this.handleClose());
883
+ this.log.info("MCP stdio transport started");
884
+ }
885
+ /**
886
+ * Stop the stdio transport.
887
+ */
888
+ stop() {
889
+ if (!this.started) return;
890
+ this.started = false;
891
+ this.rl?.close();
892
+ this.rl = void 0;
893
+ this.log.info("MCP stdio transport stopped");
894
+ }
895
+ /**
896
+ * Handle an incoming line from stdin.
897
+ */
898
+ async handleLine(line) {
899
+ if (!line.trim()) return;
900
+ try {
901
+ const request = parseMessage(line);
902
+ const response = await this.mcpServer.handleMessage(request);
903
+ if (response) this.send(response);
904
+ } catch (error) {
905
+ if (error instanceof JsonRpcParseError) this.send(createErrorResponse(0, createParseError(error.message)));
906
+ else this.log.error("Failed to process MCP message", error);
907
+ }
908
+ }
909
+ /**
910
+ * Handle stdin close event.
911
+ */
912
+ handleClose() {
913
+ this.log.debug("MCP stdio input closed");
914
+ }
915
+ /**
916
+ * Send a message to stdout.
917
+ */
918
+ send(message) {
919
+ const json = JSON.stringify(message);
920
+ process.stdout.write(json + "\n");
921
+ }
922
+ };
923
+
924
+ //#endregion
925
+ //#region ../../src/mcp/index.ts
926
+ /**
927
+ * Core MCP module with primitives and server provider.
928
+ *
929
+ * This module registers the $tool, $resource, and $prompt primitives
930
+ * and the McpServerProvider. You need to add a transport module
931
+ * (AlephaMcpStdio or AlephaMcpSse) for actual communication.
932
+ *
933
+ * @example
934
+ * ```ts
935
+ * import { Alepha, run } from "alepha";
936
+ * import { AlephaMcp, AlephaMcpStdio, $tool, t } from "alepha/mcp";
937
+ *
938
+ * class MyMcpServer {
939
+ * add = $tool({
940
+ * description: "Add two numbers",
941
+ * schema: {
942
+ * params: t.object({ a: t.number(), b: t.number() }),
943
+ * result: t.number(),
944
+ * },
945
+ * handler: async ({ params }) => params.a + params.b,
946
+ * });
947
+ * }
948
+ *
949
+ * run(
950
+ * Alepha.create()
951
+ * .with(AlephaMcp)
952
+ * .with(AlephaMcpStdio)
953
+ * .with(MyMcpServer)
954
+ * );
955
+ * ```
956
+ *
957
+ * @module alepha.mcp
958
+ */
959
+ const AlephaMcp = $module({
960
+ name: "alepha.mcp",
961
+ primitives: [
962
+ $tool,
963
+ $resource,
964
+ $prompt
965
+ ],
966
+ services: [
967
+ McpServerProvider,
968
+ SseMcpTransport,
969
+ StdioMcpTransport
970
+ ],
971
+ register: (alepha) => {
972
+ alepha.with(McpServerProvider);
973
+ }
974
+ });
975
+
976
+ //#endregion
977
+ export { $prompt, $resource, $tool, AlephaMcp, JSONRPC_VERSION, JsonRpcErrorCodes, JsonRpcParseError, MCP_PROTOCOL_VERSION, McpError, McpInvalidParamsError, McpMethodNotFoundError, McpPromptNotFoundError, McpResourceNotFoundError, McpServerProvider, McpToolNotFoundError, PromptPrimitive, ResourcePrimitive, SseMcpTransport, StdioMcpTransport, ToolPrimitive, createErrorResponse, createInternalError, createInvalidParamsError, createInvalidRequestError, createMethodNotFoundError, createNotification, createParseError, createResponse, isNotification, isValidJsonRpcRequest, parseMessage };
978
+ //# sourceMappingURL=index.js.map