@effect/ai 0.18.12 → 0.18.13

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.
@@ -0,0 +1,708 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.toolkit = exports.run = exports.resource = exports.registerToolkit = exports.registerResource = exports.registerPrompt = exports.prompt = exports.layerStdio = exports.layerHttp = exports.layer = exports.McpServer = void 0;
7
+ var Headers = _interopRequireWildcard(require("@effect/platform/Headers"));
8
+ var RpcClient = _interopRequireWildcard(require("@effect/rpc/RpcClient"));
9
+ var RpcSerialization = _interopRequireWildcard(require("@effect/rpc/RpcSerialization"));
10
+ var RpcServer = _interopRequireWildcard(require("@effect/rpc/RpcServer"));
11
+ var Arr = _interopRequireWildcard(require("effect/Array"));
12
+ var Cause = _interopRequireWildcard(require("effect/Cause"));
13
+ var Context = _interopRequireWildcard(require("effect/Context"));
14
+ var Effect = _interopRequireWildcard(require("effect/Effect"));
15
+ var Exit = _interopRequireWildcard(require("effect/Exit"));
16
+ var JsonSchema = _interopRequireWildcard(require("effect/JSONSchema"));
17
+ var Layer = _interopRequireWildcard(require("effect/Layer"));
18
+ var Logger = _interopRequireWildcard(require("effect/Logger"));
19
+ var Mailbox = _interopRequireWildcard(require("effect/Mailbox"));
20
+ var Option = _interopRequireWildcard(require("effect/Option"));
21
+ var Schema = _interopRequireWildcard(require("effect/Schema"));
22
+ var AST = _interopRequireWildcard(require("effect/SchemaAST"));
23
+ var FindMyWay = _interopRequireWildcard(require("find-my-way-ts"));
24
+ var AiTool = _interopRequireWildcard(require("./AiTool.js"));
25
+ var _McpSchema = require("./McpSchema.js");
26
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
27
+ /**
28
+ * @since 1.0.0
29
+ */
30
+
31
+ /**
32
+ * @since 1.0.0
33
+ * @category McpServer
34
+ */
35
+ class McpServer extends /*#__PURE__*/Context.Tag("@effect/ai/McpServer")() {
36
+ /**
37
+ * @since 1.0.0
38
+ */
39
+ static make = /*#__PURE__*/Effect.gen(function* () {
40
+ const matcher = makeUriMatcher();
41
+ const tools = Arr.empty();
42
+ const toolMap = new Map();
43
+ const resources = [];
44
+ const resourceTemplates = [];
45
+ const prompts = [];
46
+ const promptMap = new Map();
47
+ const completionsMap = new Map();
48
+ const notificationsMailbox = yield* Mailbox.make();
49
+ const listChangedHandles = new Map();
50
+ const notifications = yield* RpcClient.makeNoSerialization(_McpSchema.ServerNotificationRpcs, {
51
+ onFromClient(options) {
52
+ const message = options.message;
53
+ if (message._tag !== "Request") {
54
+ return Effect.void;
55
+ }
56
+ if (message.tag.includes("list_changed")) {
57
+ if (!listChangedHandles.has(message.tag)) {
58
+ listChangedHandles.set(message.tag, setTimeout(() => {
59
+ notificationsMailbox.unsafeOffer(message);
60
+ listChangedHandles.delete(message.tag);
61
+ }, 0));
62
+ }
63
+ } else {
64
+ notificationsMailbox.unsafeOffer(message);
65
+ }
66
+ return notifications.write({
67
+ clientId: 0,
68
+ requestId: message.id,
69
+ _tag: "Exit",
70
+ exit: Exit.void
71
+ });
72
+ }
73
+ });
74
+ return McpServer.of({
75
+ notifications: notifications.client,
76
+ notificationsMailbox,
77
+ get tools() {
78
+ return tools;
79
+ },
80
+ addTool: options => Effect.suspend(() => {
81
+ tools.push(options.tool);
82
+ toolMap.set(options.tool.name, options.handle);
83
+ return notifications.client["notifications/tools/list_changed"]({});
84
+ }),
85
+ callTool: request => Effect.suspend(() => {
86
+ const handle = toolMap.get(request.name);
87
+ if (!handle) {
88
+ return Effect.fail(new _McpSchema.InvalidParams({
89
+ message: `Tool '${request.name}' not found`
90
+ }));
91
+ }
92
+ return handle(request.arguments);
93
+ }),
94
+ get resources() {
95
+ return resources;
96
+ },
97
+ get resourceTemplates() {
98
+ return resourceTemplates;
99
+ },
100
+ addResource: (resource, effect) => Effect.suspend(() => {
101
+ resources.push(resource);
102
+ matcher.add(resource.uri, {
103
+ _tag: "Resource",
104
+ effect
105
+ });
106
+ return notifications.client["notifications/resources/list_changed"]({});
107
+ }),
108
+ addResourceTemplate: ({
109
+ completions,
110
+ handle,
111
+ routerPath,
112
+ template
113
+ }) => Effect.suspend(() => {
114
+ resourceTemplates.push(template);
115
+ matcher.add(routerPath, {
116
+ _tag: "ResourceTemplate",
117
+ handle
118
+ });
119
+ for (const [param, handle] of Object.entries(completions)) {
120
+ completionsMap.set(`ref/resource/${template.uriTemplate}/${param}`, handle);
121
+ }
122
+ return notifications.client["notifications/resources/list_changed"]({});
123
+ }),
124
+ findResource: uri => Effect.suspend(() => {
125
+ const match = matcher.find(uri);
126
+ if (!match) {
127
+ return Effect.succeed(new _McpSchema.ReadResourceResult({
128
+ contents: []
129
+ }));
130
+ } else if (match.handler._tag === "Resource") {
131
+ return match.handler.effect;
132
+ }
133
+ const params = [];
134
+ for (const key of Object.keys(match.params)) {
135
+ params[Number(key)] = match.params[key];
136
+ }
137
+ return match.handler.handle(uri, params);
138
+ }),
139
+ get prompts() {
140
+ return prompts;
141
+ },
142
+ addPrompt: options => Effect.suspend(() => {
143
+ prompts.push(options.prompt);
144
+ promptMap.set(options.prompt.name, options.handle);
145
+ for (const [param, handle] of Object.entries(options.completions)) {
146
+ completionsMap.set(`ref/prompt/${options.prompt.name}/${param}`, handle);
147
+ }
148
+ return notifications.client["notifications/prompts/list_changed"]({});
149
+ }),
150
+ getPromptResult: Effect.fnUntraced(function* ({
151
+ arguments: params,
152
+ name
153
+ }) {
154
+ const handler = promptMap.get(name);
155
+ if (!handler) {
156
+ return yield* new _McpSchema.InvalidParams({
157
+ message: `Prompt '${name}' not found`
158
+ });
159
+ }
160
+ return yield* handler(params ?? {});
161
+ }),
162
+ completion: Effect.fnUntraced(function* (complete) {
163
+ const ref = complete.ref;
164
+ const key = ref.type === "ref/resource" ? `ref/resource/${ref.uri}/${complete.argument.name}` : `ref/prompt/${ref.name}/${complete.argument.name}`;
165
+ const handler = completionsMap.get(key);
166
+ return handler ? yield* handler(complete.argument.value) : _McpSchema.CompleteResult.empty;
167
+ })
168
+ });
169
+ });
170
+ /**
171
+ * @since 1.0.0
172
+ */
173
+ static layer = /*#__PURE__*/Layer.scoped(McpServer, McpServer.make);
174
+ }
175
+ exports.McpServer = McpServer;
176
+ const LATEST_PROTOCOL_VERSION = "2025-03-26";
177
+ const SUPPORTED_PROTOCOL_VERSIONS = [LATEST_PROTOCOL_VERSION, "2024-11-05", "2024-10-07"];
178
+ /**
179
+ * @since 1.0.0
180
+ * @category Constructors
181
+ */
182
+ const run = exports.run = /*#__PURE__*/Effect.fnUntraced(function* (options) {
183
+ const protocol = yield* RpcServer.Protocol;
184
+ const handlers = yield* Layer.build(layerHandlers(options));
185
+ const server = yield* McpServer;
186
+ const patchedProtocol = RpcServer.Protocol.of({
187
+ ...protocol,
188
+ run: f => protocol.run((clientId, request) => {
189
+ if (request._tag === "Request" && request.tag.startsWith("notifications/")) {
190
+ if (request.tag === "notifications/cancelled") {
191
+ return f(clientId, {
192
+ _tag: "Interrupt",
193
+ requestId: String(request.payload.requestId)
194
+ });
195
+ }
196
+ const handler = handlers.unsafeMap.get(request.tag);
197
+ return handler ? handler.handler(request.payload, Headers.fromInput(request.headers)) : Effect.void;
198
+ }
199
+ return f(clientId, request);
200
+ })
201
+ });
202
+ const encodeNotification = Schema.encode(Schema.Union(...Array.from(_McpSchema.ServerNotificationRpcs.requests.values(), rpc => rpc.payloadSchema)));
203
+ yield* server.notificationsMailbox.take.pipe(Effect.flatMap(Effect.fnUntraced(function* (request) {
204
+ const encoded = yield* encodeNotification(request.payload);
205
+ const message = {
206
+ _tag: "Request",
207
+ tag: request.tag,
208
+ payload: encoded
209
+ };
210
+ const clientIds = yield* patchedProtocol.clientIds;
211
+ for (const clientId of clientIds) {
212
+ yield* patchedProtocol.send(clientId, message);
213
+ }
214
+ })), Effect.catchAllCause(() => Effect.void), Effect.forever, Effect.forkScoped);
215
+ return yield* RpcServer.make(_McpSchema.ClientRpcs, {
216
+ spanPrefix: "McpServer",
217
+ disableFatalDefects: true
218
+ }).pipe(Effect.provideService(RpcServer.Protocol, patchedProtocol), Effect.provide(handlers));
219
+ }, Effect.scoped);
220
+ /**
221
+ * @since 1.0.0
222
+ * @category Layers
223
+ */
224
+ const layer = options => Layer.scopedDiscard(Effect.forkScoped(run(options))).pipe(Layer.provideMerge(McpServer.layer));
225
+ /**
226
+ * Run the McpServer, using stdio for input and output.
227
+ *
228
+ * ```ts
229
+ * import { McpSchema, McpServer } from "@effect/ai"
230
+ * import { NodeRuntime, NodeSink, NodeStream } from "@effect/platform-node"
231
+ * import { Effect, Layer, Logger, Schema } from "effect"
232
+ *
233
+ * const idParam = McpSchema.param("id", Schema.NumberFromString)
234
+ *
235
+ * // Define a resource template for a README file
236
+ * const ReadmeTemplate = McpServer.resource`file://readme/${idParam}`({
237
+ * name: "README Template",
238
+ * // You can add auto-completion for the ID parameter
239
+ * completion: {
240
+ * id: (_) => Effect.succeed([1, 2, 3, 4, 5])
241
+ * },
242
+ * content: Effect.fn(function*(_uri, id) {
243
+ * return `# MCP Server Demo - ID: ${id}`
244
+ * })
245
+ * })
246
+ *
247
+ * // Define a test prompt with parameters
248
+ * const TestPrompt = McpServer.prompt({
249
+ * name: "Test Prompt",
250
+ * description: "A test prompt to demonstrate MCP server capabilities",
251
+ * parameters: Schema.Struct({
252
+ * flightNumber: Schema.String
253
+ * }),
254
+ * completion: {
255
+ * flightNumber: () => Effect.succeed(["FL123", "FL456", "FL789"])
256
+ * },
257
+ * content: ({ flightNumber }) => Effect.succeed(`Get the booking details for flight number: ${flightNumber}`)
258
+ * })
259
+ *
260
+ * // Merge all the resources and prompts into a single server layer
261
+ * const ServerLayer = Layer.mergeAll(
262
+ * ReadmeTemplate,
263
+ * TestPrompt
264
+ * ).pipe(
265
+ * // Provide the MCP server implementation
266
+ * Layer.provide(McpServer.layerStdio({
267
+ * name: "Demo Server",
268
+ * version: "1.0.0",
269
+ * stdin: NodeStream.stdin,
270
+ * stdout: NodeSink.stdout
271
+ * })),
272
+ * // add a stderr logger
273
+ * Layer.provide(Logger.add(Logger.prettyLogger({ stderr: true })))
274
+ * )
275
+ *
276
+ * Layer.launch(ServerLayer).pipe(NodeRuntime.runMain)
277
+ * ```
278
+ *
279
+ * @since 1.0.0
280
+ * @category Layers
281
+ */
282
+ exports.layer = layer;
283
+ const layerStdio = options => layer(options).pipe(Layer.provide(RpcServer.layerProtocolStdio({
284
+ stdin: options.stdin,
285
+ stdout: options.stdout
286
+ })), Layer.provide(RpcSerialization.layerNdJsonRpc()),
287
+ // remove stdout loggers
288
+ Layer.provideMerge(Logger.remove(Logger.defaultLogger)), Layer.provideMerge(Logger.remove(Logger.prettyLoggerDefault)));
289
+ /**
290
+ * Run the McpServer, using HTTP for input and output.
291
+ *
292
+ * ```ts
293
+ * import { McpSchema, McpServer } from "@effect/ai"
294
+ * import { HttpRouter } from "@effect/platform"
295
+ * import { NodeHttpServer, NodeRuntime } from "@effect/platform-node"
296
+ * import { Effect, Layer, Schema } from "effect"
297
+ * import { createServer } from "node:http"
298
+ *
299
+ * const idParam = McpSchema.param("id", Schema.NumberFromString)
300
+ *
301
+ * // Define a resource template for a README file
302
+ * const ReadmeTemplate = McpServer.resource`file://readme/${idParam}`({
303
+ * name: "README Template",
304
+ * // You can add auto-completion for the ID parameter
305
+ * completion: {
306
+ * id: (_) => Effect.succeed([1, 2, 3, 4, 5])
307
+ * },
308
+ * content: Effect.fn(function*(_uri, id) {
309
+ * return `# MCP Server Demo - ID: ${id}`
310
+ * })
311
+ * })
312
+ *
313
+ * // Define a test prompt with parameters
314
+ * const TestPrompt = McpServer.prompt({
315
+ * name: "Test Prompt",
316
+ * description: "A test prompt to demonstrate MCP server capabilities",
317
+ * parameters: Schema.Struct({
318
+ * flightNumber: Schema.String
319
+ * }),
320
+ * completion: {
321
+ * flightNumber: () => Effect.succeed(["FL123", "FL456", "FL789"])
322
+ * },
323
+ * content: ({ flightNumber }) => Effect.succeed(`Get the booking details for flight number: ${flightNumber}`)
324
+ * })
325
+ *
326
+ * // Merge all the resources and prompts into a single server layer
327
+ * const ServerLayer = Layer.mergeAll(
328
+ * ReadmeTemplate,
329
+ * TestPrompt,
330
+ * HttpRouter.Default.serve()
331
+ * ).pipe(
332
+ * // Provide the MCP server implementation
333
+ * Layer.provide(McpServer.layerHttp({
334
+ * name: "Demo Server",
335
+ * version: "1.0.0",
336
+ * path: "/mcp"
337
+ * })),
338
+ * Layer.provide(NodeHttpServer.layer(createServer, { port: 3000 }))
339
+ * )
340
+ *
341
+ * Layer.launch(ServerLayer).pipe(NodeRuntime.runMain)
342
+ * ```
343
+ *
344
+ * @since 1.0.0
345
+ * @category Layers
346
+ */
347
+ exports.layerStdio = layerStdio;
348
+ const layerHttp = options => layer(options).pipe(Layer.provide(RpcServer.layerProtocolHttp(options)), Layer.provide(RpcSerialization.layerJsonRpc()));
349
+ /**
350
+ * Register an AiToolkit with the McpServer.
351
+ *
352
+ * @since 1.0.0
353
+ * @category Tools
354
+ */
355
+ exports.layerHttp = layerHttp;
356
+ const registerToolkit = exports.registerToolkit = /*#__PURE__*/Effect.fnUntraced(function* (toolkit) {
357
+ const registry = yield* McpServer;
358
+ const built = yield* toolkit;
359
+ const context = yield* Effect.context();
360
+ for (const tool of built.tools) {
361
+ const mcpTool = new _McpSchema.Tool({
362
+ name: tool.name,
363
+ description: tool.description,
364
+ inputSchema: makeJsonSchema(tool.parametersSchema.ast),
365
+ annotations: new _McpSchema.ToolAnnotations({
366
+ ...Context.getOption(tool.annotations, AiTool.Title).pipe(Option.map(title => ({
367
+ title
368
+ })), Option.getOrUndefined),
369
+ readOnlyHint: Context.get(tool.annotations, AiTool.Readonly),
370
+ destructiveHint: Context.get(tool.annotations, AiTool.Destructive),
371
+ idempotentHint: Context.get(tool.annotations, AiTool.Idempotent),
372
+ openWorldHint: Context.get(tool.annotations, AiTool.OpenWorld)
373
+ })
374
+ });
375
+ yield* registry.addTool({
376
+ tool: mcpTool,
377
+ handle(payload) {
378
+ return built.handle(tool.name, payload).pipe(Effect.provide(context), Effect.match({
379
+ onFailure: error => new _McpSchema.CallToolResult({
380
+ isError: true,
381
+ content: [new _McpSchema.TextContent({
382
+ text: JSON.stringify(error)
383
+ })]
384
+ }),
385
+ onSuccess: result => new _McpSchema.CallToolResult({
386
+ isError: false,
387
+ content: [new _McpSchema.TextContent({
388
+ text: JSON.stringify(result.encodedResult)
389
+ })]
390
+ })
391
+ }));
392
+ }
393
+ });
394
+ }
395
+ });
396
+ /**
397
+ * Register an AiToolkit with the McpServer.
398
+ *
399
+ * @since 1.0.0
400
+ * @category Tools
401
+ */
402
+ const toolkit = toolkit => Layer.effectDiscard(registerToolkit(toolkit));
403
+ /**
404
+ * Register a resource with the McpServer.
405
+ *
406
+ * @since 1.0.0
407
+ * @category Resources
408
+ */
409
+ exports.toolkit = toolkit;
410
+ const registerResource = function () {
411
+ if (arguments.length === 1) {
412
+ const options = arguments[0];
413
+ return Effect.gen(function* () {
414
+ const context = yield* Effect.context();
415
+ const registry = yield* McpServer;
416
+ yield* registry.addResource(new _McpSchema.Resource({
417
+ ...options,
418
+ annotations: new _McpSchema.Annotations(options)
419
+ }), options.content.pipe(Effect.provide(context), Effect.map(content => resolveResourceContent(options.uri, content)), Effect.catchAllCause(cause => {
420
+ const prettyError = Cause.prettyErrors(cause)[0];
421
+ return new _McpSchema.InternalError({
422
+ message: prettyError.message
423
+ });
424
+ })));
425
+ });
426
+ }
427
+ const {
428
+ params,
429
+ routerPath,
430
+ schema,
431
+ uriPath
432
+ } = compileUriTemplate(...arguments);
433
+ return Effect.fnUntraced(function* (options) {
434
+ const context = yield* Effect.context();
435
+ const registry = yield* McpServer;
436
+ const decode = Schema.decodeUnknown(schema);
437
+ const template = new _McpSchema.ResourceTemplate({
438
+ ...options,
439
+ uriTemplate: uriPath,
440
+ annotations: new _McpSchema.Annotations(options)
441
+ });
442
+ const completions = {};
443
+ for (const [param, handle] of Object.entries(options.completion ?? {})) {
444
+ const encodeArray = Schema.encodeUnknown(Schema.Array(params[param]));
445
+ const handler = input => handle(input).pipe(Effect.flatMap(encodeArray), Effect.map(values => new _McpSchema.CompleteResult({
446
+ completion: {
447
+ values: values,
448
+ total: values.length,
449
+ hasMore: false
450
+ }
451
+ })), Effect.catchAllCause(cause => {
452
+ const prettyError = Cause.prettyErrors(cause)[0];
453
+ return new _McpSchema.InternalError({
454
+ message: prettyError.message
455
+ });
456
+ }), Effect.provide(context));
457
+ completions[param] = handler;
458
+ }
459
+ yield* registry.addResourceTemplate({
460
+ template,
461
+ routerPath,
462
+ completions,
463
+ handle: (uri, params) => decode(params).pipe(Effect.mapError(error => new _McpSchema.InvalidParams({
464
+ message: error.message
465
+ })), Effect.flatMap(params => options.content(uri, ...params).pipe(Effect.map(content => resolveResourceContent(uri, content)), Effect.catchAllCause(cause => {
466
+ const prettyError = Cause.prettyErrors(cause)[0];
467
+ return new _McpSchema.InternalError({
468
+ message: prettyError.message
469
+ });
470
+ }))), Effect.provide(context))
471
+ });
472
+ });
473
+ };
474
+ /**
475
+ * Register a resource with the McpServer.
476
+ *
477
+ * @since 1.0.0
478
+ * @category Resources
479
+ */
480
+ exports.registerResource = registerResource;
481
+ const resource = function () {
482
+ if (arguments.length === 1) {
483
+ return Layer.effectDiscard(registerResource(arguments[0]));
484
+ }
485
+ const register = registerResource(...arguments);
486
+ return options => Layer.effectDiscard(register(options));
487
+ };
488
+ /**
489
+ * Register a prompt with the McpServer.
490
+ *
491
+ * @since 1.0.0
492
+ * @category Resources
493
+ */
494
+ exports.resource = resource;
495
+ const registerPrompt = options => {
496
+ const args = Arr.empty();
497
+ const props = {};
498
+ const propSignatures = options.parameters ? AST.getPropertySignatures(options.parameters.ast) : [];
499
+ for (const prop of propSignatures) {
500
+ args.push(new _McpSchema.PromptArgument({
501
+ name: prop.name,
502
+ description: Option.getOrUndefined(AST.getDescriptionAnnotation(prop)),
503
+ required: !prop.isOptional
504
+ }));
505
+ props[prop.name] = Schema.make(prop.type);
506
+ }
507
+ const prompt = new _McpSchema.Prompt({
508
+ name: options.name,
509
+ description: options.description,
510
+ arguments: args
511
+ });
512
+ const decode = options.parameters ? Schema.decodeUnknown(options.parameters) : () => Effect.succeed({});
513
+ const completion = options.completion ?? {};
514
+ return Effect.gen(function* () {
515
+ const registry = yield* McpServer;
516
+ const context = yield* Effect.context();
517
+ const completions = {};
518
+ for (const [param, handle] of Object.entries(completion)) {
519
+ const encodeArray = Schema.encodeUnknown(Schema.Array(props[param]));
520
+ const handler = input => handle(input).pipe(Effect.flatMap(encodeArray), Effect.map(values => new _McpSchema.CompleteResult({
521
+ completion: {
522
+ values: values,
523
+ total: values.length,
524
+ hasMore: false
525
+ }
526
+ })), Effect.catchAllCause(cause => {
527
+ const prettyError = Cause.prettyErrors(cause)[0];
528
+ return new _McpSchema.InternalError({
529
+ message: prettyError.message
530
+ });
531
+ }), Effect.provide(context));
532
+ completions[param] = handler;
533
+ }
534
+ yield* registry.addPrompt({
535
+ prompt,
536
+ completions,
537
+ handle: params => decode(params).pipe(Effect.mapError(error => new _McpSchema.InvalidParams({
538
+ message: error.message
539
+ })), Effect.flatMap(params => options.content(params)), Effect.map(messages => {
540
+ messages = typeof messages === "string" ? [new _McpSchema.PromptMessage({
541
+ role: "user",
542
+ content: new _McpSchema.TextContent({
543
+ text: messages
544
+ })
545
+ })] : messages;
546
+ return new _McpSchema.GetPromptResult({
547
+ messages,
548
+ description: prompt.description
549
+ });
550
+ }), Effect.catchAllCause(cause => {
551
+ const prettyError = Cause.prettyErrors(cause)[0];
552
+ return new _McpSchema.InternalError({
553
+ message: prettyError.message
554
+ });
555
+ }), Effect.provide(context))
556
+ });
557
+ });
558
+ };
559
+ /**
560
+ * Register a prompt with the McpServer.
561
+ *
562
+ * @since 1.0.0
563
+ * @category Resources
564
+ */
565
+ exports.registerPrompt = registerPrompt;
566
+ const prompt = options => Layer.effectDiscard(registerPrompt(options));
567
+ // -----------------------------------------------------------------------------
568
+ // Internal
569
+ // -----------------------------------------------------------------------------
570
+ exports.prompt = prompt;
571
+ const makeUriMatcher = () => {
572
+ const router = FindMyWay.make({
573
+ ignoreTrailingSlash: true,
574
+ ignoreDuplicateSlashes: true,
575
+ caseSensitive: true
576
+ });
577
+ const add = (uri, value) => {
578
+ router.on("GET", uri, value);
579
+ };
580
+ const find = uri => router.find("GET", uri);
581
+ return {
582
+ add,
583
+ find
584
+ };
585
+ };
586
+ const compileUriTemplate = (segments, ...schemas) => {
587
+ let routerPath = segments[0].replace(":", "::");
588
+ let uriPath = segments[0];
589
+ const params = {};
590
+ let pathSchema = Schema.Tuple();
591
+ if (schemas.length > 0) {
592
+ const arr = [];
593
+ for (let i = 0; i < schemas.length; i++) {
594
+ const schema = schemas[i];
595
+ const key = String(i);
596
+ arr.push(schema);
597
+ routerPath += `:${key}${segments[i + 1].replace(":", "::")}`;
598
+ const paramName = AST.getAnnotation(_McpSchema.ParamAnnotation)(schema.ast).pipe(Option.getOrElse(() => `param${key}`));
599
+ params[paramName] = schema;
600
+ uriPath += `{${paramName}}`;
601
+ }
602
+ pathSchema = Schema.Tuple(...arr);
603
+ }
604
+ return {
605
+ routerPath,
606
+ uriPath,
607
+ schema: pathSchema,
608
+ params
609
+ };
610
+ };
611
+ const layerHandlers = serverInfo => _McpSchema.ClientRpcs.toLayer(Effect.gen(function* () {
612
+ const server = yield* McpServer;
613
+ return {
614
+ // Requests
615
+ ping: () => Effect.succeed({}),
616
+ initialize(params) {
617
+ const requestedVersion = params.protocolVersion;
618
+ const capabilities = {
619
+ completions: {}
620
+ };
621
+ if (server.tools.length > 0) {
622
+ capabilities.tools = {
623
+ listChanged: true
624
+ };
625
+ }
626
+ if (server.resources.length > 0 || server.resourceTemplates.length > 0) {
627
+ capabilities.resources = {
628
+ listChanged: true,
629
+ subscribe: false
630
+ };
631
+ }
632
+ if (server.prompts.length > 0) {
633
+ capabilities.prompts = {
634
+ listChanged: true
635
+ };
636
+ }
637
+ return Effect.succeed({
638
+ capabilities,
639
+ serverInfo,
640
+ protocolVersion: SUPPORTED_PROTOCOL_VERSIONS.includes(requestedVersion) ? requestedVersion : LATEST_PROTOCOL_VERSION
641
+ });
642
+ },
643
+ "completion/complete": server.completion,
644
+ "logging/setLevel": () => _McpSchema.InternalError.notImplemented,
645
+ "prompts/get": server.getPromptResult,
646
+ "prompts/list": () => Effect.sync(() => new _McpSchema.ListPromptsResult({
647
+ prompts: server.prompts
648
+ })),
649
+ "resources/list": () => Effect.sync(() => new _McpSchema.ListResourcesResult({
650
+ resources: server.resources
651
+ })),
652
+ "resources/read": ({
653
+ uri
654
+ }) => server.findResource(uri),
655
+ "resources/subscribe": () => _McpSchema.InternalError.notImplemented,
656
+ "resources/unsubscribe": () => _McpSchema.InternalError.notImplemented,
657
+ "resources/templates/list": () => Effect.sync(() => new _McpSchema.ListResourceTemplatesResult({
658
+ resourceTemplates: server.resourceTemplates
659
+ })),
660
+ "tools/call": server.callTool,
661
+ "tools/list": () => Effect.sync(() => new _McpSchema.ListToolsResult({
662
+ tools: server.tools
663
+ })),
664
+ // Notifications
665
+ "notifications/cancelled": _ => Effect.void,
666
+ "notifications/initialized": _ => Effect.void,
667
+ "notifications/progress": _ => Effect.void,
668
+ "notifications/roots/list_changed": _ => Effect.void
669
+ };
670
+ }));
671
+ const makeJsonSchema = ast => {
672
+ const props = AST.getPropertySignatures(ast);
673
+ if (props.length === 0) {
674
+ return {
675
+ type: "object",
676
+ properties: {},
677
+ required: [],
678
+ additionalProperties: false
679
+ };
680
+ }
681
+ const $defs = {};
682
+ const schema = JsonSchema.fromAST(ast, {
683
+ definitions: $defs,
684
+ topLevelReferenceStrategy: "skip"
685
+ });
686
+ if (Object.keys($defs).length === 0) return schema;
687
+ schema.$defs = $defs;
688
+ return schema;
689
+ };
690
+ const resolveResourceContent = (uri, content) => {
691
+ if (typeof content === "string") {
692
+ return new _McpSchema.ReadResourceResult({
693
+ contents: [new _McpSchema.TextResourceContents({
694
+ uri,
695
+ text: content
696
+ })]
697
+ });
698
+ } else if (content instanceof Uint8Array) {
699
+ return new _McpSchema.ReadResourceResult({
700
+ contents: [new _McpSchema.BlobResourceContents({
701
+ uri,
702
+ blob: content
703
+ })]
704
+ });
705
+ }
706
+ return content;
707
+ };
708
+ //# sourceMappingURL=McpServer.js.map