My agentic slop goes here. Not intended for anyone else!
at main 12 kB view raw
1(** SDK Control Protocol for Claude. 2 3 This module defines the typed SDK control protocol for bidirectional 4 communication between the SDK and the Claude CLI. It handles: 5 6 - Permission requests (tool usage authorization) 7 - Hook callbacks (intercepting and modifying tool execution) 8 - Dynamic control (changing settings mid-conversation) 9 - Server introspection (querying capabilities) 10 11 {2 Protocol Overview} 12 13 The SDK control protocol is a JSON-based request/response protocol that 14 runs alongside the main message stream. It enables: 15 16 1. {b Callbacks}: Claude asks the SDK for permission or hook execution 17 2. {b Control}: SDK changes Claude's behavior dynamically 18 3. {b Introspection}: SDK queries server metadata 19 20 {2 Request/Response Flow} 21 22 {v 23 SDK Claude CLI 24 | | 25 |-- Initialize (with hooks) --> | 26 |<-- Permission Request --------| (for tool usage) 27 |-- Allow/Deny Response ------> | 28 | | 29 |<-- Hook Callback -------------| (pre/post tool) 30 |-- Hook Result -------------> | 31 | | 32 |-- Set Model ---------------> | (dynamic control) 33 |<-- Success Response ----------| 34 | | 35 |-- Get Server Info ----------> | 36 |<-- Server Info Response ------| 37 v} 38 39 {2 Usage} 40 41 Most users won't interact with this module directly. The {!Client} module 42 handles the protocol automatically. However, this module is exposed for: 43 44 - Understanding the control protocol 45 - Implementing custom control logic 46 - Debugging control message flow 47 - Advanced SDK extensions 48 49 {2 Dynamic Control Examples} 50 51 See {!Client.set_permission_mode}, {!Client.set_model}, and 52 {!Client.get_server_info} for high-level APIs that use this protocol. *) 53 54(** The log source for SDK control operations *) 55val src : Logs.Src.t 56 57(** {1 Control Subtypes} 58 59 These modules define the individual request/response subtypes for 60 the SDK control protocol. Each subtype represents a specific control 61 operation with its own request and response structure. *) 62 63(** {2 MCP Message Routing} 64 65 The [Mcp_message] subtype routes JSONRPC messages to in-process MCP servers. 66 This is used when the SDK manages MCP servers directly (SDK MCP servers). 67 68 External MCP servers (stdio, HTTP, SSE) are handled by the CLI directly 69 and don't use this control message. 70 71 Example: 72 {[ 73 let req = Mcp_message.make_request 74 ~server_name:"calculator" 75 ~message:(* JSONRPC tools/list request *) 76 77 (* CLI routes to SDK MCP server and returns response *) 78 let resp = (* receive Mcp_message response *) 79 let jsonrpc_response = resp.mcp_response 80 ]} *) 81module Mcp_message : sig 82 module Unknown : sig 83 type t = Jsont.json 84 val empty : t 85 val is_empty : t -> bool 86 val jsont : t Jsont.t 87 end 88 89 type request = { 90 server_name : string; 91 (** Name of the SDK MCP server to route the message to *) 92 93 message : Jsont.json; 94 (** JSONRPC message to send to the MCP server *) 95 96 unknown : Unknown.t; 97 (** Unknown fields for forward compatibility *) 98 } 99 (** Request to route JSONRPC message to an in-process MCP server. *) 100 101 type response = { 102 mcp_response : Jsont.json; 103 (** JSONRPC response from the MCP server *) 104 105 unknown : Unknown.t; 106 (** Unknown fields for forward compatibility *) 107 } 108 (** Response containing JSONRPC response from MCP server. *) 109 110 val request_jsont : request Jsont.t 111 (** [request_jsont] is the jsont codec for MCP message requests. *) 112 113 val response_jsont : response Jsont.t 114 (** [response_jsont] is the jsont codec for MCP message responses. *) 115 116 val make_request : server_name:string -> message:Jsont.json -> ?unknown:Unknown.t -> unit -> request 117 (** [make_request ~server_name ~message ?unknown ()] creates an MCP message request. *) 118 119 val make_response : mcp_response:Jsont.json -> ?unknown:Unknown.t -> unit -> response 120 (** [make_response ~mcp_response ?unknown ()] creates an MCP message response. *) 121 122 val pp_request : Format.formatter -> request -> unit 123 (** [pp_request fmt req] pretty-prints an MCP message request. *) 124 125 val pp_response : Format.formatter -> response -> unit 126 (** [pp_response fmt resp] pretty-prints an MCP message response. *) 127end 128 129(** {1 Request Types} *) 130 131module Request : sig 132 (** SDK control request types. *) 133 134 type interrupt = { 135 subtype : [`Interrupt]; 136 unknown : Unknown.t; 137 } 138 (** Interrupt request to stop execution. *) 139 140 type permission = { 141 subtype : [`Can_use_tool]; 142 tool_name : string; 143 input : Jsont.json; 144 permission_suggestions : Permissions.Update.t list option; 145 blocked_path : string option; 146 unknown : Unknown.t; 147 } 148 (** Permission request for tool usage. *) 149 150 type initialize = { 151 subtype : [`Initialize]; 152 hooks : (string * Jsont.json) list option; (* Hook event to configuration *) 153 unknown : Unknown.t; 154 } 155 (** Initialize request with optional hook configuration. *) 156 157 type set_permission_mode = { 158 subtype : [`Set_permission_mode]; 159 mode : Permissions.Mode.t; 160 unknown : Unknown.t; 161 } 162 (** Request to change permission mode. *) 163 164 type hook_callback = { 165 subtype : [`Hook_callback]; 166 callback_id : string; 167 input : Jsont.json; 168 tool_use_id : string option; 169 unknown : Unknown.t; 170 } 171 (** Hook callback request. *) 172 173 type set_model = { 174 subtype : [`Set_model]; 175 model : string; 176 unknown : Unknown.t; 177 } 178 (** Request to change the AI model. *) 179 180 type get_server_info = { 181 subtype : [`Get_server_info]; 182 unknown : Unknown.t; 183 } 184 (** Request to get server information. *) 185 186 type t = 187 | Interrupt of interrupt 188 | Permission of permission 189 | Initialize of initialize 190 | Set_permission_mode of set_permission_mode 191 | Hook_callback of hook_callback 192 | Mcp_message of Mcp_message.request 193 | Set_model of set_model 194 | Get_server_info of get_server_info 195 (** The type of SDK control requests. *) 196 197 val interrupt : ?unknown:Unknown.t -> unit -> t 198 (** [interrupt ?unknown ()] creates an interrupt request. *) 199 200 val permission : 201 tool_name:string -> 202 input:Jsont.json -> 203 ?permission_suggestions:Permissions.Update.t list -> 204 ?blocked_path:string -> 205 ?unknown:Unknown.t -> 206 unit -> t 207 (** [permission ~tool_name ~input ?permission_suggestions ?blocked_path ?unknown ()] 208 creates a permission request. *) 209 210 val initialize : ?hooks:(string * Jsont.json) list -> ?unknown:Unknown.t -> unit -> t 211 (** [initialize ?hooks ?unknown ()] creates an initialize request. *) 212 213 val set_permission_mode : mode:Permissions.Mode.t -> ?unknown:Unknown.t -> unit -> t 214 (** [set_permission_mode ~mode ?unknown] creates a permission mode change request. *) 215 216 val hook_callback : 217 callback_id:string -> 218 input:Jsont.json -> 219 ?tool_use_id:string -> 220 ?unknown:Unknown.t -> 221 unit -> t 222 (** [hook_callback ~callback_id ~input ?tool_use_id ?unknown ()] creates a hook callback request. *) 223 224 val mcp_message : server_name:string -> message:Jsont.json -> ?unknown:Unknown.t -> unit -> t 225 (** [mcp_message ~server_name ~message ?unknown] creates an MCP message request. *) 226 227 val set_model : model:string -> ?unknown:Unknown.t -> unit -> t 228 (** [set_model ~model ?unknown] creates a model change request. *) 229 230 val get_server_info : ?unknown:Unknown.t -> unit -> t 231 (** [get_server_info ?unknown ()] creates a server info request. *) 232 233 val jsont : t Jsont.t 234 (** [jsont] is the jsont codec for requests. *) 235 236 val pp : Format.formatter -> t -> unit 237 (** [pp fmt t] pretty-prints the request. *) 238end 239 240(** {1 Response Types} *) 241 242module Response : sig 243 (** SDK control response types. *) 244 245 type success = { 246 subtype : [`Success]; 247 request_id : string; 248 response : Jsont.json option; 249 unknown : Unknown.t; 250 } 251 (** Successful response. *) 252 253 type error = { 254 subtype : [`Error]; 255 request_id : string; 256 error : string; 257 unknown : Unknown.t; 258 } 259 (** Error response. *) 260 261 type t = 262 | Success of success 263 | Error of error 264 (** The type of SDK control responses. *) 265 266 val success : request_id:string -> ?response:Jsont.json -> ?unknown:Unknown.t -> unit -> t 267 (** [success ~request_id ?response ?unknown ()] creates a success response. *) 268 269 val error : request_id:string -> error:string -> ?unknown:Unknown.t -> unit -> t 270 (** [error ~request_id ~error ?unknown] creates an error response. *) 271 272 val jsont : t Jsont.t 273 (** [jsont] is the jsont codec for responses. *) 274 275 val pp : Format.formatter -> t -> unit 276 (** [pp fmt t] pretty-prints the response. *) 277end 278 279(** {1 Control Messages} *) 280 281type control_request = { 282 type_ : [`Control_request]; 283 request_id : string; 284 request : Request.t; 285 unknown : Unknown.t; 286} 287(** Control request message. *) 288 289type control_response = { 290 type_ : [`Control_response]; 291 response : Response.t; 292 unknown : Unknown.t; 293} 294(** Control response message. *) 295 296val control_response_jsont : control_response Jsont.t 297(** [control_response_jsont] is the jsont codec for control response messages. *) 298 299type t = 300 | Request of control_request 301 | Response of control_response 302(** The type of SDK control messages. *) 303 304val create_request : request_id:string -> request:Request.t -> ?unknown:Unknown.t -> unit -> t 305(** [create_request ~request_id ~request ?unknown ()] creates a control request message. *) 306 307val create_response : response:Response.t -> ?unknown:Unknown.t -> unit -> t 308(** [create_response ~response ?unknown ()] creates a control response message. *) 309 310val jsont : t Jsont.t 311(** [jsont] is the jsont codec for control messages. *) 312 313val pp : Format.formatter -> t -> unit 314(** [pp fmt t] pretty-prints the control message. *) 315 316(** {1 Logging} *) 317 318val log_request : Request.t -> unit 319(** [log_request req] logs an SDK control request. *) 320 321val log_response : Response.t -> unit 322(** [log_response resp] logs an SDK control response. *) 323 324(** {1 Server Information} 325 326 Server information provides metadata about the Claude CLI server, 327 including version, capabilities, available commands, and output styles. 328 329 {2 Use Cases} 330 331 - Feature detection: Check if specific capabilities are available 332 - Version compatibility: Ensure minimum version requirements 333 - Debugging: Log server information for troubleshooting 334 - Dynamic adaptation: Adjust SDK behavior based on capabilities 335 336 {2 Example} 337 338 {[ 339 let info = Client.get_server_info client in 340 Printf.printf "Claude CLI version: %s\n" 341 (Server_info.version info); 342 343 if List.mem "structured-output" (Server_info.capabilities info) then 344 Printf.printf "Structured output is supported\n" 345 else 346 Printf.printf "Structured output not available\n"; 347 ]} *) 348 349module Server_info : sig 350 (** Server information and capabilities. *) 351 352 type t = { 353 version : string; 354 (** Server version string (e.g., "2.0.0") *) 355 356 capabilities : string list; 357 (** Available server capabilities (e.g., "hooks", "structured-output") *) 358 359 commands : string list; 360 (** Available CLI commands *) 361 362 output_styles : string list; 363 (** Supported output formats (e.g., "json", "stream-json") *) 364 365 unknown : Unknown.t; 366 (** Unknown fields for forward compatibility *) 367 } 368 (** Server metadata and capabilities. 369 370 This information is useful for feature detection and debugging. *) 371 372 val create : 373 version:string -> 374 capabilities:string list -> 375 commands:string list -> 376 output_styles:string list -> 377 ?unknown:Unknown.t -> 378 unit -> 379 t 380 (** [create ~version ~capabilities ~commands ~output_styles ?unknown ()] creates server info. *) 381 382 val version : t -> string 383 (** [version t] returns the server version. *) 384 385 val capabilities : t -> string list 386 (** [capabilities t] returns the server capabilities. *) 387 388 val commands : t -> string list 389 (** [commands t] returns available commands. *) 390 391 val output_styles : t -> string list 392 (** [output_styles t] returns available output styles. *) 393 394 val unknown : t -> Unknown.t 395 (** [unknown t] returns the unknown fields. *) 396 397 val jsont : t Jsont.t 398 (** [jsont] is the jsont codec for server info. *) 399 400 val pp : Format.formatter -> t -> unit 401 (** [pp fmt t] pretty-prints the server info. *) 402end