Model Context Protocol in OCaml
1(* Mcp_message - High-level RPC message definitions for Model Context Protocol *)
2
3open Mcp
4open Jsonrpc
5
6(* Resources/List *)
7module ResourcesList = struct
8 module Request = struct
9 type t = {
10 cursor: Cursor.t option;
11 }
12
13 let yojson_of_t { cursor } =
14 let assoc = [] in
15 let assoc = match cursor with
16 | Some c -> ("cursor", Cursor.yojson_of_t c) :: assoc
17 | None -> assoc
18 in
19 `Assoc assoc
20
21 let t_of_yojson = function
22 | `Assoc fields ->
23 let cursor = List.assoc_opt "cursor" fields |> Option.map Cursor.t_of_yojson in
24 { cursor }
25 | j -> Util.json_error "Expected object for ResourcesList.Request.t" j
26
27 end
28
29 module Resource = struct
30 type t = {
31 uri: string;
32 name: string;
33 description: string option;
34 mime_type: string option;
35 size: int option;
36 }
37
38 let yojson_of_t { uri; name; description; mime_type; size } =
39 let assoc = [
40 ("uri", `String uri);
41 ("name", `String name);
42 ] in
43 let assoc = match description with
44 | Some desc -> ("description", `String desc) :: assoc
45 | None -> assoc
46 in
47 let assoc = match mime_type with
48 | Some mime -> ("mimeType", `String mime) :: assoc
49 | None -> assoc
50 in
51 let assoc = match size with
52 | Some s -> ("size", `Int s) :: assoc
53 | None -> assoc
54 in
55 `Assoc assoc
56
57 let t_of_yojson = function
58 | `Assoc fields as json ->
59 let uri = match List.assoc_opt "uri" fields with
60 | Some (`String s) -> s
61 | _ -> Util.json_error "Missing or invalid 'uri' field" json
62 in
63 let name = match List.assoc_opt "name" fields with
64 | Some (`String s) -> s
65 | _ -> Util.json_error "Missing or invalid 'name' field" json
66 in
67 let description = List.assoc_opt "description" fields |> Option.map (function
68 | `String s -> s
69 | j -> Util.json_error "Expected string for description" j
70 ) in
71 let mime_type = List.assoc_opt "mimeType" fields |> Option.map (function
72 | `String s -> s
73 | j -> Util.json_error "Expected string for mimeType" j
74 ) in
75 let size = List.assoc_opt "size" fields |> Option.map (function
76 | `Int i -> i
77 | j -> Util.json_error "Expected int for size" j
78 ) in
79 { uri; name; description; mime_type; size }
80 | j -> Util.json_error "Expected object for ResourcesList.Resource.t" j
81 end
82
83 module Response = struct
84 type t = {
85 resources: Resource.t list;
86 next_cursor: Cursor.t option;
87 }
88
89 let yojson_of_t { resources; next_cursor } =
90 let assoc = [
91 ("resources", `List (List.map Resource.yojson_of_t resources));
92 ] in
93 let assoc = match next_cursor with
94 | Some c -> ("nextCursor", Cursor.yojson_of_t c) :: assoc
95 | None -> assoc
96 in
97 `Assoc assoc
98
99 let t_of_yojson = function
100 | `Assoc fields as json ->
101 let resources = match List.assoc_opt "resources" fields with
102 | Some (`List items) -> List.map Resource.t_of_yojson items
103 | _ -> Util.json_error "Missing or invalid 'resources' field" json
104 in
105 let next_cursor = List.assoc_opt "nextCursor" fields |> Option.map Cursor.t_of_yojson in
106 { resources; next_cursor }
107 | j -> Util.json_error "Expected object for ResourcesList.Response.t" j
108
109 end
110
111 (* Request/response creation helpers *)
112 let create_request ?cursor ?id () =
113 let id = match id with
114 | Some i -> i
115 | None -> `Int (Random.int 10000)
116 in
117 let params = Request.yojson_of_t { cursor } in
118 JSONRPCMessage.create_request ~id ~meth:Method.ResourcesList ~params:(Some params) ()
119
120 let create_response ~id ~resources ?next_cursor () =
121 let result = Response.yojson_of_t { resources; next_cursor } in
122 JSONRPCMessage.create_response ~id ~result
123end
124
125(* Resources/Templates/List *)
126module ListResourceTemplatesRequest = struct
127 type t = {
128 cursor: Cursor.t option;
129 }
130
131 let yojson_of_t { cursor } =
132 let assoc = [] in
133 let assoc = match cursor with
134 | Some c -> ("cursor", Cursor.yojson_of_t c) :: assoc
135 | None -> assoc
136 in
137 `Assoc assoc
138
139 let t_of_yojson = function
140 | `Assoc fields ->
141 let cursor = List.assoc_opt "cursor" fields |> Option.map Cursor.t_of_yojson in
142 { cursor }
143 | j -> Util.json_error "Expected object for ListResourceTemplatesRequest.t" j
144
145end
146
147(* Resources/Templates/List Response *)
148module ListResourceTemplatesResult = struct
149 module ResourceTemplate = struct
150 type t = {
151 uri_template: string;
152 name: string;
153 description: string option;
154 mime_type: string option;
155 }
156
157 let yojson_of_t { uri_template; name; description; mime_type } =
158 let assoc = [
159 ("uriTemplate", `String uri_template);
160 ("name", `String name);
161 ] in
162 let assoc = match description with
163 | Some desc -> ("description", `String desc) :: assoc
164 | None -> assoc
165 in
166 let assoc = match mime_type with
167 | Some mime -> ("mimeType", `String mime) :: assoc
168 | None -> assoc
169 in
170 `Assoc assoc
171
172 let t_of_yojson = function
173 | `Assoc fields as json ->
174 let uri_template = match List.assoc_opt "uriTemplate" fields with
175 | Some (`String s) -> s
176 | _ -> Util.json_error "Missing or invalid 'uriTemplate' field" json
177 in
178 let name = match List.assoc_opt "name" fields with
179 | Some (`String s) -> s
180 | _ -> Util.json_error "Missing or invalid 'name' field" json
181 in
182 let description = List.assoc_opt "description" fields |> Option.map (function
183 | `String s -> s
184 | j -> Util.json_error "Expected string for description" j
185 ) in
186 let mime_type = List.assoc_opt "mimeType" fields |> Option.map (function
187 | `String s -> s
188 | j -> Util.json_error "Expected string for mimeType" j
189 ) in
190 { uri_template; name; description; mime_type }
191 | j -> Util.json_error "Expected object for ListResourceTemplatesResult.ResourceTemplate.t" j
192 end
193
194 type t = {
195 resource_templates: ResourceTemplate.t list;
196 next_cursor: Cursor.t option;
197 }
198
199 let yojson_of_t { resource_templates; next_cursor } =
200 let assoc = [
201 ("resourceTemplates", `List (List.map ResourceTemplate.yojson_of_t resource_templates));
202 ] in
203 let assoc = match next_cursor with
204 | Some c -> ("nextCursor", Cursor.yojson_of_t c) :: assoc
205 | None -> assoc
206 in
207 `Assoc assoc
208
209 let t_of_yojson = function
210 | `Assoc fields as json ->
211 let resource_templates = match List.assoc_opt "resourceTemplates" fields with
212 | Some (`List items) -> List.map ResourceTemplate.t_of_yojson items
213 | _ -> Util.json_error "Missing or invalid 'resourceTemplates' field" json
214 in
215 let next_cursor = List.assoc_opt "nextCursor" fields |> Option.map Cursor.t_of_yojson in
216 { resource_templates; next_cursor }
217 | j -> Util.json_error "Expected object for ListResourceTemplatesResult.t" j
218
219 (* Request/response creation helpers *)
220 let create_request ?cursor ?id () =
221 let id = match id with
222 | Some i -> i
223 | None -> `Int (Random.int 10000)
224 in
225 let params = ListResourceTemplatesRequest.yojson_of_t { cursor } in
226 JSONRPCMessage.create_request ~id ~meth:Method.ResourceTemplatesList ~params:(Some params) ()
227
228 let create_response ~id ~resource_templates ?next_cursor () =
229 let result = yojson_of_t { resource_templates; next_cursor } in
230 JSONRPCMessage.create_response ~id ~result
231end
232
233(* Resources/Read *)
234module ResourcesRead = struct
235 module Request = struct
236 type t = {
237 uri: string;
238 }
239
240 let yojson_of_t { uri } =
241 `Assoc [
242 ("uri", `String uri);
243 ]
244
245 let t_of_yojson = function
246 | `Assoc fields as json ->
247 let uri = match List.assoc_opt "uri" fields with
248 | Some (`String s) -> s
249 | _ -> Util.json_error "Missing or invalid 'uri' field" json
250 in
251 { uri }
252 | j -> Util.json_error "Expected object for ResourcesRead.Request.t" j
253
254 end
255
256 module ResourceContent = struct
257 type t =
258 | TextResource of TextResourceContents.t
259 | BlobResource of BlobResourceContents.t
260
261 let yojson_of_t = function
262 | TextResource tr -> TextResourceContents.yojson_of_t tr
263 | BlobResource br -> BlobResourceContents.yojson_of_t br
264
265 let t_of_yojson json =
266 match json with
267 | `Assoc fields ->
268 if List.mem_assoc "text" fields then
269 TextResource (TextResourceContents.t_of_yojson json)
270 else if List.mem_assoc "blob" fields then
271 BlobResource (BlobResourceContents.t_of_yojson json)
272 else
273 Util.json_error "Invalid resource content" json
274 | j -> Util.json_error "Expected object for ResourcesRead.ResourceContent.t" j
275
276 end
277
278 module Response = struct
279 type t = {
280 contents: ResourceContent.t list;
281 }
282
283 let yojson_of_t { contents } =
284 `Assoc [
285 ("contents", `List (List.map ResourceContent.yojson_of_t contents));
286 ]
287
288 let t_of_yojson = function
289 | `Assoc fields as json ->
290 let contents = match List.assoc_opt "contents" fields with
291 | Some (`List items) -> List.map ResourceContent.t_of_yojson items
292 | _ -> Util.json_error "Missing or invalid 'contents' field" json
293 in
294 { contents }
295 | j -> Util.json_error "Expected object for ResourcesRead.Response.t" j
296
297 end
298
299 (* Request/response creation helpers *)
300 let create_request ~uri ?id () =
301 let id = match id with
302 | Some i -> i
303 | None -> `Int (Random.int 10000)
304 in
305 let params = Request.yojson_of_t { uri } in
306 JSONRPCMessage.create_request ~id ~meth:Method.ResourcesRead ~params:(Some params) ()
307
308 let create_response ~id ~contents () =
309 let result = Response.yojson_of_t { contents } in
310 JSONRPCMessage.create_response ~id ~result
311end
312
313(* Tools/List *)
314module ToolsList = struct
315 module Request = struct
316 type t = {
317 cursor: Cursor.t option;
318 }
319
320 let yojson_of_t { cursor } =
321 let assoc = [] in
322 let assoc = match cursor with
323 | Some c -> ("cursor", Cursor.yojson_of_t c) :: assoc
324 | None -> assoc
325 in
326 `Assoc assoc
327
328 let t_of_yojson = function
329 | `Assoc fields ->
330 let cursor = List.assoc_opt "cursor" fields |> Option.map Cursor.t_of_yojson in
331 { cursor }
332 | j -> Util.json_error "Expected object for ToolsList.Request.t" j
333
334 end
335
336 module Tool = struct
337 type t = {
338 name: string;
339 description: string option;
340 input_schema: Json.t;
341 annotations: Json.t option;
342 }
343
344 let yojson_of_t { name; description; input_schema; annotations } =
345 let assoc = [
346 ("name", `String name);
347 ("inputSchema", input_schema);
348 ] in
349 let assoc = match description with
350 | Some desc -> ("description", `String desc) :: assoc
351 | None -> assoc
352 in
353 let assoc = match annotations with
354 | Some anno -> ("annotations", anno) :: assoc
355 | None -> assoc
356 in
357 `Assoc assoc
358
359 let t_of_yojson = function
360 | `Assoc fields as json ->
361 let name = match List.assoc_opt "name" fields with
362 | Some (`String s) -> s
363 | _ -> Util.json_error "Missing or invalid 'name' field" json
364 in
365 let description = List.assoc_opt "description" fields |> Option.map (function
366 | `String s -> s
367 | j -> Util.json_error "Expected string for description" j
368 ) in
369 let input_schema = match List.assoc_opt "inputSchema" fields with
370 | Some schema -> schema
371 | None -> Util.json_error "Missing 'inputSchema' field" json
372 in
373 let annotations = List.assoc_opt "annotations" fields in
374 { name; description; input_schema; annotations }
375 | j -> Util.json_error "Expected object for ToolsList.Tool.t" j
376
377 end
378
379 module Response = struct
380 type t = {
381 tools: Tool.t list;
382 next_cursor: Cursor.t option;
383 }
384
385 let yojson_of_t { tools; next_cursor } =
386 let assoc = [
387 ("tools", `List (List.map Tool.yojson_of_t tools));
388 ] in
389 let assoc = match next_cursor with
390 | Some c -> ("nextCursor", Cursor.yojson_of_t c) :: assoc
391 | None -> assoc
392 in
393 `Assoc assoc
394
395 let t_of_yojson = function
396 | `Assoc fields as json ->
397 let tools = match List.assoc_opt "tools" fields with
398 | Some (`List items) -> List.map Tool.t_of_yojson items
399 | _ -> Util.json_error "Missing or invalid 'tools' field" json
400 in
401 let next_cursor = List.assoc_opt "nextCursor" fields |> Option.map Cursor.t_of_yojson in
402 { tools; next_cursor }
403 | j -> Util.json_error "Expected object for ToolsList.Response.t" j
404
405 end
406
407 (* Request/response creation helpers *)
408 let create_request ?cursor ?id () =
409 let id = match id with
410 | Some i -> i
411 | None -> `Int (Random.int 10000)
412 in
413 let params = Request.yojson_of_t { cursor } in
414 JSONRPCMessage.create_request ~id ~meth:Method.ToolsList ~params:(Some params) ()
415
416 let create_response ~id ~tools ?next_cursor () =
417 let result = Response.yojson_of_t { tools; next_cursor } in
418 JSONRPCMessage.create_response ~id ~result
419end
420
421(* Tools/Call *)
422module ToolsCall = struct
423 module Request = struct
424 type t = {
425 name: string;
426 arguments: Json.t;
427 }
428
429 let yojson_of_t { name; arguments } =
430 `Assoc [
431 ("name", `String name);
432 ("arguments", arguments);
433 ]
434
435 let t_of_yojson = function
436 | `Assoc fields as json ->
437 let name = match List.assoc_opt "name" fields with
438 | Some (`String s) -> s
439 | _ -> Util.json_error "Missing or invalid 'name' field" json
440 in
441 let arguments = match List.assoc_opt "arguments" fields with
442 | Some json -> json
443 | None -> Util.json_error "Missing 'arguments' field" json
444 in
445 { name; arguments }
446 | j -> Util.json_error "Expected object for ToolsCall.Request.t" j
447
448 end
449
450 module ToolContent = struct
451 type t =
452 | Text of TextContent.t
453 | Image of ImageContent.t
454 | Audio of AudioContent.t
455 | Resource of EmbeddedResource.t
456
457 let yojson_of_t = function
458 | Text t -> TextContent.yojson_of_t t
459 | Image i -> ImageContent.yojson_of_t i
460 | Audio a -> AudioContent.yojson_of_t a
461 | Resource r -> EmbeddedResource.yojson_of_t r
462
463 let t_of_yojson json =
464 match json with
465 | `Assoc fields ->
466 (match List.assoc_opt "type" fields with
467 | Some (`String "text") -> Text (TextContent.t_of_yojson json)
468 | Some (`String "image") -> Image (ImageContent.t_of_yojson json)
469 | Some (`String "audio") -> Audio (AudioContent.t_of_yojson json)
470 | Some (`String "resource") -> Resource (EmbeddedResource.t_of_yojson json)
471 | _ -> Util.json_error "Invalid or missing content type" json)
472 | j -> Util.json_error "Expected object for ToolsCall.ToolContent.t" j
473
474 end
475
476 module Response = struct
477 type t = {
478 content: ToolContent.t list;
479 is_error: bool;
480 }
481
482 let yojson_of_t { content; is_error } =
483 `Assoc [
484 ("content", `List (List.map ToolContent.yojson_of_t content));
485 ("isError", `Bool is_error);
486 ]
487
488 let t_of_yojson = function
489 | `Assoc fields as json ->
490 let content = match List.assoc_opt "content" fields with
491 | Some (`List items) -> List.map ToolContent.t_of_yojson items
492 | _ -> Util.json_error "Missing or invalid 'content' field" json
493 in
494 let is_error = match List.assoc_opt "isError" fields with
495 | Some (`Bool b) -> b
496 | _ -> false
497 in
498 { content; is_error }
499 | j -> Util.json_error "Expected object for ToolsCall.Response.t" j
500
501 end
502
503 (* Request/response creation helpers *)
504 let create_request ~name ~arguments ?id () =
505 let id = match id with
506 | Some i -> i
507 | None -> `Int (Random.int 10000)
508 in
509 let params = Request.yojson_of_t { name; arguments } in
510 JSONRPCMessage.create_request ~id ~meth:Method.ToolsCall ~params:(Some params) ()
511
512 let create_response ~id ~content ~is_error () =
513 let result = Response.yojson_of_t { content; is_error } in
514 JSONRPCMessage.create_response ~id ~result
515end
516
517(* Prompts/List *)
518module PromptsList = struct
519 module PromptArgument = struct
520 type t = {
521 name: string;
522 description: string option;
523 required: bool;
524 }
525
526 let yojson_of_t { name; description; required } =
527 let assoc = [
528 ("name", `String name);
529 ] in
530 let assoc = match description with
531 | Some desc -> ("description", `String desc) :: assoc
532 | None -> assoc
533 in
534 let assoc = if required then
535 ("required", `Bool true) :: assoc
536 else
537 assoc
538 in
539 `Assoc assoc
540
541 let t_of_yojson = function
542 | `Assoc fields as json ->
543 let name = match List.assoc_opt "name" fields with
544 | Some (`String s) -> s
545 | _ -> Util.json_error "Missing or invalid 'name' field" json
546 in
547 let description = List.assoc_opt "description" fields |> Option.map (function
548 | `String s -> s
549 | j -> Util.json_error "Expected string for description" j
550 ) in
551 let required = match List.assoc_opt "required" fields with
552 | Some (`Bool b) -> b
553 | _ -> false
554 in
555 { name; description; required }
556 | j -> Util.json_error "Expected object for PromptsList.PromptArgument.t" j
557
558 end
559
560 module Prompt = struct
561 type t = {
562 name: string;
563 description: string option;
564 arguments: PromptArgument.t list;
565 }
566
567 let yojson_of_t { name; description; arguments } =
568 let assoc = [
569 ("name", `String name);
570 ] in
571 let assoc = match description with
572 | Some desc -> ("description", `String desc) :: assoc
573 | None -> assoc
574 in
575 let assoc = if arguments <> [] then
576 ("arguments", `List (List.map PromptArgument.yojson_of_t arguments)) :: assoc
577 else
578 assoc
579 in
580 `Assoc assoc
581
582 let t_of_yojson = function
583 | `Assoc fields as json ->
584 let name = match List.assoc_opt "name" fields with
585 | Some (`String s) -> s
586 | _ -> Util.json_error "Missing or invalid 'name' field" json
587 in
588 let description = List.assoc_opt "description" fields |> Option.map (function
589 | `String s -> s
590 | j -> Util.json_error "Expected string for description" j
591 ) in
592 let arguments = match List.assoc_opt "arguments" fields with
593 | Some (`List items) -> List.map PromptArgument.t_of_yojson items
594 | _ -> []
595 in
596 { name; description; arguments }
597 | j -> Util.json_error "Expected object for PromptsList.Prompt.t" j
598
599 end
600
601 module Request = struct
602 type t = {
603 cursor: Cursor.t option;
604 }
605
606 let yojson_of_t { cursor } =
607 let assoc = [] in
608 let assoc = match cursor with
609 | Some c -> ("cursor", Cursor.yojson_of_t c) :: assoc
610 | None -> assoc
611 in
612 `Assoc assoc
613
614 let t_of_yojson = function
615 | `Assoc fields ->
616 let cursor = List.assoc_opt "cursor" fields |> Option.map Cursor.t_of_yojson in
617 { cursor }
618 | j -> Util.json_error "Expected object for PromptsList.Request.t" j
619
620 end
621
622 module Response = struct
623 type t = {
624 prompts: Prompt.t list;
625 next_cursor: Cursor.t option;
626 }
627
628 let yojson_of_t { prompts; next_cursor } =
629 let assoc = [
630 ("prompts", `List (List.map Prompt.yojson_of_t prompts));
631 ] in
632 let assoc = match next_cursor with
633 | Some c -> ("nextCursor", Cursor.yojson_of_t c) :: assoc
634 | None -> assoc
635 in
636 `Assoc assoc
637
638 let t_of_yojson = function
639 | `Assoc fields as json ->
640 let prompts = match List.assoc_opt "prompts" fields with
641 | Some (`List items) -> List.map Prompt.t_of_yojson items
642 | _ -> Util.json_error "Missing or invalid 'prompts' field" json
643 in
644 let next_cursor = List.assoc_opt "nextCursor" fields |> Option.map Cursor.t_of_yojson in
645 { prompts; next_cursor }
646 | j -> Util.json_error "Expected object for PromptsList.Response.t" j
647
648 end
649
650 (* Request/response creation helpers *)
651 let create_request ?cursor ?id () =
652 let id = match id with
653 | Some i -> i
654 | None -> `Int (Random.int 10000)
655 in
656 let params = Request.yojson_of_t { cursor } in
657 JSONRPCMessage.create_request ~id ~meth:Method.PromptsList ~params:(Some params) ()
658
659 let create_response ~id ~prompts ?next_cursor () =
660 let result = Response.yojson_of_t { prompts; next_cursor } in
661 JSONRPCMessage.create_response ~id ~result
662end
663
664(* Prompts/Get *)
665module PromptsGet = struct
666 module Request = struct
667 type t = {
668 name: string;
669 arguments: (string * string) list;
670 }
671
672 let yojson_of_t { name; arguments } =
673 let args_json = `Assoc (List.map (fun (k, v) -> (k, `String v)) arguments) in
674 `Assoc [
675 ("name", `String name);
676 ("arguments", args_json);
677 ]
678
679 let t_of_yojson = function
680 | `Assoc fields as json ->
681 let name = match List.assoc_opt "name" fields with
682 | Some (`String s) -> s
683 | _ -> Util.json_error "Missing or invalid 'name' field" json
684 in
685 let arguments = match List.assoc_opt "arguments" fields with
686 | Some (`Assoc args) ->
687 List.map (fun (k, v) ->
688 match v with
689 | `String s -> (k, s)
690 | _ -> Util.json_error "Expected string value for argument" v
691 ) args
692 | _ -> []
693 in
694 { name; arguments }
695 | j -> Util.json_error "Expected object for PromptsGet.Request.t" j
696
697 end
698
699 module Response = struct
700 type t = {
701 description: string option;
702 messages: PromptMessage.t list;
703 }
704
705 let yojson_of_t { description; messages } =
706 let assoc = [
707 ("messages", `List (List.map PromptMessage.yojson_of_t messages));
708 ] in
709 let assoc = match description with
710 | Some desc -> ("description", `String desc) :: assoc
711 | None -> assoc
712 in
713 `Assoc assoc
714
715 let t_of_yojson = function
716 | `Assoc fields as json ->
717 let messages = match List.assoc_opt "messages" fields with
718 | Some (`List items) -> List.map PromptMessage.t_of_yojson items
719 | _ -> Util.json_error "Missing or invalid 'messages' field" json
720 in
721 let description = List.assoc_opt "description" fields |> Option.map (function
722 | `String s -> s
723 | j -> Util.json_error "Expected string for description" j
724 ) in
725 { description; messages }
726 | j -> Util.json_error "Expected object for PromptsGet.Response.t" j
727
728 end
729
730 (* Request/response creation helpers *)
731 let create_request ~name ~arguments ?id () =
732 let id = match id with
733 | Some i -> i
734 | None -> `Int (Random.int 10000)
735 in
736 let params = Request.yojson_of_t { name; arguments } in
737 JSONRPCMessage.create_request ~id ~meth:Method.PromptsGet ~params:(Some params) ()
738
739 let create_response ~id ?description ~messages () =
740 let result = Response.yojson_of_t { description; messages } in
741 JSONRPCMessage.create_response ~id ~result
742end
743
744(* List Changed Notifications *)
745module ListChanged = struct
746 (* No parameters for these notifications *)
747
748 let create_resources_notification () =
749 JSONRPCMessage.create_notification ~meth:Method.ResourcesListChanged ()
750
751 let create_tools_notification () =
752 JSONRPCMessage.create_notification ~meth:Method.ToolsListChanged ()
753
754 let create_prompts_notification () =
755 JSONRPCMessage.create_notification ~meth:Method.PromptsListChanged ()
756end
757
758(* Resource Updated Notification *)
759module ResourceUpdated = struct
760 module Notification = struct
761 type t = {
762 uri: string;
763 }
764
765 let yojson_of_t { uri } =
766 `Assoc [
767 ("uri", `String uri);
768 ]
769
770 let t_of_yojson = function
771 | `Assoc fields as json ->
772 let uri = match List.assoc_opt "uri" fields with
773 | Some (`String s) -> s
774 | _ -> Util.json_error "Missing or invalid 'uri' field" json
775 in
776 { uri }
777 | j -> Util.json_error "Expected object for ResourceUpdated.Notification.t" j
778
779 end
780
781 let create_notification ~uri () =
782 let params = Notification.yojson_of_t { uri } in
783 JSONRPCMessage.create_notification ~meth:Method.ResourcesUpdated ~params:(Some params) ()
784end
785
786(* Progress Notification *)
787module Progress = struct
788 module Notification = struct
789 type t = {
790 progress: float;
791 total: float;
792 progress_token: ProgressToken.t;
793 }
794
795 let yojson_of_t { progress; total; progress_token } =
796 `Assoc [
797 ("progress", `Float progress);
798 ("total", `Float total);
799 ("progressToken", ProgressToken.yojson_of_t progress_token);
800 ]
801
802 let t_of_yojson = function
803 | `Assoc fields as json ->
804 let progress = match List.assoc_opt "progress" fields with
805 | Some (`Float f) -> f
806 | _ -> Util.json_error "Missing or invalid 'progress' field" json
807 in
808 let total = match List.assoc_opt "total" fields with
809 | Some (`Float f) -> f
810 | _ -> Util.json_error "Missing or invalid 'total' field" json
811 in
812 let progress_token = match List.assoc_opt "progressToken" fields with
813 | Some token -> ProgressToken.t_of_yojson token
814 | _ -> Util.json_error "Missing or invalid 'progressToken' field" json
815 in
816 { progress; total; progress_token }
817 | j -> Util.json_error "Expected object for Progress.Notification.t" j
818
819 end
820
821 let create_notification ~progress ~total ~progress_token () =
822 let params = Notification.yojson_of_t { progress; total; progress_token } in
823 JSONRPCMessage.create_notification ~meth:Method.Progress ~params:(Some params) ()
824end
825
826(* Type aliases for backward compatibility *)
827type request = ResourcesList.Request.t
828type response = ResourcesList.Response.t
829type resource = ResourcesList.Resource.t
830type resource_content = ResourcesRead.ResourceContent.t
831type tool = ToolsList.Tool.t
832type tool_content = ToolsCall.ToolContent.t
833type prompt = PromptsList.Prompt.t
834type prompt_argument = PromptsList.PromptArgument.t