Model Context Protocol in OCaml
1open Jsonrpc 2 3(* Common types *) 4 5module Role = struct 6 type t = [ `User | `Assistant ] 7 8 let to_string = function 9 | `User -> "user" 10 | `Assistant -> "assistant" 11 12 let of_string = function 13 | "user" -> `User 14 | "assistant" -> `Assistant 15 | s -> raise (Json.Of_json ("Unknown role: " ^ s, `String s)) 16 17 let yojson_of_t t = `String (to_string t) 18 let t_of_yojson = function 19 | `String s -> of_string s 20 | j -> raise (Json.Of_json ("Expected string for Role", j)) 21end 22 23module ProgressToken = struct 24 type t = [ `String of string | `Int of int ] 25 26 include (Id : Json.Jsonable.S with type t := t) 27end 28 29module RequestId = Id 30 31module Cursor = struct 32 type t = string 33 34 let yojson_of_t t = `String t 35 let t_of_yojson = function 36 | `String s -> s 37 | j -> raise (Json.Of_json ("Expected string for Cursor", j)) 38end 39 40(* Annotations *) 41 42module Annotated = struct 43 type t = { 44 annotations: annotation option; 45 } 46 and annotation = { 47 audience: Role.t list option; 48 priority: float option; 49 } 50 51 let yojson_of_annotation { audience; priority } = 52 let assoc = [] in 53 let assoc = match audience with 54 | Some audience -> ("audience", `List (List.map Role.yojson_of_t audience)) :: assoc 55 | None -> assoc 56 in 57 let assoc = match priority with 58 | Some priority -> ("priority", `Float priority) :: assoc 59 | None -> assoc 60 in 61 `Assoc assoc 62 63 let annotation_of_yojson = function 64 | `Assoc fields -> 65 let audience = List.assoc_opt "audience" fields |> Option.map (function 66 | `List items -> List.map Role.t_of_yojson items 67 | j -> raise (Json.Of_json ("Expected list for audience", j)) 68 ) in 69 let priority = List.assoc_opt "priority" fields |> Option.map (function 70 | `Float f -> f 71 | j -> raise (Json.Of_json ("Expected float for priority", j)) 72 ) in 73 { audience; priority } 74 | j -> raise (Json.Of_json ("Expected object for annotation", j)) 75 76 let yojson_of_t { annotations } = 77 match annotations with 78 | Some annotations -> `Assoc [ "annotations", yojson_of_annotation annotations ] 79 | None -> `Assoc [] 80 81 let t_of_yojson = function 82 | `Assoc fields -> 83 let annotations = List.assoc_opt "annotations" fields |> Option.map annotation_of_yojson in 84 { annotations } 85 | j -> raise (Json.Of_json ("Expected object for Annotated", j)) 86end 87 88(* Content types *) 89 90module TextContent = struct 91 type t = { 92 text: string; 93 annotations: Annotated.annotation option; 94 } 95 96 let yojson_of_t { text; annotations } = 97 let assoc = [ 98 ("text", `String text); 99 ("type", `String "text"); 100 ] in 101 let assoc = match annotations with 102 | Some annotations -> ("annotations", Annotated.yojson_of_annotation annotations) :: assoc 103 | None -> assoc 104 in 105 `Assoc assoc 106 107 let t_of_yojson = function 108 | `Assoc fields -> 109 let text = match List.assoc_opt "text" fields with 110 | Some (`String s) -> s 111 | _ -> raise (Json.Of_json ("Missing or invalid 'text' field", `Assoc fields)) 112 in 113 let _ = match List.assoc_opt "type" fields with 114 | Some (`String "text") -> () 115 | _ -> raise (Json.Of_json ("Missing or invalid 'type' field", `Assoc fields)) 116 in 117 let annotations = List.assoc_opt "annotations" fields |> Option.map Annotated.annotation_of_yojson in 118 { text; annotations } 119 | j -> raise (Json.Of_json ("Expected object for TextContent", j)) 120end 121 122module ImageContent = struct 123 type t = { 124 data: string; 125 mime_type: string; 126 annotations: Annotated.annotation option; 127 } 128 129 let yojson_of_t { data; mime_type; annotations } = 130 let assoc = [ 131 ("type", `String "image"); 132 ("data", `String data); 133 ("mimeType", `String mime_type); 134 ] in 135 let assoc = match annotations with 136 | Some annotations -> ("annotations", Annotated.yojson_of_annotation annotations) :: assoc 137 | None -> assoc 138 in 139 `Assoc assoc 140 141 let t_of_yojson = function 142 | `Assoc fields -> 143 let data = match List.assoc_opt "data" fields with 144 | Some (`String s) -> s 145 | _ -> raise (Json.Of_json ("Missing or invalid 'data' field", `Assoc fields)) 146 in 147 let mime_type = match List.assoc_opt "mimeType" fields with 148 | Some (`String s) -> s 149 | _ -> raise (Json.Of_json ("Missing or invalid 'mimeType' field", `Assoc fields)) 150 in 151 let _ = match List.assoc_opt "type" fields with 152 | Some (`String "image") -> () 153 | _ -> raise (Json.Of_json ("Missing or invalid 'type' field", `Assoc fields)) 154 in 155 let annotations = List.assoc_opt "annotations" fields |> Option.map Annotated.annotation_of_yojson in 156 { data; mime_type; annotations } 157 | j -> raise (Json.Of_json ("Expected object for ImageContent", j)) 158end 159 160module AudioContent = struct 161 type t = { 162 data: string; 163 mime_type: string; 164 annotations: Annotated.annotation option; 165 } 166 167 let yojson_of_t { data; mime_type; annotations } = 168 let assoc = [ 169 ("type", `String "audio"); 170 ("data", `String data); 171 ("mimeType", `String mime_type); 172 ] in 173 let assoc = match annotations with 174 | Some annotations -> ("annotations", Annotated.yojson_of_annotation annotations) :: assoc 175 | None -> assoc 176 in 177 `Assoc assoc 178 179 let t_of_yojson = function 180 | `Assoc fields -> 181 let data = match List.assoc_opt "data" fields with 182 | Some (`String s) -> s 183 | _ -> raise (Json.Of_json ("Missing or invalid 'data' field", `Assoc fields)) 184 in 185 let mime_type = match List.assoc_opt "mimeType" fields with 186 | Some (`String s) -> s 187 | _ -> raise (Json.Of_json ("Missing or invalid 'mimeType' field", `Assoc fields)) 188 in 189 let _ = match List.assoc_opt "type" fields with 190 | Some (`String "audio") -> () 191 | _ -> raise (Json.Of_json ("Missing or invalid 'type' field", `Assoc fields)) 192 in 193 let annotations = List.assoc_opt "annotations" fields |> Option.map Annotated.annotation_of_yojson in 194 { data; mime_type; annotations } 195 | j -> raise (Json.Of_json ("Expected object for AudioContent", j)) 196end 197 198module ResourceContents = struct 199 type t = { 200 uri: string; 201 mime_type: string option; 202 } 203 204 let yojson_of_t { uri; mime_type } = 205 let assoc = [ 206 ("uri", `String uri); 207 ] in 208 let assoc = match mime_type with 209 | Some mime_type -> ("mimeType", `String mime_type) :: assoc 210 | None -> assoc 211 in 212 `Assoc assoc 213 214 let t_of_yojson = function 215 | `Assoc fields -> 216 let uri = match List.assoc_opt "uri" fields with 217 | Some (`String s) -> s 218 | _ -> raise (Json.Of_json ("Missing or invalid 'uri' field", `Assoc fields)) 219 in 220 let mime_type = List.assoc_opt "mimeType" fields |> Option.map (function 221 | `String s -> s 222 | j -> raise (Json.Of_json ("Expected string for mimeType", j)) 223 ) in 224 { uri; mime_type } 225 | j -> raise (Json.Of_json ("Expected object for ResourceContents", j)) 226end 227 228module TextResourceContents = struct 229 type t = { 230 uri: string; 231 text: string; 232 mime_type: string option; 233 } 234 235 let yojson_of_t { uri; text; mime_type } = 236 let assoc = [ 237 ("uri", `String uri); 238 ("text", `String text); 239 ] in 240 let assoc = match mime_type with 241 | Some mime_type -> ("mimeType", `String mime_type) :: assoc 242 | None -> assoc 243 in 244 `Assoc assoc 245 246 let t_of_yojson = function 247 | `Assoc fields -> 248 let uri = match List.assoc_opt "uri" fields with 249 | Some (`String s) -> s 250 | _ -> raise (Json.Of_json ("Missing or invalid 'uri' field", `Assoc fields)) 251 in 252 let text = match List.assoc_opt "text" fields with 253 | Some (`String s) -> s 254 | _ -> raise (Json.Of_json ("Missing or invalid 'text' field", `Assoc fields)) 255 in 256 let mime_type = List.assoc_opt "mimeType" fields |> Option.map (function 257 | `String s -> s 258 | j -> raise (Json.Of_json ("Expected string for mimeType", j)) 259 ) in 260 { uri; text; mime_type } 261 | j -> raise (Json.Of_json ("Expected object for TextResourceContents", j)) 262end 263 264module BlobResourceContents = struct 265 type t = { 266 uri: string; 267 blob: string; 268 mime_type: string option; 269 } 270 271 let yojson_of_t { uri; blob; mime_type } = 272 let assoc = [ 273 ("uri", `String uri); 274 ("blob", `String blob); 275 ] in 276 let assoc = match mime_type with 277 | Some mime_type -> ("mimeType", `String mime_type) :: assoc 278 | None -> assoc 279 in 280 `Assoc assoc 281 282 let t_of_yojson = function 283 | `Assoc fields -> 284 let uri = match List.assoc_opt "uri" fields with 285 | Some (`String s) -> s 286 | _ -> raise (Json.Of_json ("Missing or invalid 'uri' field", `Assoc fields)) 287 in 288 let blob = match List.assoc_opt "blob" fields with 289 | Some (`String s) -> s 290 | _ -> raise (Json.Of_json ("Missing or invalid 'blob' field", `Assoc fields)) 291 in 292 let mime_type = List.assoc_opt "mimeType" fields |> Option.map (function 293 | `String s -> s 294 | j -> raise (Json.Of_json ("Expected string for mimeType", j)) 295 ) in 296 { uri; blob; mime_type } 297 | j -> raise (Json.Of_json ("Expected object for BlobResourceContents", j)) 298end 299 300module EmbeddedResource = struct 301 type t = { 302 resource: [ `Text of TextResourceContents.t | `Blob of BlobResourceContents.t ]; 303 annotations: Annotated.annotation option; 304 } 305 306 let yojson_of_t { resource; annotations } = 307 let resource_json = match resource with 308 | `Text txt -> TextResourceContents.yojson_of_t txt 309 | `Blob blob -> BlobResourceContents.yojson_of_t blob 310 in 311 let assoc = [ 312 ("resource", resource_json); 313 ("type", `String "resource"); 314 ] in 315 let assoc = match annotations with 316 | Some annotations -> ("annotations", Annotated.yojson_of_annotation annotations) :: assoc 317 | None -> assoc 318 in 319 `Assoc assoc 320 321 let t_of_yojson = function 322 | `Assoc fields -> 323 let _ = match List.assoc_opt "type" fields with 324 | Some (`String "resource") -> () 325 | _ -> raise (Json.Of_json ("Missing or invalid 'type' field", `Assoc fields)) 326 in 327 let resource = match List.assoc_opt "resource" fields with 328 | Some (`Assoc res_fields) -> 329 if List.mem_assoc "text" res_fields then 330 `Text (TextResourceContents.t_of_yojson (`Assoc res_fields)) 331 else if List.mem_assoc "blob" res_fields then 332 `Blob (BlobResourceContents.t_of_yojson (`Assoc res_fields)) 333 else 334 raise (Json.Of_json ("Invalid resource content", `Assoc res_fields)) 335 | _ -> raise (Json.Of_json ("Missing or invalid 'resource' field", `Assoc fields)) 336 in 337 let annotations = List.assoc_opt "annotations" fields |> Option.map Annotated.annotation_of_yojson in 338 { resource; annotations } 339 | j -> raise (Json.Of_json ("Expected object for EmbeddedResource", j)) 340end 341 342type content = 343 | Text of TextContent.t 344 | Image of ImageContent.t 345 | Audio of AudioContent.t 346 | Resource of EmbeddedResource.t 347 348let yojson_of_content = function 349 | Text t -> TextContent.yojson_of_t t 350 | Image i -> ImageContent.yojson_of_t i 351 | Audio a -> AudioContent.yojson_of_t a 352 | Resource r -> EmbeddedResource.yojson_of_t r 353 354let content_of_yojson = function 355 | `Assoc fields -> 356 (match List.assoc_opt "type" fields with 357 | Some (`String "text") -> Text (TextContent.t_of_yojson (`Assoc fields)) 358 | Some (`String "image") -> Image (ImageContent.t_of_yojson (`Assoc fields)) 359 | Some (`String "audio") -> Audio (AudioContent.t_of_yojson (`Assoc fields)) 360 | Some (`String "resource") -> Resource (EmbeddedResource.t_of_yojson (`Assoc fields)) 361 | _ -> raise (Json.Of_json ("Invalid or missing content type", `Assoc fields))) 362 | j -> raise (Json.Of_json ("Expected object for content", j)) 363 364(* Message types *) 365 366module PromptMessage = struct 367 type t = { 368 role: Role.t; 369 content: content; 370 } 371 372 let yojson_of_t { role; content } = 373 `Assoc [ 374 ("role", Role.yojson_of_t role); 375 ("content", yojson_of_content content); 376 ] 377 378 let t_of_yojson = function 379 | `Assoc fields -> 380 let role = match List.assoc_opt "role" fields with 381 | Some json -> Role.t_of_yojson json 382 | None -> raise (Json.Of_json ("Missing role field", `Assoc fields)) 383 in 384 let content = match List.assoc_opt "content" fields with 385 | Some json -> content_of_yojson json 386 | None -> raise (Json.Of_json ("Missing content field", `Assoc fields)) 387 in 388 { role; content } 389 | j -> raise (Json.Of_json ("Expected object for PromptMessage", j)) 390end 391 392module SamplingMessage = struct 393 type t = { 394 role: Role.t; 395 content: [ `Text of TextContent.t | `Image of ImageContent.t | `Audio of AudioContent.t ]; 396 } 397 398 let yojson_of_t { role; content } = 399 let content_json = match content with 400 | `Text t -> TextContent.yojson_of_t t 401 | `Image i -> ImageContent.yojson_of_t i 402 | `Audio a -> AudioContent.yojson_of_t a 403 in 404 `Assoc [ 405 ("role", Role.yojson_of_t role); 406 ("content", content_json); 407 ] 408 409 let t_of_yojson = function 410 | `Assoc fields -> 411 let role = match List.assoc_opt "role" fields with 412 | Some json -> Role.t_of_yojson json 413 | None -> raise (Json.Of_json ("Missing role field", `Assoc fields)) 414 in 415 let content = match List.assoc_opt "content" fields with 416 | Some (`Assoc content_fields) -> 417 (match List.assoc_opt "type" content_fields with 418 | Some (`String "text") -> `Text (TextContent.t_of_yojson (`Assoc content_fields)) 419 | Some (`String "image") -> `Image (ImageContent.t_of_yojson (`Assoc content_fields)) 420 | Some (`String "audio") -> `Audio (AudioContent.t_of_yojson (`Assoc content_fields)) 421 | _ -> raise (Json.Of_json ("Invalid content type", `Assoc content_fields))) 422 | _ -> raise (Json.Of_json ("Missing or invalid content field", `Assoc fields)) 423 in 424 { role; content } 425 | j -> raise (Json.Of_json ("Expected object for SamplingMessage", j)) 426end 427 428(* Implementation info *) 429 430module Implementation = struct 431 type t = { 432 name: string; 433 version: string; 434 } 435 436 let yojson_of_t { name; version } = 437 `Assoc [ 438 ("name", `String name); 439 ("version", `String version); 440 ] 441 442 let t_of_yojson = function 443 | `Assoc fields -> 444 let name = match List.assoc_opt "name" fields with 445 | Some (`String s) -> s 446 | _ -> raise (Json.Of_json ("Missing or invalid 'name' field", `Assoc fields)) 447 in 448 let version = match List.assoc_opt "version" fields with 449 | Some (`String s) -> s 450 | _ -> raise (Json.Of_json ("Missing or invalid 'version' field", `Assoc fields)) 451 in 452 { name; version } 453 | j -> raise (Json.Of_json ("Expected object for Implementation", j)) 454end 455 456(* JSONRPC Message types *) 457 458module JSONRPCMessage = struct 459 type notification = { 460 method_: string; 461 params: Json.t option; 462 } 463 464 type request = { 465 id: RequestId.t; 466 method_: string; 467 params: Json.t option; 468 progress_token: ProgressToken.t option; 469 } 470 471 type response = { 472 id: RequestId.t; 473 result: Json.t; 474 } 475 476 type error = { 477 id: RequestId.t; 478 code: int; 479 message: string; 480 data: Json.t option; 481 } 482 483 type t = 484 | Notification of notification 485 | Request of request 486 | Response of response 487 | Error of error 488 489 let yojson_of_notification (n: notification) = 490 let assoc = [ 491 ("jsonrpc", `String "2.0"); 492 ("method", `String n.method_); 493 ] in 494 let assoc = match n.params with 495 | Some params -> ("params", params) :: assoc 496 | None -> assoc 497 in 498 `Assoc assoc 499 500 let yojson_of_request (r: request) = 501 let assoc = [ 502 ("jsonrpc", `String "2.0"); 503 ("id", Id.yojson_of_t r.id); 504 ("method", `String r.method_); 505 ] in 506 let assoc = match r.params with 507 | Some params -> 508 let params_json = match params with 509 | `Assoc fields -> 510 let fields = match r.progress_token with 511 | Some token -> 512 let meta = `Assoc [ "progressToken", ProgressToken.yojson_of_t token ] in 513 ("_meta", meta) :: fields 514 | None -> fields 515 in 516 `Assoc fields 517 | _ -> params 518 in 519 ("params", params_json) :: assoc 520 | None -> assoc 521 in 522 `Assoc assoc 523 524 let yojson_of_response (r: response) = 525 `Assoc [ 526 ("jsonrpc", `String "2.0"); 527 ("id", Id.yojson_of_t r.id); 528 ("result", r.result); 529 ] 530 531 let yojson_of_error (e: error) = 532 let error_assoc = [ 533 ("code", `Int e.code); 534 ("message", `String e.message); 535 ] in 536 let error_assoc = match e.data with 537 | Some data -> ("data", data) :: error_assoc 538 | None -> error_assoc 539 in 540 `Assoc [ 541 ("jsonrpc", `String "2.0"); 542 ("id", Id.yojson_of_t e.id); 543 ("error", `Assoc error_assoc); 544 ] 545 546 let yojson_of_t = function 547 | Notification n -> yojson_of_notification n 548 | Request r -> yojson_of_request r 549 | Response r -> yojson_of_response r 550 | Error e -> yojson_of_error e 551 552 let notification_of_yojson = function 553 | `Assoc fields -> 554 let method_ = match List.assoc_opt "method" fields with 555 | Some (`String s) -> s 556 | _ -> raise (Json.Of_json ("Missing or invalid 'method' field", `Assoc fields)) 557 in 558 let params = List.assoc_opt "params" fields in 559 { method_; params } 560 | j -> raise (Json.Of_json ("Expected object for notification", j)) 561 562 let request_of_yojson = function 563 | `Assoc fields -> 564 let id = match List.assoc_opt "id" fields with 565 | Some id_json -> Id.t_of_yojson id_json 566 | _ -> raise (Json.Of_json ("Missing or invalid 'id' field", `Assoc fields)) 567 in 568 let method_ = match List.assoc_opt "method" fields with 569 | Some (`String s) -> s 570 | _ -> raise (Json.Of_json ("Missing or invalid 'method' field", `Assoc fields)) 571 in 572 let params = List.assoc_opt "params" fields in 573 let progress_token = 574 match params with 575 | Some (`Assoc param_fields) -> 576 (match List.assoc_opt "_meta" param_fields with 577 | Some (`Assoc meta_fields) -> 578 (match List.assoc_opt "progressToken" meta_fields with 579 | Some token_json -> Some (ProgressToken.t_of_yojson token_json) 580 | None -> None) 581 | _ -> None) 582 | _ -> None 583 in 584 { id; method_; params; progress_token } 585 | j -> raise (Json.Of_json ("Expected object for request", j)) 586 587 let response_of_yojson = function 588 | `Assoc fields -> 589 let id = match List.assoc_opt "id" fields with 590 | Some id_json -> Id.t_of_yojson id_json 591 | _ -> raise (Json.Of_json ("Missing or invalid 'id' field", `Assoc fields)) 592 in 593 let result = match List.assoc_opt "result" fields with 594 | Some result -> result 595 | _ -> raise (Json.Of_json ("Missing 'result' field", `Assoc fields)) 596 in 597 { id; result } 598 | j -> raise (Json.Of_json ("Expected object for response", j)) 599 600 let error_of_yojson = function 601 | `Assoc fields -> 602 let id = match List.assoc_opt "id" fields with 603 | Some id_json -> Id.t_of_yojson id_json 604 | _ -> raise (Json.Of_json ("Missing or invalid 'id' field", `Assoc fields)) 605 in 606 let error = match List.assoc_opt "error" fields with 607 | Some (`Assoc error_fields) -> error_fields 608 | _ -> raise (Json.Of_json ("Missing or invalid 'error' field", `Assoc fields)) 609 in 610 let code = match List.assoc_opt "code" error with 611 | Some (`Int code) -> code 612 | _ -> raise (Json.Of_json ("Missing or invalid 'code' field in error", `Assoc error)) 613 in 614 let message = match List.assoc_opt "message" error with 615 | Some (`String msg) -> msg 616 | _ -> raise (Json.Of_json ("Missing or invalid 'message' field in error", `Assoc error)) 617 in 618 let data = List.assoc_opt "data" error in 619 { id; code; message; data } 620 | j -> raise (Json.Of_json ("Expected object for error", j)) 621 622 let t_of_yojson json = 623 match json with 624 | `Assoc fields -> 625 let _jsonrpc = match List.assoc_opt "jsonrpc" fields with 626 | Some (`String "2.0") -> () 627 | _ -> raise (Json.Of_json ("Missing or invalid 'jsonrpc' field", json)) 628 in 629 if List.mem_assoc "method" fields then 630 if List.mem_assoc "id" fields then 631 Request (request_of_yojson json) 632 else 633 Notification (notification_of_yojson json) 634 else if List.mem_assoc "result" fields then 635 Response (response_of_yojson json) 636 else if List.mem_assoc "error" fields then 637 Error (error_of_yojson json) 638 else 639 raise (Json.Of_json ("Invalid JSONRPC message format", json)) 640 | j -> raise (Json.Of_json ("Expected object for JSONRPC message", j)) 641 642 let create_notification ?(params=None) ~method_ () = 643 Notification { method_; params } 644 645 let create_request ?(params=None) ?(progress_token=None) ~id ~method_ () = 646 Request { id; method_; params; progress_token } 647 648 let create_response ~id ~result = 649 Response { id; result } 650 651 let create_error ~id ~code ~message ?(data=None) () = 652 Error { id; code; message; data } 653end 654 655(* MCP-specific request/response types *) 656 657module Initialize = struct 658 module Request = struct 659 type t = { 660 capabilities: Json.t; (* ClientCapabilities *) 661 client_info: Implementation.t; 662 protocol_version: string; 663 } 664 665 let yojson_of_t { capabilities; client_info; protocol_version } = 666 `Assoc [ 667 ("capabilities", capabilities); 668 ("clientInfo", Implementation.yojson_of_t client_info); 669 ("protocolVersion", `String protocol_version); 670 ] 671 672 let t_of_yojson = function 673 | `Assoc fields -> 674 let capabilities = match List.assoc_opt "capabilities" fields with 675 | Some json -> json 676 | None -> raise (Json.Of_json ("Missing capabilities field", `Assoc fields)) 677 in 678 let client_info = match List.assoc_opt "clientInfo" fields with 679 | Some json -> Implementation.t_of_yojson json 680 | None -> raise (Json.Of_json ("Missing clientInfo field", `Assoc fields)) 681 in 682 let protocol_version = match List.assoc_opt "protocolVersion" fields with 683 | Some (`String s) -> s 684 | _ -> raise (Json.Of_json ("Missing or invalid protocolVersion field", `Assoc fields)) 685 in 686 { capabilities; client_info; protocol_version } 687 | j -> raise (Json.Of_json ("Expected object for InitializeRequest", j)) 688 689 let create ~capabilities ~client_info ~protocol_version = 690 { capabilities; client_info; protocol_version } 691 692 let to_jsonrpc ~id t = 693 let params = yojson_of_t t in 694 JSONRPCMessage.create_request ~id ~method_:"initialize" ~params:(Some params) () 695 end 696 697 module Result = struct 698 type t = { 699 capabilities: Json.t; (* ServerCapabilities *) 700 server_info: Implementation.t; 701 protocol_version: string; 702 instructions: string option; 703 meta: Json.t option; 704 } 705 706 let yojson_of_t { capabilities; server_info; protocol_version; instructions; meta } = 707 let assoc = [ 708 ("capabilities", capabilities); 709 ("serverInfo", Implementation.yojson_of_t server_info); 710 ("protocolVersion", `String protocol_version); 711 ] in 712 let assoc = match instructions with 713 | Some instr -> ("instructions", `String instr) :: assoc 714 | None -> assoc 715 in 716 let assoc = match meta with 717 | Some meta -> ("_meta", meta) :: assoc 718 | None -> assoc 719 in 720 `Assoc assoc 721 722 let t_of_yojson = function 723 | `Assoc fields -> 724 let capabilities = match List.assoc_opt "capabilities" fields with 725 | Some json -> json 726 | None -> raise (Json.Of_json ("Missing capabilities field", `Assoc fields)) 727 in 728 let server_info = match List.assoc_opt "serverInfo" fields with 729 | Some json -> Implementation.t_of_yojson json 730 | None -> raise (Json.Of_json ("Missing serverInfo field", `Assoc fields)) 731 in 732 let protocol_version = match List.assoc_opt "protocolVersion" fields with 733 | Some (`String s) -> s 734 | _ -> raise (Json.Of_json ("Missing or invalid protocolVersion field", `Assoc fields)) 735 in 736 let instructions = match List.assoc_opt "instructions" fields with 737 | Some (`String s) -> Some s 738 | _ -> None 739 in 740 let meta = List.assoc_opt "_meta" fields in 741 { capabilities; server_info; protocol_version; instructions; meta } 742 | j -> raise (Json.Of_json ("Expected object for InitializeResult", j)) 743 744 let create ~capabilities ~server_info ~protocol_version ?instructions ?meta () = 745 { capabilities; server_info; protocol_version; instructions; meta } 746 747 let to_jsonrpc ~id t = 748 JSONRPCMessage.create_response ~id ~result:(yojson_of_t t) 749 end 750end 751 752module Initialized = struct 753 module Notification = struct 754 type t = { 755 meta: Json.t option; 756 } 757 758 let yojson_of_t { meta } = 759 let assoc = [] in 760 let assoc = match meta with 761 | Some meta -> ("_meta", meta) :: assoc 762 | None -> assoc 763 in 764 `Assoc assoc 765 766 let t_of_yojson = function 767 | `Assoc fields -> 768 let meta = List.assoc_opt "_meta" fields in 769 { meta } 770 | j -> raise (Json.Of_json ("Expected object for InitializedNotification", j)) 771 772 let create ?meta () = { meta } 773 774 let to_jsonrpc t = 775 let params = match yojson_of_t t with 776 | `Assoc [] -> None 777 | json -> Some json 778 in 779 JSONRPCMessage.create_notification ~method_:"notifications/initialized" ~params () 780 end 781end 782 783(* Export the main interface for using the MCP protocol *) 784 785let parse_message json = 786 JSONRPCMessage.t_of_yojson json 787 788let create_notification = JSONRPCMessage.create_notification 789let create_request = JSONRPCMessage.create_request 790let create_response = JSONRPCMessage.create_response 791let create_error = JSONRPCMessage.create_error