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