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