···9999100100```ocaml
101101(* If expression *)
102102-let abs x =
102102+let abs x =
103103 if x < 0 then -x else x
104104105105(* Match expression (pattern matching) *)
···308308 let pi = 3.14159
309309 let square x = x *. x
310310 let cube x = x *. x *. x
311311-311311+312312 (* This is hidden because it's not in the signature *)
313313 let private_helper x = x +. 1.0
314314end
···330330(* Functor that creates a set implementation given an element type with comparison *)
331331module MakeSet (Element : sig type t val compare : t -> t -> int end) : COLLECTION with type 'a t = Element.t list = struct
332332 type 'a t = Element.t list
333333-333333+334334 let empty = []
335335-335335+336336 let rec add x lst =
337337 match lst with
338338 | [] -> [x]
···341341 if c < 0 then x :: lst
342342 else if c = 0 then lst (* Element already exists *)
343343 else y :: add x ys
344344-344344+345345 let rec mem x lst =
346346 match lst with
347347 | [] -> false
···459459 | `Circle r -> Float.pi *. r *. r
460460 | `Rectangle (w, h) -> w *. h
461461 | `Triangle (b, h) -> 0.5 *. b *. h
462462- | `Regular_polygon(n, s) when n >= 3 ->
462462+ | `Regular_polygon(n, s) when n >= 3 ->
463463 let apothem = s /. (2.0 *. tan (Float.pi /. float_of_int n)) in
464464 n *. s *. apothem /. 2.0
465465 | _ -> failwith "Invalid shape"
···475475 object (self)
476476 val mutable x = x_init
477477 val mutable y = y_init
478478-478478+479479 method get_x = x
480480 method get_y = y
481481 method move dx dy = x <- x + dx; y <- y + dy
482482- method distance_from_origin =
482482+ method distance_from_origin =
483483 sqrt (float_of_int (x * x + y * y))
484484-484484+485485 (* Private method *)
486486- method private to_string =
486486+ method private to_string =
487487 Printf.sprintf "(%d, %d)" x y
488488-488488+489489 (* Calling another method *)
490490 method print = print_endline self#to_string
491491 end
···554554(* Handler for the Ask effect *)
555555let prompt_user () =
556556 Effect.Deep.try_with
557557- (fun () ->
557557+ (fun () ->
558558 let name = Effect.perform (Ask "What is your name?") in
559559 Printf.printf "Hello, %s!\n" name)
560560 { Effect.Deep.effc = fun (type a) (effect : a Effect.t) ->
···605605} [@@deriving sexp]
606606607607(* With ppx_let for monadic operations *)
608608-let computation =
608608+let computation =
609609 [%m.let
610610 let* x = get_value_from_db "key1" in
611611 let* y = get_value_from_db "key2" in
···621621(* Phantom types for added type safety *)
622622module SafeString : sig
623623 type 'a t
624624-624624+625625 (* Constructors for different string types *)
626626 val of_raw : string -> [`Raw] t
627627 val sanitize : [`Raw] t -> [`Sanitized] t
628628 val validate : [`Sanitized] t -> [`Validated] t option
629629-629629+630630 (* Operations that require specific string types *)
631631 val to_html : [`Sanitized] t -> string
632632 val to_sql : [`Validated] t -> string
633633-633633+634634 (* Common operations for all string types *)
635635 val length : _ t -> int
636636 val concat : _ t -> _ t -> [`Raw] t
637637end = struct
638638 type 'a t = string
639639-639639+640640 let of_raw s = s
641641 let sanitize s = String.map (function '<' | '>' -> '_' | c -> c) s
642642 let validate s = if String.length s > 0 then Some s else None
643643-643643+644644 let to_html s = s
645645 let to_sql s = "'" ^ String.map (function '\'' -> '\'' | c -> c) s ^ "'"
646646-646646+647647 let length = String.length
648648 let concat s1 s2 = s1 ^ s2
649649end
···718718 content)
719719720720(* Run the server with the default scheduler *)
721721-let () = Eio_main.run @@ fun env -> Mcp_server.run_server env server
721721+let () = Eio_main.run @@ fun env -> Mcp_server.run_stdio_server env server
+5-4
bin/multimodal_sdk.ml
···313313 ]
314314 ~is_error:false
315315 with Failure msg ->
316316- Log.errorf "Error in multimodal tool: %s" msg;
316316+ Logs.err (fun m -> m "Error in multimodal tool: %s" msg);
317317 Tool.create_tool_result
318318 [ Mcp.make_text_content (Printf.sprintf "Error: %s" msg) ]
319319 ~is_error:true)
···346346 [ Mcp.make_image_content image_data "image/gif" ]
347347 ~is_error:false
348348 with Failure msg ->
349349- Log.errorf "Error in generate_image tool: %s" msg;
349349+ Logs.err (fun m -> m "Error in generate_image tool: %s" msg);
350350 Tool.create_tool_result
351351 [ Mcp.make_text_content (Printf.sprintf "Error: %s" msg) ]
352352 ~is_error:true)
···388388 [ Mcp.make_audio_content audio_data "audio/wav" ]
389389 ~is_error:false
390390 with Failure msg ->
391391- Log.errorf "Error in generate_audio tool: %s" msg;
391391+ Logs.err (fun m -> m "Error in generate_audio tool: %s" msg);
392392 Tool.create_tool_result
393393 [ Mcp.make_text_content (Printf.sprintf "Error: %s" msg) ]
394394 ~is_error:true)
···427427428428(* Run the server with the default scheduler *)
429429let () =
430430+ Logs.set_reporter (Logs.format_reporter ());
430431 Random.self_init ();
431432 (* Initialize random generator *)
432432- Eio_main.run @@ fun env -> Mcp_server.run_server env server
433433+ Eio_main.run @@ fun env -> Mcp_server.run_stdio_server env server
+4-2
bin/ocaml_eval_sdk.ml
···150150 [ Mcp.make_text_content output ]
151151 ~is_error:(not success)
152152 with Failure msg ->
153153- Log.errorf "Error in OCaml eval tool: %s" msg;
153153+ Logs.err (fun m -> m "Error in OCaml eval tool: %s" msg);
154154 Tool.create_tool_result
155155 [ Mcp.make_text_content (Printf.sprintf "Error: %s" msg) ]
156156 ~is_error:true)
157157158158(* Run the server with the default scheduler *)
159159-let () = Eio_main.run @@ fun env -> Mcp_server.run_server env server
159159+let () =
160160+ Logs.set_reporter (Logs.format_reporter ());
161161+ Eio_main.run @@ fun env -> Mcp_server.run_stdio_server env server
···3344(* SDK version *)
55let version = "0.1.0"
66-77-(* Logging utilities *)
88-module Log = struct
99- type level = Debug | Info | Warning | Error
1010-1111- let string_of_level = function
1212- | Debug -> "DEBUG"
1313- | Info -> "INFO"
1414- | Warning -> "WARNING"
1515- | Error -> "ERROR"
1616-1717- let logf level fmt =
1818- Printf.fprintf stderr "[%s] " (string_of_level level);
1919- Printf.kfprintf
2020- (fun oc ->
2121- Printf.fprintf oc "\n";
2222- flush oc)
2323- stderr fmt
2424-2525- let debugf fmt = logf Debug fmt
2626- let infof fmt = logf Info fmt
2727- let warningf fmt = logf Warning fmt
2828- let errorf fmt = logf Error fmt
66+let src = Logs.Src.create "mcp.sdk" ~doc:"mcp.sdk logging"
2973030- (* Backward compatibility functions that take a simple string *)
3131- let log level msg = logf level "%s" msg
3232- let debug msg = debugf "%s" msg
3333- let info msg = infof "%s" msg
3434- let warning msg = warningf "%s" msg
3535- let error msg = errorf "%s" msg
3636-end
88+module Log = (val Logs.src_log src : Logs.LOG)
3793810(* Context for tools and resources *)
3911module Context = struct
···182154183155 (* Create a tool error result with structured content *)
184156 let create_error_result error =
185185- Log.errorf "Error result: %s" error;
157157+ Logs.err (fun m -> m "Error result: %s" error);
186158 create_tool_result [ Mcp.make_text_content error ] ~is_error:true
187159188160 (* Handle tool execution errors *)
···214186 let create ~uri ~name ?description ?mime_type ~handler () =
215187 (* Validate that the URI doesn't contain template variables *)
216188 if String.contains uri '{' || String.contains uri '}' then
217217- Log.warningf
218218- "Resource '%s' contains template variables. Consider using \
219219- add_resource_template instead."
220220- uri;
189189+ Logs.warn (fun m ->
190190+ m
191191+ "Resource '%s' contains template variables. Consider using \
192192+ add_resource_template instead."
193193+ uri);
221194 { uri; name; description; mime_type; handler }
222195223196 let to_json resource =
-23
lib/mcp_sdk.mli
···66val version : string
77(** SDK version *)
8899-(** Logging utilities *)
1010-module Log : sig
1111- type level = Debug | Info | Warning | Error
1212-1313- val string_of_level : level -> string
1414-1515- val logf : level -> ('a, out_channel, unit) format -> 'a
1616- (** Format-string based logging functions *)
1717-1818- val debugf : ('a, out_channel, unit) format -> 'a
1919- val infof : ('a, out_channel, unit) format -> 'a
2020- val warningf : ('a, out_channel, unit) format -> 'a
2121- val errorf : ('a, out_channel, unit) format -> 'a
2222-2323- val log : level -> string -> unit
2424- (** Simple string logging functions (for backward compatibility) *)
2525-2626- val debug : string -> unit
2727- val info : string -> unit
2828- val warning : string -> unit
2929- val error : string -> unit
3030-end
3131-329(** Context for tools and resources *)
3310module Context : sig
3411 type t
+93-70
lib/mcp_server.ml
···22open Jsonrpc
33open Mcp_sdk
4455+let src = Logs.Src.create "mcp.sdk" ~doc:"mcp.sdk logging"
66+77+module Log = (val Logs.src_log src : Logs.LOG)
88+59(* Create a proper JSONRPC error with code and data *)
610let create_jsonrpc_error id code message ?data () =
711 let error_code = ErrorCode.to_int code in
···10141115(* Process initialize request *)
1216let handle_initialize server req =
1313- Log.debug "Processing initialize request";
1717+ Log.debug (fun m -> m "Processing initialize request");
1418 let result =
1519 match req.JSONRPCMessage.params with
1620 | Some params ->
1721 let req_data = Initialize.Request.t_of_yojson params in
1818- Log.debugf "Client info: %s v%s" req_data.client_info.name
1919- req_data.client_info.version;
2020- Log.debugf "Client protocol version: %s" req_data.protocol_version;
2222+ Logs.debug (fun m ->
2323+ m "Client info: %s v%s" req_data.client_info.name
2424+ req_data.client_info.version);
2525+ Log.debug (fun m ->
2626+ m "Client protocol version: %s" req_data.protocol_version);
21272228 (* Create initialize response *)
2329 let result =
···3137 in
3238 Initialize.Result.yojson_of_t result
3339 | None ->
3434- Log.error "Missing params for initialize request";
4040+ Log.err (fun m -> m "Missing params for initialize request");
3541 `Assoc [ ("error", `String "Missing params for initialize request") ]
3642 in
3743 Some (create_response ~id:req.id ~result)
38443945(* Process tools/list request *)
4046let handle_tools_list server (req : JSONRPCMessage.request) =
4141- Log.debug "Processing tools/list request";
4747+ Log.debug (fun m -> m "Processing tools/list request");
4248 let tools_list = Tool.to_rpc_tools_list (tools server) in
4349 let response =
4450 Mcp_rpc.ToolsList.create_response ~id:req.id ~tools:tools_list ()
···47534854(* Process prompts/list request *)
4955let handle_prompts_list server (req : JSONRPCMessage.request) =
5050- Log.debug "Processing prompts/list request";
5656+ Log.debug (fun m -> m "Processing prompts/list request");
5157 let prompts_list = Prompt.to_rpc_prompts_list (prompts server) in
5258 let response =
5359 Mcp_rpc.PromptsList.create_response ~id:req.id ~prompts:prompts_list ()
···56625763(* Process resources/list request *)
5864let handle_resources_list server (req : JSONRPCMessage.request) =
5959- Log.debug "Processing resources/list request";
6565+ Log.debug (fun m -> m "Processing resources/list request");
6066 let resources_list = Resource.to_rpc_resources_list (resources server) in
6167 let response =
6268 Mcp_rpc.ResourcesList.create_response ~id:req.id ~resources:resources_list
···66726773(* Process resources/templates/list request *)
6874let handle_resource_templates_list server (req : JSONRPCMessage.request) =
6969- Log.debug "Processing resources/templates/list request";
7575+ Log.debug (fun m -> m "Processing resources/templates/list request");
7076 let templates_list =
7177 ResourceTemplate.to_rpc_resource_templates_list (resource_templates server)
7278 in
···144150145151(* Process resources/read request *)
146152let handle_resources_read server (req : JSONRPCMessage.request) =
147147- Log.debug "Processing resources/read request";
153153+ Log.debug (fun m -> m "Processing resources/read request");
148154 match req.JSONRPCMessage.params with
149155 | None ->
150150- Log.error "Missing params for resources/read request";
156156+ Log.err (fun m -> m "Missing params for resources/read request");
151157 Some
152158 (create_jsonrpc_error req.id ErrorCode.InvalidParams
153159 "Missing params for resources/read request" ())
154160 | Some params -> (
155161 let req_data = Mcp_rpc.ResourcesRead.Request.t_of_yojson params in
156162 let uri = req_data.uri in
157157- Log.debugf "Resource URI: %s" uri;
163163+ Log.debug (fun m -> m "Resource URI: %s" uri);
158164159165 (* Find matching resource or template *)
160166 match Resource_matcher.find_match server uri with
···168174 ()
169175 in
170176171171- Log.debugf "Handling direct resource: %s" resource.name;
177177+ Log.debug (fun m -> m "Handling direct resource: %s" resource.name);
172178173179 (* Call the resource handler *)
174180 match resource.handler ctx params with
···195201 in
196202 Some response
197203 | Error err ->
198198- Log.errorf "Error reading resource: %s" err;
204204+ Log.err (fun m -> m "Error reading resource: %s" err);
199205 Some
200206 (create_jsonrpc_error req.id ErrorCode.InternalError
201207 ("Error reading resource: " ^ err)
···210216 ()
211217 in
212218213213- Log.debugf "Handling resource template: %s with params: [%s]"
214214- template.name
215215- (String.concat ", " params);
219219+ Log.debug (fun m ->
220220+ m "Handling resource template: %s with params: [%s]" template.name
221221+ (String.concat ", " params));
216222217223 (* Call the template handler *)
218224 match template.handler ctx params with
···239245 in
240246 Some response
241247 | Error err ->
242242- Log.errorf "Error reading resource template: %s" err;
248248+ Log.err (fun m -> m "Error reading resource template: %s" err);
243249 Some
244250 (create_jsonrpc_error req.id ErrorCode.InternalError
245251 ("Error reading resource template: " ^ err)
246252 ()))
247253 | Resource_matcher.NoMatch ->
248248- Log.errorf "Resource not found: %s" uri;
254254+ Log.err (fun m -> m "Resource not found: %s" uri);
249255 Some
250256 (create_jsonrpc_error req.id ErrorCode.InvalidParams
251257 ("Resource not found: " ^ uri)
···255261let extract_tool_name params =
256262 match List.assoc_opt "name" params with
257263 | Some (`String name) ->
258258- Log.debugf "Tool name: %s" name;
264264+ Log.debug (fun m -> m "Tool name: %s" name);
259265 Some name
260266 | _ ->
261261- Log.error "Missing or invalid 'name' parameter in tool call";
267267+ Log.err (fun m -> m "Missing or invalid 'name' parameter in tool call");
262268 None
263269264270(* Extract the tool arguments from params *)
265271let extract_tool_arguments params =
266272 match List.assoc_opt "arguments" params with
267273 | Some args ->
268268- Log.debugf "Tool arguments: %s" (Yojson.Safe.to_string args);
274274+ Log.debug (fun m -> m "Tool arguments: %s" (Yojson.Safe.to_string args));
269275 args
270276 | _ ->
271271- Log.debug "No arguments provided for tool call, using empty object";
277277+ Log.debug (fun m ->
278278+ m "No arguments provided for tool call, using empty object");
272279 `Assoc [] (* Empty arguments is valid *)
273280274281(* Execute a tool *)
275282let execute_tool server ctx name args =
276283 try
277284 let tool = List.find (fun t -> t.Tool.name = name) (tools server) in
278278- Log.debugf "Found tool: %s" name;
285285+ Log.debug (fun m -> m "Found tool: %s" name);
279286280287 (* Call the tool handler *)
281288 match tool.handler ctx args with
282289 | Ok result ->
283283- Log.debug "Tool execution succeeded";
290290+ Log.debug (fun m -> m "Tool execution succeeded");
284291 result
285292 | Error err -> Tool.handle_execution_error err
286293 with
···311318312319(* Process tools/call request *)
313320let handle_tools_call server req =
314314- Log.debug "Processing tools/call request";
321321+ Log.debug (fun m -> m "Processing tools/call request");
315322 match req.JSONRPCMessage.params with
316323 | Some (`Assoc params) -> (
317324 match extract_tool_name params with
···343350 (create_jsonrpc_error req.id InvalidParams
344351 "Missing tool name parameter" ()))
345352 | _ ->
346346- Log.error "Invalid params format for tools/call";
353353+ Log.err (fun m -> m "Invalid params format for tools/call");
347354 Some
348355 (create_jsonrpc_error req.id InvalidParams
349356 "Invalid params format for tools/call" ())
350357351358(* Process ping request *)
352359let handle_ping (req : JSONRPCMessage.request) =
353353- Log.debug "Processing ping request";
360360+ Log.debug (fun m -> m "Processing ping request");
354361 Some (create_response ~id:req.JSONRPCMessage.id ~result:(`Assoc []))
355362356363(* Handle notifications/initialized *)
357364let handle_initialized (notif : JSONRPCMessage.notification) =
358358- Log.debug
359359- "Client initialization complete - Server is now ready to receive requests";
360360- Log.debugf "Notification params: %s"
361361- (match notif.JSONRPCMessage.params with
362362- | Some p -> Yojson.Safe.to_string p
363363- | None -> "null");
365365+ Log.debug (fun m ->
366366+ m
367367+ "Client initialization complete - Server is now ready to receive \
368368+ requests\n\
369369+ \ Notification params: %s"
370370+ (match notif.JSONRPCMessage.params with
371371+ | Some p -> Yojson.Safe.to_string p
372372+ | None -> "null"));
364373 None
365374366375(* Process a single message using the MCP SDK *)
367376let process_message server message =
368377 try
369369- Log.debugf "Processing message: %s" (Yojson.Safe.to_string message);
378378+ Log.debug (fun m ->
379379+ m "Processing message: %s" (Yojson.Safe.to_string message));
370380 match JSONRPCMessage.t_of_yojson message with
371381 | JSONRPCMessage.Request req -> (
372372- Log.debugf "Received request with method: %s"
373373- (Method.to_string req.meth);
382382+ Log.debug (fun m ->
383383+ m "Received request with method: %s" (Method.to_string req.meth));
374384 match req.meth with
375385 | Method.Initialize -> handle_initialize server req
376386 | Method.ToolsList -> handle_tools_list server req
···381391 | Method.ResourceTemplatesList ->
382392 handle_resource_templates_list server req
383393 | _ ->
384384- Log.errorf "Unknown method received: %s" (Method.to_string req.meth);
394394+ Log.err (fun m ->
395395+ m "Unknown method received: %s" (Method.to_string req.meth));
385396 Some
386397 (create_jsonrpc_error req.id ErrorCode.MethodNotFound
387398 ("Method not found: " ^ Method.to_string req.meth)
388399 ()))
389400 | JSONRPCMessage.Notification notif -> (
390390- Log.debugf "Received notification with method: %s"
391391- (Method.to_string notif.meth);
401401+ Log.debug (fun m ->
402402+ m "Received notification with method: %s"
403403+ (Method.to_string notif.meth));
392404 match notif.meth with
393405 | Method.Initialized -> handle_initialized notif
394406 | _ ->
395395- Log.debugf "Ignoring notification: %s" (Method.to_string notif.meth);
407407+ Log.debug (fun m ->
408408+ m "Ignoring notification: %s" (Method.to_string notif.meth));
396409 None)
397410 | JSONRPCMessage.Response _ ->
398398- Log.error "Unexpected response message received";
411411+ Log.err (fun m -> m "Unexpected response message received");
399412 None
400413 | JSONRPCMessage.Error _ ->
401401- Log.error "Unexpected error message received";
414414+ Log.err (fun m -> m "Unexpected error message received");
402415 None
403416 with
404417 | Json.Of_json (msg, _) ->
405405- Log.errorf "JSON error: %s" msg;
418418+ Log.err (fun m -> m "JSON error: %s" msg);
406419 (* Can't respond with error because we don't have a request ID *)
407420 None
408421 | Yojson.Json_error msg ->
409409- Log.errorf "JSON parse error: %s" msg;
422422+ Log.err (fun m -> m "JSON parse error: %s" msg);
410423 (* Can't respond with error because we don't have a request ID *)
411424 None
412425 | exc ->
413413- Log.errorf "Exception during message processing: %s"
414414- (Printexc.to_string exc);
415415- Log.errorf "Backtrace: %s" (Printexc.get_backtrace ());
416416- Log.errorf "Message was: %s" (Yojson.Safe.to_string message);
426426+ Log.err (fun m ->
427427+ m
428428+ "Exception during message processing: %s\n\
429429+ Backtrace: %s\n\
430430+ Message was: %s"
431431+ (Printexc.to_string exc)
432432+ (Printexc.get_backtrace ())
433433+ (Yojson.Safe.to_string message));
417434 None
418435419436(* Extract a request ID from a potentially malformed message *)
···431448(* Handle processing for an input line *)
432449let process_input_line server line =
433450 if line = "" then (
434434- Log.debug "Empty line received, ignoring";
451451+ Log.debug (fun m -> m "Empty line received, ignoring");
435452 None)
436453 else (
437437- Log.debugf "Raw input: %s" line;
454454+ Log.debug (fun m -> m "Raw input: %s" line);
438455 try
439456 let json = Yojson.Safe.from_string line in
440440- Log.debug "Successfully parsed JSON";
457457+ Log.debug (fun m -> m "Successfully parsed JSON");
441458442459 (* Process the message *)
443460 process_message server json
444461 with Yojson.Json_error msg ->
445445- Log.errorf "Error parsing JSON: %s" msg;
446446- Log.errorf "Input was: %s" line;
462462+ Log.err (fun m -> m "Error parsing JSON: %s" msg);
463463+ Log.err (fun m -> m "Input was: %s" line);
447464 None)
448465449466(* Send a response to the client *)
450467let send_response stdout response =
451468 let response_json = JSONRPCMessage.yojson_of_t response in
452469 let response_str = Yojson.Safe.to_string response_json in
453453- Log.debugf "Sending response: %s" response_str;
470470+ Log.debug (fun m -> m "Sending response: %s" response_str);
454471455472 (* Write the response followed by a newline *)
456473 Eio.Flow.copy_string response_str stdout;
···460477let callback mcp_server _conn (request : Http.Request.t) body =
461478 match request.meth with
462479 | `POST -> (
463463- Log.debug "Received POST request";
480480+ Log.debug (fun m -> m "Received POST request");
464481 let request_body_str =
465482 Eio.Buf_read.(parse_exn take_all) body ~max_size:max_int
466483 in
···468485 | Some mcp_response ->
469486 let response_json = JSONRPCMessage.yojson_of_t mcp_response in
470487 let response_str = Yojson.Safe.to_string response_json in
471471- Log.debugf "Sending MCP response: %s" response_str;
488488+ Log.debug (fun m -> m "Sending MCP response: %s" response_str);
472489 let headers =
473490 Http.Header.of_list [ ("Content-Type", "application/json") ]
474491 in
···476493 ~body:(Cohttp_eio.Body.of_string response_str)
477494 ()
478495 | None ->
479479- Log.debug "No MCP response needed";
496496+ Log.debug (fun m -> m "No MCP response needed");
480497 Cohttp_eio.Server.respond ~status:`No_content
481498 ~body:(Cohttp_eio.Body.of_string "")
482499 ())
483500 | _ ->
484484- Log.infof "Unsupported method: %s" (Http.Method.to_string request.meth);
501501+ Log.info (fun m ->
502502+ m "Unsupported method: %s" (Http.Method.to_string request.meth));
485503 Cohttp_eio.Server.respond ~status:`Method_not_allowed
486504 ~body:(Cohttp_eio.Body.of_string "Only POST is supported")
487505 ()
···493511 let net = Eio.Stdenv.net env in
494512 let addr = `Tcp (Eio.Net.Ipaddr.V4.loopback, port) in
495513496496- Log.debugf "Starting MCP server: %s v%s" (name server) (version server);
497497- Log.debugf "Protocol version: %s" (protocol_version server);
514514+ Log.info (fun m ->
515515+ m "Starting http MCP server: %s v%s\nProtocol version: %s" (name server)
516516+ (version server) (protocol_version server));
498517499518 Eio.Switch.run @@ fun sw ->
500519 let server_spec = Cohttp_eio.Server.make ~callback:(callback server) () in
···502521 let server_socket =
503522 Eio.Net.listen net ~sw ~backlog:128 ~reuse_addr:true addr
504523 in
505505- Log.infof "MCP HTTP Server listening on http://localhost:%d" port;
524524+ Log.info (fun m -> m "MCP HTTP Server listening on http://localhost:%d" port);
506525507526 Cohttp_eio.Server.run server_socket server_spec ~on_error
508527509528(** run the server using the stdio transport *)
510510-let run_sdtio_server env server =
529529+let run_stdio_server env server =
511530 let stdin = Eio.Stdenv.stdin env in
512531 let stdout = Eio.Stdenv.stdout env in
513532514514- Log.debugf "Starting MCP server: %s v%s" (name server) (version server);
515515- Log.debugf "Protocol version: %s" (protocol_version server);
533533+ Log.info (fun m ->
534534+ m "Starting stdio MCP server: %s v%s\nProtocol version: %s" (name server)
535535+ (version server) (protocol_version server));
516536517537 (* Enable exception backtraces *)
518538 Printexc.record_backtrace true;
···522542 (* Main processing loop *)
523543 try
524544 while true do
525525- Log.debug "Waiting for message...";
545545+ Log.info (fun m -> m "Waiting for message...");
526546 let line = Eio.Buf_read.line buf in
527547528548 (* Process the input and send response if needed *)
529549 match process_input_line server line with
530550 | Some response -> send_response stdout response
531531- | None -> Log.debug "No response needed for this message"
551551+ | None -> Log.info (fun m -> m "No response needed for this message")
532552 done
533553 with
534554 | End_of_file ->
535535- Log.debug "End of file received on stdin";
555555+ Log.debug (fun m -> m "End of file received on stdin");
536556 ()
537557 | Eio.Exn.Io _ as exn ->
538538- Log.errorf "I/O error while reading: %s" (Printexc.to_string exn);
558558+ (* Only a warning since on Windows, once the client closes the connection, we normally fail with `I/O error while reading: Eio.Io Net Connection_reset Unix_error (Broken pipe, "stub_cstruct_read", "")` *)
559559+ Log.warn (fun m ->
560560+ m "I/O error while reading: %s" (Printexc.to_string exn));
539561 ()
540562 | exn ->
541541- Log.errorf "Exception while reading: %s" (Printexc.to_string exn);
563563+ Log.err (fun m ->
564564+ m "Exception while reading: %s" (Printexc.to_string exn));
542565 ()