Model Context Protocol in OCaml
1(** MCP - Model Context Protocol implementation 2 3 The Model Context Protocol (MCP) is a standardized protocol for AI agents to exchange context 4 with servers. This module provides the core OCaml implementation of MCP including 5 all message types, content representations, and serialization functionality. 6 7 MCP Architecture: 8 - Uses JSON-RPC 2.0 as its underlying message format with UTF-8 encoding 9 - Follows a client-server model where clients (often LLM-integrated applications) communicate with MCP servers 10 - Supports multiple transport methods including stdio and streamable HTTP 11 - Implements a three-phase connection lifecycle: initialization, operation, and shutdown 12 - Provides capability negotiation during initialization to determine available features 13 - Offers four primary context exchange mechanisms: 14 1. Resources: Server-exposed data that provides context to language models 15 2. Tools: Server-exposed functionality that can be invoked by language models 16 3. Prompts: Server-defined templates for structuring interactions with models 17 4. Sampling: Client-exposed ability to generate completions from LLMs 18 - Supports multimodal content types: text, images, audio, and embedded resources 19 - Includes standardized error handling with defined error codes 20 21 This implementation follows Protocol Revision 2025-03-26. 22*) 23 24open Jsonrpc 25 26(** Utility functions for JSON parsing *) 27module Util : sig 28 (** Extract a string field from JSON object or raise an error 29 @param fields Assoc list of fields from JSON object 30 @param name Field name to extract 31 @param json Original JSON for error context 32 @return The string value of the field 33 @raise Json.Of_json if the field is missing or not a string 34 *) 35 val get_string_field : (string * Json.t) list -> string -> Json.t -> string 36 37 (** Extract an optional string field from JSON object 38 @param fields Assoc list of fields from JSON object 39 @param name Field name to extract 40 @return Some string if present and a string, None if missing 41 @raise Json.Of_json if the field exists but is not a string 42 *) 43 val get_optional_string_field : (string * Json.t) list -> string -> string option 44 45 (** Extract an int field from JSON object or raise an error 46 @param fields Assoc list of fields from JSON object 47 @param name Field name to extract 48 @param json Original JSON for error context 49 @return The int value of the field 50 @raise Json.Of_json if the field is missing or not an int 51 *) 52 val get_int_field : (string * Json.t) list -> string -> Json.t -> int 53 54 (** Extract a float field from JSON object or raise an error 55 @param fields Assoc list of fields from JSON object 56 @param name Field name to extract 57 @param json Original JSON for error context 58 @return The float value of the field 59 @raise Json.Of_json if the field is missing or not a float 60 *) 61 val get_float_field : (string * Json.t) list -> string -> Json.t -> float 62 63 (** Extract a boolean field from JSON object or raise an error 64 @param fields Assoc list of fields from JSON object 65 @param name Field name to extract 66 @param json Original JSON for error context 67 @return The boolean value of the field 68 @raise Json.Of_json if the field is missing or not a boolean 69 *) 70 val get_bool_field : (string * Json.t) list -> string -> Json.t -> bool 71 72 (** Extract an object field from JSON object or raise an error 73 @param fields Assoc list of fields from JSON object 74 @param name Field name to extract 75 @param json Original JSON for error context 76 @return The object as an assoc list 77 @raise Json.Of_json if the field is missing or not an object 78 *) 79 val get_object_field : (string * Json.t) list -> string -> Json.t -> (string * Json.t) list 80 81 (** Extract a list field from JSON object or raise an error 82 @param fields Assoc list of fields from JSON object 83 @param name Field name to extract 84 @param json Original JSON for error context 85 @return The list items 86 @raise Json.Of_json if the field is missing or not a list 87 *) 88 val get_list_field : (string * Json.t) list -> string -> Json.t -> Json.t list 89 90 (** Verify a specific string value in a field 91 @param fields Assoc list of fields from JSON object 92 @param name Field name to check 93 @param expected_value The expected string value 94 @param json Original JSON for error context 95 @raise Json.Of_json if the field is missing or not equal to expected_value 96 *) 97 val verify_string_field : (string * Json.t) list -> string -> string -> Json.t -> unit 98end 99 100(** Error codes for JSON-RPC *) 101module ErrorCode : sig 102 (** Standard JSON-RPC error codes with MCP-specific additions *) 103 type t = 104 | ParseError (** -32700 - Invalid JSON *) 105 | InvalidRequest (** -32600 - Invalid JSON-RPC request *) 106 | MethodNotFound (** -32601 - Method not available *) 107 | InvalidParams (** -32602 - Invalid method parameters *) 108 | InternalError (** -32603 - Internal JSON-RPC error *) 109 | ResourceNotFound (** -32002 - Custom MCP error: requested resource not found *) 110 | AuthRequired (** -32001 - Custom MCP error: authentication required *) 111 | CustomError of int (** For any other error codes *) 112 113 (** Convert the error code to its integer representation 114 @param code The error code to convert 115 @return The integer error code as defined in the JSON-RPC spec 116 *) 117 val to_int : t -> int 118 119 (** Get error message for standard error codes 120 @param code The error code to get message for 121 @return A standard message for the error code 122 *) 123 val to_message : t -> string 124end 125 126(** MCP Protocol Methods - Algebraic data type representing all MCP methods *) 127module Method : sig 128 (** Method type representing all MCP protocol methods *) 129 type t = 130 (* Initialization and lifecycle methods *) 131 | Initialize (** Start the MCP lifecycle *) 132 | Initialized (** Signal readiness after initialization *) 133 134 (* Resource methods *) 135 | ResourcesList (** Discover available resources *) 136 | ResourcesRead (** Retrieve resource contents *) 137 | ResourcesTemplatesList (** List available resource templates *) 138 | ResourcesSubscribe (** Subscribe to resource changes *) 139 | ResourcesListChanged (** Resource list has changed *) 140 | ResourcesUpdated (** Resource has been updated *) 141 142 (* Tool methods *) 143 | ToolsList (** Discover available tools *) 144 | ToolsCall (** Invoke a tool *) 145 | ToolsListChanged (** Tool list has changed *) 146 147 (* Prompt methods *) 148 | PromptsList (** Discover available prompts *) 149 | PromptsGet (** Retrieve a prompt template with arguments *) 150 | PromptsListChanged (** Prompt list has changed *) 151 152 (* Progress notifications *) 153 | Progress (** Progress update for long-running operations *) 154 155 (** Convert method type to string representation 156 @param meth The method to convert 157 @return The string representation of the method (e.g., "initialize", "resources/list") 158 *) 159 val to_string : t -> string 160 161 (** Convert string to method type 162 @param s The string representation of the method 163 @return The corresponding method type 164 @raise Failure if the string is not a valid MCP method 165 *) 166 val of_string : string -> t 167end 168 169 170(** Common types *) 171 172(** Roles for conversation participants *) 173module Role : sig 174 (** Role represents conversation participants in MCP messages. 175 Roles can be either 'user' or 'assistant', determining the 176 source of each message in a conversation. *) 177 type t = [ `User | `Assistant ] 178 include Json.Jsonable.S with type t := t 179end 180 181(** Progress tokens for long-running operations *) 182module ProgressToken : sig 183 (** Progress tokens identify long-running operations and enable 184 servers to provide progress updates to clients. This is used 185 to track operations that may take significant time to complete. *) 186 type t = [ `String of string | `Int of int ] 187 include Json.Jsonable.S with type t := t 188end 189 190(** Request IDs *) 191module RequestId : sig 192 (** Request IDs uniquely identify JSON-RPC requests, allowing responses 193 to be correlated with their originating requests. They can be either 194 string or integer values. *) 195 type t = [ `String of string | `Int of int ] 196 include Json.Jsonable.S with type t := t 197end 198 199(** Cursors for pagination *) 200module Cursor : sig 201 (** Cursors enable pagination in list operations for resources, tools, and prompts. 202 When a server has more items than can be returned in a single response, 203 it provides a cursor for the client to retrieve subsequent pages. *) 204 type t = string 205 include Json.Jsonable.S with type t := t 206end 207 208(** Annotations for objects *) 209module Annotated : sig 210 (** Annotations provide metadata for content objects, allowing 211 role-specific targeting and priority settings. *) 212 type t = { 213 annotations: annotation option; 214 } 215 and annotation = { 216 audience: Role.t list option; 217 (** Optional list of roles that should receive this content *) 218 priority: float option; 219 (** Optional priority value for this content *) 220 } 221 include Json.Jsonable.S with type t := t 222end 223 224(** Text content - Core textual message representation in MCP *) 225module TextContent : sig 226 (** TextContent represents plain text messages in MCP conversations. 227 This is the most common content type used for natural language interactions 228 between users and assistants. Text content is used in prompts, tool results, 229 and model responses. 230 231 In JSON-RPC, this is represented as: 232 {v 233 { 234 "type": "text", 235 "text": "The text content of the message" 236 } 237 v} 238 239 For security, implementations must sanitize text content to prevent 240 injection attacks or unauthorized access to resources. *) 241 type t = { 242 text: string; 243 (** The actual text content as a UTF-8 encoded string *) 244 annotations: Annotated.annotation option; 245 (** Optional annotations for audience targeting and priority. 246 Annotations can restrict content visibility to specific roles (user/assistant) 247 and indicate relative importance of different content elements. *) 248 } 249 include Json.Jsonable.S with type t := t 250end 251 252(** Image content - Visual data representation in MCP *) 253module ImageContent : sig 254 (** ImageContent enables including visual information in MCP messages, 255 supporting multimodal interactions where visual context is important. 256 257 Images can be used in several scenarios: 258 - As user inputs for visual understanding tasks 259 - As context for generating descriptions or analysis 260 - As outputs from tools that generate visualizations 261 - As part of prompt templates with visual components 262 263 In JSON-RPC, this is represented as: 264 {v 265 { 266 "type": "image", 267 "data": "base64-encoded-image-data", 268 "mimeType": "image/png" 269 } 270 v} 271 272 The data MUST be base64-encoded to ensure safe transmission in JSON. 273 Common mime types include image/png, image/jpeg, image/gif, and image/svg+xml. *) 274 type t = { 275 data: string; 276 (** Base64-encoded image data. All binary image data must be encoded using 277 standard base64 encoding (RFC 4648) to safely transmit within JSON. *) 278 mime_type: string; 279 (** MIME type of the image (e.g., "image/png", "image/jpeg", "image/gif", "image/svg+xml"). 280 This field is required and must accurately represent the image format to ensure 281 proper handling by clients. *) 282 annotations: Annotated.annotation option; 283 (** Optional annotations for audience targeting and priority. 284 Annotations can restrict content visibility to specific roles (user/assistant) 285 and indicate relative importance of different content elements. *) 286 } 287 include Json.Jsonable.S with type t := t 288end 289 290(** Audio content - Sound data representation in MCP *) 291module AudioContent : sig 292 (** AudioContent enables including audio information in MCP messages, 293 supporting multimodal interactions where audio context is important. 294 295 Audio can be used in several scenarios: 296 - As user inputs for speech recognition or audio analysis 297 - As context for transcription or sound classification tasks 298 - As outputs from tools that generate audio samples 299 - As part of prompt templates with audio components 300 301 In JSON-RPC, this is represented as: 302 {v 303 { 304 "type": "audio", 305 "data": "base64-encoded-audio-data", 306 "mimeType": "audio/wav" 307 } 308 v} 309 310 The data MUST be base64-encoded to ensure safe transmission in JSON. 311 Common mime types include audio/wav, audio/mp3, audio/ogg, and audio/mpeg. *) 312 type t = { 313 data: string; 314 (** Base64-encoded audio data. All binary audio data must be encoded using 315 standard base64 encoding (RFC 4648) to safely transmit within JSON. *) 316 mime_type: string; 317 (** MIME type of the audio (e.g., "audio/wav", "audio/mp3", "audio/ogg", "audio/mpeg"). 318 This field is required and must accurately represent the audio format to ensure 319 proper handling by clients. *) 320 annotations: Annotated.annotation option; 321 (** Optional annotations for audience targeting and priority. 322 Annotations can restrict content visibility to specific roles (user/assistant) 323 and indicate relative importance of different content elements. *) 324 } 325 include Json.Jsonable.S with type t := t 326end 327 328(** Base resource contents - Core resource metadata in MCP *) 329module ResourceContents : sig 330 (** ResourceContents provides basic metadata for resources in MCP. 331 332 Resources are server-exposed data that provides context to language models, 333 such as files, database schemas, or application-specific information. 334 Each resource is uniquely identified by a URI. 335 336 The MCP resources architecture is designed to be application-driven, with 337 host applications determining how to incorporate context based on their needs. 338 339 In the protocol, resources are discovered via the 'resources/list' endpoint 340 and retrieved via the 'resources/read' endpoint. Servers that support resources 341 must declare the 'resources' capability during initialization. *) 342 type t = { 343 uri: string; 344 (** URI that uniquely identifies the resource. 345 346 Resources use standard URI schemes including: 347 - file:// - For filesystem-like resources 348 - https:// - For web-accessible resources 349 - git:// - For version control integration 350 351 The URI serves as a stable identifier even if the underlying content changes. *) 352 mime_type: string option; 353 (** Optional MIME type of the resource content to aid in client rendering. 354 Common MIME types include text/plain, application/json, image/png, etc. 355 For directories, the XDG MIME type inode/directory may be used. *) 356 } 357 include Json.Jsonable.S with type t := t 358end 359 360(** Text resource contents - Textual resource data *) 361module TextResourceContents : sig 362 (** TextResourceContents represents a text-based resource in MCP. 363 364 Text resources are used for sharing code snippets, documentation, logs, 365 configuration files, and other textual information with language models. 366 367 The server handles access control and security, ensuring that only 368 authorized resources are shared with clients. 369 370 In JSON-RPC, this is represented as: 371 {v 372 { 373 "uri": "file:///example.txt", 374 "mimeType": "text/plain", 375 "text": "Resource content" 376 } 377 v} 378 *) 379 type t = { 380 uri: string; 381 (** URI that uniquely identifies the resource. 382 This URI can be referenced in subsequent requests to fetch updates. *) 383 text: string; 384 (** The actual text content of the resource as a UTF-8 encoded string. 385 This may be sanitized by the server to remove sensitive information. *) 386 mime_type: string option; 387 (** Optional MIME type of the text content to aid in client rendering. 388 Common text MIME types include: text/plain, text/markdown, text/x-python, 389 application/json, text/html, text/csv, etc. *) 390 } 391 include Json.Jsonable.S with type t := t 392end 393 394(** Binary resource contents - Binary resource data *) 395module BlobResourceContents : sig 396 (** BlobResourceContents represents a binary resource in MCP. 397 398 Binary resources allow sharing non-textual data like images, audio files, 399 PDFs, and other binary formats with language models that support processing 400 such content. 401 402 In JSON-RPC, this is represented as: 403 {v 404 { 405 "uri": "file:///example.png", 406 "mimeType": "image/png", 407 "blob": "base64-encoded-data" 408 } 409 v} 410 411 Binary data MUST be properly base64-encoded to ensure safe transmission 412 in JSON payloads. *) 413 type t = { 414 uri: string; 415 (** URI that uniquely identifies the resource. 416 This URI can be referenced in subsequent requests to fetch updates. *) 417 blob: string; 418 (** Base64-encoded binary data using standard base64 encoding (RFC 4648). 419 This encoding ensures that binary data can be safely transmitted in JSON. *) 420 mime_type: string option; 421 (** Optional MIME type of the binary content to aid in client rendering. 422 Common binary MIME types include: image/png, image/jpeg, application/pdf, 423 audio/wav, video/mp4, application/octet-stream, etc. *) 424 } 425 include Json.Jsonable.S with type t := t 426end 427 428(** Embedded resource - Resource included directly in messages *) 429module EmbeddedResource : sig 430 (** EmbeddedResource allows referencing server-side resources directly 431 in MCP messages, enabling seamless incorporation of managed content. 432 433 Embedded resources can be included in: 434 - Tool results to provide rich context 435 - Prompt templates to include reference materials 436 - Messages to provide additional context to language models 437 438 In contrast to direct content (TextContent, ImageContent, AudioContent), 439 embedded resources have the advantage of being persistently stored on the server 440 with a stable URI, allowing later retrieval and updates through the resources API. 441 442 For example, a tool might return an embedded resource containing a chart or 443 a large dataset that the client can later reference or update. *) 444 type t = { 445 resource: [ `Text of TextResourceContents.t | `Blob of BlobResourceContents.t ]; 446 (** The resource content, either as text or binary blob. *) 447 annotations: Annotated.annotation option; 448 (** Optional annotations for audience targeting and priority. 449 Annotations can restrict resource visibility to specific roles (user/assistant) 450 and indicate relative importance of different content elements. *) 451 } 452 include Json.Jsonable.S with type t := t 453end 454 455(** Content type used in messages - Unified multimodal content representation in MCP *) 456type content = 457 | Text of TextContent.t (** Text content for natural language messages. This is the most common content type for user-assistant interactions. *) 458 | Image of ImageContent.t (** Image content for visual data. Used for sharing visual context in multimodal conversations. *) 459 | Audio of AudioContent.t (** Audio content for audio data. Used for sharing audio context in multimodal conversations. *) 460 | Resource of EmbeddedResource.t (** Resource content for referencing server-side resources. Used for incorporating managed server content with stable URIs. *) 461 462(** Convert content to Yojson representation 463 @param content The content to convert 464 @return JSON representation of the content 465*) 466val yojson_of_content : content -> Json.t 467 468(** Convert Yojson representation to content 469 @param json JSON representation of content 470 @return Parsed content object 471*) 472val content_of_yojson : Json.t -> content 473 474(** Message for prompts - Template messages in the MCP prompts feature *) 475module PromptMessage : sig 476 (** PromptMessage represents a message in an MCP prompt template, 477 containing a role and content which can be customized with arguments. 478 479 Prompt messages are part of prompt templates exposed by servers through 480 the prompts/get endpoint. They define structured conversation templates 481 that can be instantiated with user-provided arguments. 482 483 The prompt feature is designed to be user-controlled, with prompts typically 484 exposed through UI elements like slash commands that users can explicitly select. 485 486 In JSON-RPC, prompt messages are represented as: 487 {v 488 { 489 "role": "user", 490 "content": { 491 "type": "text", 492 "text": "Please review this code: ${code}" 493 } 494 } 495 v} 496 497 Where $code would be replaced with a user-provided argument. *) 498 type t = { 499 role: Role.t; 500 (** The role of the message sender (user or assistant). 501 Prompt templates typically alternate between user and assistant messages 502 to create a conversation structure. *) 503 content: content; 504 (** The message content, which can be text, image, audio, or resource. 505 This unified content type supports rich multimodal prompts. *) 506 } 507 include Json.Jsonable.S with type t := t 508end 509 510(** Message for sampling - Messages used in LLM completion requests *) 511module SamplingMessage : sig 512 (** SamplingMessage represents a message in an MCP sampling request, 513 used for AI model generation based on a prompt. 514 515 The sampling feature allows clients to expose language model capabilities 516 to servers, enabling servers to request completions from the client's LLM. 517 This is effectively the reverse of the normal MCP flow, with the server 518 requesting generative capabilities from the client. 519 520 Sampling messages differ from prompt messages in that they don't support 521 embedded resources, as they represent the actual context window being 522 sent to the LLM rather than template definitions. 523 524 Clients that support sampling must declare the 'sampling' capability 525 during initialization. *) 526 type t = { 527 role: Role.t; 528 (** The role of the message sender (user or assistant). 529 Typically, a sampling request will contain multiple messages 530 representing a conversation history, with alternating roles. *) 531 content: [ `Text of TextContent.t | `Image of ImageContent.t | `Audio of AudioContent.t ]; 532 (** The message content, restricted to text, image, or audio (no resources). 533 Resources are not included since sampling messages represent the 534 actual context window for the LLM, not template definitions. *) 535 } 536 include Json.Jsonable.S with type t := t 537end 538 539(** Implementation information *) 540module Implementation : sig 541 (** Implementation provides metadata about client and server implementations, 542 used during the initialization phase to identify each party. *) 543 type t = { 544 name: string; 545 (** Name of the implementation *) 546 version: string; 547 (** Version of the implementation *) 548 } 549 include Json.Jsonable.S with type t := t 550end 551 552(** JSONRPC message types - Core message protocol for MCP 553 554 MCP uses JSON-RPC 2.0 as its underlying messaging protocol. 555 All MCP messages are encoded as JSON-RPC 2.0 messages with UTF-8 encoding, 556 following the standard JSON-RPC message formats with some MCP-specific extensions. 557 558 MCP defines four message types: 559 1. Notifications: One-way messages that don't expect a response 560 2. Requests: Messages that expect a corresponding response 561 3. Responses: Replies to requests with successful results 562 4. Errors: Replies to requests with error information 563 564 These can be transported over multiple transport mechanisms: 565 - stdio: Communication over standard input/output 566 - Streamable HTTP: HTTP POST/GET with SSE for server streaming 567 - Custom transports: Implementation-specific transports 568 569 Messages may be sent individually or as part of a JSON-RPC batch. 570*) 571module JSONRPCMessage : sig 572 (** Notification represents a JSON-RPC notification (one-way message without a response). 573 574 Notifications are used for events that don't require a response, such as: 575 - The 'initialized' notification completing initialization 576 - Resource change notifications 577 - Progress updates for long-running operations 578 - List changed notifications for tools, resources, and prompts 579 580 In JSON-RPC, notifications are identified by the absence of an 'id' field: 581 {v 582 { 583 "jsonrpc": "2.0", 584 "method": "notifications/resources/updated", 585 "params": { 586 "uri": "file:///project/src/main.rs" 587 } 588 } 589 v} 590 *) 591 type notification = { 592 meth: Method.t; 593 (** Method for the notification, using the Method.t type to ensure type safety. 594 Examples: Method.Initialized, Method.ResourcesUpdated *) 595 params: Json.t option; 596 (** Optional parameters for the notification as arbitrary JSON. 597 The structure depends on the specific notification method. *) 598 } 599 600 (** Request represents a JSON-RPC request that expects a response. 601 602 Requests are used for operations that require a response, such as: 603 - Initialization 604 - Listing resources, tools, or prompts 605 - Reading resources 606 - Calling tools 607 - Getting prompts 608 609 In JSON-RPC, requests include an 'id' field that correlates with the response: 610 {v 611 { 612 "jsonrpc": "2.0", 613 "id": 1, 614 "method": "resources/read", 615 "params": { 616 "uri": "file:///project/src/main.rs" 617 } 618 } 619 v} 620 *) 621 type request = { 622 id: RequestId.t; 623 (** Unique identifier for the request, which will be echoed in the response. 624 This can be a string or integer and should be unique within the session. *) 625 meth: Method.t; 626 (** Method for the request, using the Method.t type to ensure type safety. 627 Examples: Method.Initialize, Method.ResourcesRead, Method.ToolsCall *) 628 params: Json.t option; 629 (** Optional parameters for the request as arbitrary JSON. 630 The structure depends on the specific request method. *) 631 progress_token: ProgressToken.t option; 632 (** Optional progress token for long-running operations. 633 If provided, the server can send progress notifications using this token 634 to inform the client about the operation's status. *) 635 } 636 637 (** Response represents a successful JSON-RPC response to a request. 638 639 Responses are sent in reply to requests and contain the successful result. 640 Each response must include the same ID as its corresponding request. 641 642 In JSON-RPC, responses include the 'id' field matching the request: 643 {v 644 { 645 "jsonrpc": "2.0", 646 "id": 1, 647 "result": { 648 "contents": [ 649 { 650 "uri": "file:///project/src/main.rs", 651 "mimeType": "text/x-rust", 652 "text": "fn main() {\n println!(\"Hello world!\");\n}" 653 } 654 ] 655 } 656 } 657 v} 658 *) 659 type response = { 660 id: RequestId.t; 661 (** ID matching the original request, allowing clients to correlate 662 responses with their originating requests, especially important 663 when multiple requests are in flight. *) 664 result: Json.t; 665 (** Result of the successful request as arbitrary JSON. 666 The structure depends on the specific request method that was called. *) 667 } 668 669 (** Error represents an error response to a JSON-RPC request. 670 671 Errors are sent in reply to requests when processing fails. 672 Each error must include the same ID as its corresponding request. 673 674 MCP defines several standard error codes: 675 - Standard JSON-RPC errors (-32700 to -32603) 676 - MCP-specific errors (-32002 for resource not found, etc.) 677 678 In JSON-RPC, errors follow this structure: 679 {v 680 { 681 "jsonrpc": "2.0", 682 "id": 1, 683 "error": { 684 "code": -32002, 685 "message": "Resource not found", 686 "data": { 687 "uri": "file:///nonexistent.txt" 688 } 689 } 690 } 691 v} 692 *) 693 type error = { 694 id: RequestId.t; 695 (** ID matching the original request, allowing clients to correlate 696 errors with their originating requests. *) 697 code: int; 698 (** Error code indicating the type of error, following the JSON-RPC standard. 699 Common codes include: 700 - -32700: Parse error 701 - -32600: Invalid request 702 - -32601: Method not found 703 - -32602: Invalid params 704 - -32603: Internal error 705 - -32002: Resource not found (MCP-specific) 706 - -32001: Authentication required (MCP-specific) *) 707 message: string; 708 (** Human-readable error message describing the issue. 709 This should be concise but informative enough for debugging. *) 710 data: Json.t option; 711 (** Optional additional error data as arbitrary JSON. 712 This can provide more context about the error, such as which 713 resource wasn't found or which parameter was invalid. *) 714 } 715 716 (** Union type for all JSON-RPC message kinds, providing a single type 717 that can represent any MCP message. *) 718 type t = 719 | Notification of notification 720 | Request of request 721 | Response of response 722 | Error of error 723 724 (** Convert notification to Yojson representation 725 @param notification The notification to convert 726 @return JSON representation of the notification 727 *) 728 val yojson_of_notification : notification -> Json.t 729 730 (** Convert request to Yojson representation 731 @param request The request to convert 732 @return JSON representation of the request 733 *) 734 val yojson_of_request : request -> Json.t 735 736 (** Convert response to Yojson representation 737 @param response The response to convert 738 @return JSON representation of the response 739 *) 740 val yojson_of_response : response -> Json.t 741 742 (** Convert error to Yojson representation 743 @param error The error to convert 744 @return JSON representation of the error 745 *) 746 val yojson_of_error : error -> Json.t 747 748 (** Convert any message to Yojson representation 749 @param message The message to convert 750 @return JSON representation of the message 751 *) 752 val yojson_of_t : t -> Json.t 753 754 (** Convert Yojson representation to notification 755 @param json JSON representation of a notification 756 @return Parsed notification object 757 @raise Parse error if the JSON is not a valid notification 758 *) 759 val notification_of_yojson : Json.t -> notification 760 761 (** Convert Yojson representation to request 762 @param json JSON representation of a request 763 @return Parsed request object 764 @raise Parse error if the JSON is not a valid request 765 *) 766 val request_of_yojson : Json.t -> request 767 768 (** Convert Yojson representation to response 769 @param json JSON representation of a response 770 @return Parsed response object 771 @raise Parse error if the JSON is not a valid response 772 *) 773 val response_of_yojson : Json.t -> response 774 775 (** Convert Yojson representation to error 776 @param json JSON representation of an error 777 @return Parsed error object 778 @raise Parse error if the JSON is not a valid error 779 *) 780 val error_of_yojson : Json.t -> error 781 782 (** Convert Yojson representation to any message 783 @param json JSON representation of any message type 784 @return Parsed message object 785 @raise Parse error if the JSON is not a valid message 786 *) 787 val t_of_yojson : Json.t -> t 788 789 (** Create a new notification message 790 @param params Optional parameters for the notification 791 @param meth Method name for the notification 792 @return A new JSON-RPC notification message 793 *) 794 val create_notification : ?params:Json.t option -> meth:Method.t -> unit -> t 795 796 (** Create a new request message 797 @param params Optional parameters for the request 798 @param progress_token Optional progress token for long-running operations 799 @param id Unique identifier for the request 800 @param meth Method name for the request 801 @return A new JSON-RPC request message 802 *) 803 val create_request : ?params:Json.t option -> ?progress_token:ProgressToken.t option -> id:RequestId.t -> meth:Method.t -> unit -> t 804 805 (** Create a new response message 806 @param id ID matching the original request 807 @param result Result of the successful request 808 @return A new JSON-RPC response message 809 *) 810 val create_response : id:RequestId.t -> result:Json.t -> t 811 812 (** Create a new error message 813 @param id ID matching the original request 814 @param code Error code indicating the type of error 815 @param message Human-readable error message 816 @param data Optional additional error data 817 @return A new JSON-RPC error message 818 *) 819 val create_error : id:RequestId.t -> code:int -> message:string -> ?data:Json.t option -> unit -> t 820end 821 822(** Initialize request/response - The first phase of the MCP lifecycle 823 824 The initialization phase is the mandatory first interaction between client and server. 825 During this phase, the protocol version is negotiated and capabilities are exchanged 826 to determine which optional features will be available during the session. 827 828 This follows a strict sequence: 829 1. Client sends an InitializeRequest containing its capabilities and protocol version 830 2. Server responds with an InitializeResult containing its capabilities and protocol version 831 3. Client sends an InitializedNotification to signal it's ready for normal operations 832 833 The Initialize module handles steps 1 and 2 of this process. 834*) 835module Initialize : sig 836 (** Initialize request *) 837 module Request : sig 838 (** InitializeRequest starts the MCP lifecycle, negotiating capabilities 839 and protocol versions between client and server. This is always the first 840 message sent by the client and MUST NOT be part of a JSON-RPC batch. 841 842 The client SHOULD send the latest protocol version it supports. If the server 843 does not support this version, it will respond with a version it does support, 844 and the client must either use that version or disconnect. *) 845 type t = { 846 capabilities: Json.t; (** ClientCapabilities that define supported optional features. 847 This includes which optional protocol features the client supports, 848 such as 'roots' (filesystem access), 'sampling' (LLM generation), 849 and any experimental features. *) 850 client_info: Implementation.t; 851 (** Client implementation details (name and version) used for identification 852 and debugging. Helps servers understand which client they're working with. *) 853 protocol_version: string; 854 (** MCP protocol version supported by the client, formatted as YYYY-MM-DD 855 according to the MCP versioning scheme. Example: "2025-03-26" *) 856 } 857 include Json.Jsonable.S with type t := t 858 859 (** Create a new initialization request 860 @param capabilities Client capabilities that define supported optional features 861 @param client_info Client implementation details 862 @param protocol_version MCP protocol version supported by the client 863 @return A new initialization request 864 *) 865 val create : capabilities:Json.t -> client_info:Implementation.t -> protocol_version:string -> t 866 867 (** Convert to JSON-RPC message 868 @param id Unique request identifier 869 @param t Initialization request 870 @return JSON-RPC message containing the initialization request 871 *) 872 val to_jsonrpc : id:RequestId.t -> t -> JSONRPCMessage.t 873 end 874 875 (** Initialize result *) 876 module Result : sig 877 (** InitializeResult is the server's response to an initialization request, 878 completing capability negotiation and establishing the protocol version. 879 880 After receiving this message, the client must send an InitializedNotification. 881 The server should not send any requests other than pings and logging before 882 receiving the initialized notification. *) 883 type t = { 884 capabilities: Json.t; (** ServerCapabilities that define supported optional features. 885 This declares which server features are available, including: 886 - prompts: Server provides prompt templates 887 - resources: Server provides readable resources 888 - tools: Server exposes callable tools 889 - logging: Server emits structured log messages 890 891 Each capability may have sub-capabilities like: 892 - listChanged: Server will notify when available items change 893 - subscribe: Clients can subscribe to individual resources *) 894 server_info: Implementation.t; 895 (** Server implementation details (name and version) used for identification 896 and debugging. Helps clients understand which server they're working with. *) 897 protocol_version: string; 898 (** MCP protocol version supported by the server, formatted as YYYY-MM-DD. 899 If the server supports the client's requested version, it responds with 900 the same version. Otherwise, it responds with a version it does support. *) 901 instructions: string option; 902 (** Optional instructions for using the server. These can provide human-readable 903 guidance on how to interact with this specific server implementation. *) 904 meta: Json.t option; 905 (** Optional additional metadata as arbitrary JSON. Can contain server-specific 906 information not covered by the standard fields. *) 907 } 908 include Json.Jsonable.S with type t := t 909 910 (** Create a new initialization result 911 @param capabilities Server capabilities that define supported optional features 912 @param server_info Server implementation details 913 @param protocol_version MCP protocol version supported by the server 914 @param instructions Optional instructions for using the server 915 @param meta Optional additional metadata 916 @return A new initialization result 917 *) 918 val create : capabilities:Json.t -> server_info:Implementation.t -> protocol_version:string -> ?instructions:string -> ?meta:Json.t -> unit -> t 919 920 (** Convert to JSON-RPC message 921 @param id ID matching the original request 922 @param t Initialization result 923 @return JSON-RPC message containing the initialization result 924 *) 925 val to_jsonrpc : id:RequestId.t -> t -> JSONRPCMessage.t 926 end 927end 928 929(** Initialized notification - Completes the initialization phase of the MCP lifecycle *) 930module Initialized : sig 931 module Notification : sig 932 (** InitializedNotification is sent by the client after receiving the initialization 933 response, indicating it's ready to begin normal operations. This completes the 934 three-step initialization process, after which both client and server can 935 freely exchange messages according to the negotiated capabilities. 936 937 Only after this notification has been sent should the client begin normal operations 938 like listing resources, calling tools, or requesting prompts. *) 939 type t = { 940 meta: Json.t option; 941 (** Optional additional metadata as arbitrary JSON. Can contain client-specific 942 information not covered by the standard fields. *) 943 } 944 include Json.Jsonable.S with type t := t 945 946 (** Create a new initialized notification 947 @param meta Optional additional metadata 948 @return A new initialized notification 949 *) 950 val create : ?meta:Json.t -> unit -> t 951 952 (** Convert to JSON-RPC message 953 @param t Initialized notification 954 @return JSON-RPC message containing the initialized notification 955 *) 956 val to_jsonrpc : t -> JSONRPCMessage.t 957 end 958end 959 960(** Parse a JSON message into an MCP message 961 962 This function takes a raw JSON value and parses it into a structured MCP message. 963 It's the primary entry point for processing incoming JSON-RPC messages in the MCP protocol. 964 965 The function determines the message type (notification, request, response, or error) 966 based on the presence and values of specific fields: 967 - A message with "method" but no "id" is a notification 968 - A message with "method" and "id" is a request 969 - A message with "id" and "result" is a response 970 - A message with "id" and "error" is an error 971 972 @param json The JSON message to parse, typically received from the transport layer 973 @return The parsed MCP message as a structured JSONRPCMessage.t value 974 @raise Parse error if the JSON cannot be parsed as a valid MCP message 975*) 976val parse_message : Json.t -> JSONRPCMessage.t 977 978(** Create a new notification message 979 980 Notifications are one-way messages that don't expect a response. 981 This is a convenience wrapper around JSONRPCMessage.create_notification. 982 983 Common notifications in MCP include: 984 - "notifications/initialized" - Sent after initialization 985 - "notifications/progress" - Updates on long-running operations 986 - "notifications/resources/updated" - Resource content changed 987 - "notifications/prompts/list_changed" - Available prompts changed 988 - "notifications/tools/list_changed" - Available tools changed 989 990 @param params Optional parameters for the notification as a JSON value 991 @param meth Method type for the notification 992 @return A new JSON-RPC notification message 993*) 994val create_notification : ?params:Json.t option -> meth:Method.t -> unit -> JSONRPCMessage.t 995 996(** Create a new request message 997 998 Requests are messages that expect a corresponding response. 999 This is a convenience wrapper around JSONRPCMessage.create_request. 1000 1001 Common requests in MCP include: 1002 - "initialize" - Start the MCP lifecycle 1003 - "resources/list" - Discover available resources 1004 - "resources/read" - Retrieve resource contents 1005 - "tools/list" - Discover available tools 1006 - "tools/call" - Invoke a tool 1007 - "prompts/list" - Discover available prompts 1008 - "prompts/get" - Retrieve a prompt template 1009 1010 @param params Optional parameters for the request as a JSON value 1011 @param progress_token Optional progress token for long-running operations 1012 that can report progress updates 1013 @param id Unique identifier for the request, used to correlate with the response 1014 @param meth Method type for the request 1015 @return A new JSON-RPC request message 1016*) 1017val create_request : ?params:Json.t option -> ?progress_token:ProgressToken.t option -> id:RequestId.t -> meth:Method.t -> unit -> JSONRPCMessage.t 1018 1019(** Create a new response message 1020 1021 Responses are sent in reply to requests and contain successful results. 1022 This is a convenience wrapper around JSONRPCMessage.create_response. 1023 1024 Each response must include the same ID as its corresponding request 1025 to allow the client to correlate them, especially when multiple 1026 requests are in flight simultaneously. 1027 1028 @param id ID matching the original request 1029 @param result Result of the successful request as a JSON value 1030 @return A new JSON-RPC response message 1031*) 1032val create_response : id:RequestId.t -> result:Json.t -> JSONRPCMessage.t 1033 1034(** Create a new error message 1035 1036 Errors are sent in reply to requests when processing fails. 1037 This is a convenience wrapper around JSONRPCMessage.create_error. 1038 1039 MCP uses standard JSON-RPC error codes as well as some protocol-specific codes: 1040 - -32700: Parse error (invalid JSON) 1041 - -32600: Invalid request (malformed JSON-RPC) 1042 - -32601: Method not found 1043 - -32602: Invalid parameters 1044 - -32603: Internal error 1045 - -32002: Resource not found (MCP-specific) 1046 - -32001: Authentication required (MCP-specific) 1047 1048 @param id ID matching the original request 1049 @param code Error code indicating the type of error 1050 @param message Human-readable error message describing the issue 1051 @param data Optional additional error data providing more context 1052 @return A new JSON-RPC error message 1053*) 1054val create_error : id:RequestId.t -> code:int -> message:string -> ?data:Json.t option -> unit -> JSONRPCMessage.t 1055 1056(** Create a new text content object 1057 @param text The text content 1058 @return A content value with the text 1059*) 1060val make_text_content : string -> content 1061 1062(** Create a new image content object 1063 @param data Base64-encoded image data 1064 @param mime_type MIME type of the image (e.g., "image/png", "image/jpeg") 1065 @return A content value with the image 1066*) 1067val make_image_content : string -> string -> content 1068 1069(** Create a new audio content object 1070 @param data Base64-encoded audio data 1071 @param mime_type MIME type of the audio (e.g., "audio/wav", "audio/mp3") 1072 @return A content value with the audio 1073*) 1074val make_audio_content : string -> string -> content 1075 1076(** Create a new text resource content object 1077 @param uri URI that uniquely identifies the resource 1078 @param text The text content of the resource 1079 @param mime_type Optional MIME type of the text content 1080 @return A content value with the text resource 1081*) 1082val make_resource_text_content : string -> string -> string option -> content 1083 1084(** Create a new binary resource content object 1085 @param uri URI that uniquely identifies the resource 1086 @param blob Base64-encoded binary data 1087 @param mime_type Optional MIME type of the binary content 1088 @return A content value with the binary resource 1089*) 1090val make_resource_blob_content : string -> string -> string option -> content