Model Context Protocol in OCaml

mcp_server: keep also stdio transport

Both are supported after all (see https://modelcontextprotocol.io/docs/concepts/architecture)

mseri.me 3ce7cd82 37c41d48

Changed files
+38
lib
+36
lib/mcp_server.ml
···
let log_warning ex = Logs.warn (fun f -> f "%a" Eio.Exn.pp ex)
+
(** run the server using http transport *)
let run_server ?(port = 8080) ?(on_error = log_warning) env server =
let net = Eio.Stdenv.net env in
let addr = `Tcp (Eio.Net.Ipaddr.V4.loopback, port) in
···
Log.infof "MCP HTTP Server listening on http://localhost:%d" port;
Cohttp_eio.Server.run server_socket server_spec ~on_error
+
+
(** run the server using the stdio transport *)
+
let run_sdtio_server env server =
+
let stdin = Eio.Stdenv.stdin env in
+
let stdout = Eio.Stdenv.stdout env in
+
+
Log.debugf "Starting MCP server: %s v%s" (name server) (version server);
+
Log.debugf "Protocol version: %s" (protocol_version server);
+
+
(* Enable exception backtraces *)
+
Printexc.record_backtrace true;
+
+
let buf = Eio.Buf_read.of_flow stdin ~initial_size:100 ~max_size:1_000_000 in
+
+
(* Main processing loop *)
+
try
+
while true do
+
Log.debug "Waiting for message...";
+
let line = Eio.Buf_read.line buf in
+
+
(* Process the input and send response if needed *)
+
match process_input_line server line with
+
| Some response -> send_response stdout response
+
| None -> Log.debug "No response needed for this message"
+
done
+
with
+
| End_of_file ->
+
Log.debug "End of file received on stdin";
+
()
+
| Eio.Exn.Io _ as exn ->
+
Log.errorf "I/O error while reading: %s" (Printexc.to_string exn);
+
()
+
| exn ->
+
Log.errorf "Exception while reading: %s" (Printexc.to_string exn);
+
()
+2
mcp.opam
···
"dune" {>= "3.17"}
"ocaml" {>= "5.2.0"}
"jsonrpc"
+
"http"
+
"cohttp-eio"
"eio_main"
"eio"
"odoc" {with-doc}