···
4
+
(* Helper for extracting string value from JSON *)
5
+
let get_string_param json name =
8
+
(match List.assoc_opt name fields with
9
+
| Some (`String value) -> value
10
+
| _ -> raise (Failure (Printf.sprintf "Missing or invalid parameter: %s" name)))
11
+
| _ -> raise (Failure "Expected JSON object")
13
+
(* Create a server *)
14
+
let server = create_server
15
+
~name:"OCaml MCP Completion Example"
17
+
~protocol_version:"2024-11-05"
20
+
(* Define startup and shutdown hooks *)
22
+
Printf.printf "CompletionServer is starting up!\n";
24
+
Log.info "CompletionServer is starting up!"
27
+
Printf.printf "CompletionServer is shutting down. Goodbye!\n";
29
+
Log.info "CompletionServer is shutting down. Goodbye!"
31
+
(* Register the hooks *)
33
+
set_startup_hook server startup;
34
+
set_shutdown_hook server shutdown
36
+
(* Database of programming languages and their features *)
38
+
("ocaml", ["functional"; "static typing"; "pattern matching"; "modules"; "type inference"]);
39
+
("python", ["dynamic typing"; "interpreted"; "object-oriented"; "high-level"; "scripting"]);
40
+
("rust", ["memory safety"; "performance"; "static typing"; "ownership"; "zero-cost abstractions"]);
41
+
("javascript", ["dynamic typing"; "interpreted"; "prototypes"; "single-threaded"; "event-driven"]);
42
+
("go", ["concurrency"; "garbage collection"; "simplicity"; "static typing"; "compiled"]);
45
+
(* Helper function to create a completion response *)
46
+
let create_completion values ?(has_more=false) ?(total=None) () =
50
+
has_more = Some has_more;
56
+
(* Define and register a tool that handles completions *)
57
+
let _ = add_tool server
59
+
~description:"Handles completion requests for programming languages and features"
60
+
~schema_properties:[
61
+
("argument_name", "string", "The name of the argument to complete");
62
+
("argument_value", "string", "The partial value to complete");
64
+
~schema_required:["argument_name"; "argument_value"]
67
+
let argument_name = get_string_param args "argument_name" in
68
+
let argument_value = get_string_param args "argument_value" in
70
+
Log.info (Printf.sprintf "Completion request for %s = %s" argument_name argument_value);
72
+
(* Handle different completion requests *)
74
+
match argument_name with
76
+
(* Complete programming language names *)
80
+
let lang_lower = String.lowercase_ascii lang in
81
+
let arg_lower = String.lowercase_ascii argument_value in
82
+
String.length lang_lower >= String.length arg_lower &&
83
+
String.sub lang_lower 0 (String.length arg_lower) = arg_lower)
86
+
let values = List.map fst matches in
87
+
create_completion values ~has_more:false ~total:(Some (List.length values)) ()
90
+
(* Complete programming language features *)
92
+
List.flatten (List.map snd languages) |>
93
+
List.sort_uniq String.compare
98
+
let feature_lower = String.lowercase_ascii feature in
99
+
let arg_lower = String.lowercase_ascii argument_value in
100
+
String.length feature_lower >= String.length arg_lower &&
101
+
String.sub feature_lower 0 (String.length arg_lower) = arg_lower)
104
+
create_completion matches ~has_more:false ~total:(Some (List.length matches)) ()
107
+
(* Default completions for unknown arguments *)
108
+
create_completion ["unknown argument"] ()
111
+
(* Convert to JSON and return *)
112
+
TextContent.yojson_of_t TextContent.{
113
+
text = Yojson.Safe.to_string (Completion.Result.to_result result);
118
+
Log.error (Printf.sprintf "Error handling completion request: %s" msg);
119
+
TextContent.yojson_of_t TextContent.{
120
+
text = Printf.sprintf "Error: %s" msg;
125
+
(* Define and register a prompt that provides programming language info *)
126
+
let _ = add_prompt server
127
+
~name:"language-info-prompt"
128
+
~description:"A prompt that provides information about programming languages"
130
+
("language", Some "Name of the programming language", true);
134
+
try List.assoc "language" args
135
+
with Not_found -> "ocaml" (* Default to OCaml *)
140
+
let features = List.assoc (String.lowercase_ascii language) languages in
141
+
String.concat ", " features
142
+
with Not_found -> "unknown language"
148
+
content = make_text_content (Printf.sprintf "Tell me about the %s programming language" language)
152
+
content = make_text_content (Printf.sprintf "%s is a programming language with the following features: %s" language features)
157
+
(* Main function *)
159
+
(* Print directly to ensure we see output *)
160
+
Printf.printf "Starting CompletionServer...\n";
163
+
(* Set custom capabilities to indicate support for completions *)
164
+
let capabilities = `Assoc [
165
+
("completions", `Assoc []); (* Indicate support for completions *)
166
+
("prompts", `Assoc [
167
+
("listChanged", `Bool true)
169
+
("resources", `Assoc [
170
+
("listChanged", `Bool true);
171
+
("subscribe", `Bool true)
174
+
("listChanged", `Bool true)
177
+
set_capabilities server capabilities;
179
+
(* Run the server *)