this repo has no description
6
fork

Configure Feed

Select the types of activity you want to include in your feed.

sample book to experiment with resource templates

+728
+728
bin/markdown_book_sdk.ml
··· 1 + open Mcp_sdk 2 + 3 + (* Helper module for working with markdown book chapters *) 4 + module BookChapter = struct 5 + type t = { 6 + id: string; 7 + title: string; 8 + contents: string; 9 + } 10 + 11 + (* Book chapters as a series of markdown files *) 12 + let chapters = [ 13 + { 14 + id = "chapter1"; 15 + title = "# Introduction to OCaml"; 16 + contents = {| 17 + # Introduction to OCaml 18 + 19 + OCaml is a general-purpose, multi-paradigm programming language which extends the Caml dialect of ML with object-oriented features. 20 + 21 + ## Key Features 22 + 23 + - **Strong Static Typing**: Catch errors at compile time rather than runtime 24 + - **Type Inference**: No need to annotate every variable with a type 25 + - **Pattern Matching**: Express complex control flow in a clear and concise way 26 + - **Functional Programming**: First-class functions and immutability 27 + - **Module System**: Powerful abstraction capabilities with modules and functors 28 + - **Performance**: Native code compilation with excellent performance characteristics 29 + 30 + ## History 31 + 32 + OCaml was created in 1996 by Xavier Leroy, Jérôme Vouillon, Damien Doligez, and Didier Rémy at INRIA in France. It evolved from the Caml language, which itself was an implementation of ML. 33 + 34 + ## Why OCaml? 35 + 36 + OCaml offers a unique combination of features that make it particularly well-suited for certain domains: 37 + 38 + - **Program Correctness**: The strong type system catches many errors at compile time 39 + - **Symbolic Computing**: Excellent for manipulating complex data structures and symbolic expressions 40 + - **Systems Programming**: Can be used for low-level systems programming with high safety guarantees 41 + - **Web Development**: Modern frameworks like Dream make web development straightforward 42 + 43 + In the following chapters, we'll explore the language features in depth and learn how to leverage OCaml's strengths for building robust, maintainable software. 44 + |} 45 + }; 46 + { 47 + id = "chapter2"; 48 + title = "# Basic Syntax and Types"; 49 + contents = {| 50 + # Basic Syntax and Types 51 + 52 + OCaml has a clean, consistent syntax that emphasizes readability and minimizes boilerplate. 53 + 54 + ## Variables and Basic Types 55 + 56 + In OCaml, variables are immutable by default. Once a value is bound to a name, that binding cannot change. 57 + 58 + ```ocaml 59 + (* Binding a value to a name *) 60 + let x = 42 61 + let greeting = "Hello, World!" 62 + 63 + (* OCaml has type inference *) 64 + (* These are equivalent: *) 65 + let x = 42 66 + let x : int = 42 67 + ``` 68 + 69 + ## Basic Types 70 + 71 + - `int`: Integer numbers 72 + - `float`: Floating-point numbers 73 + - `bool`: Boolean values (`true` or `false`) 74 + - `char`: Single characters 75 + - `string`: Text strings 76 + - `unit`: The empty tuple, written `()` 77 + 78 + ## Functions 79 + 80 + Functions in OCaml are first-class values: 81 + 82 + ```ocaml 83 + (* A simple function *) 84 + let add x y = x + y 85 + 86 + (* With type annotations *) 87 + let add (x : int) (y : int) : int = x + y 88 + 89 + (* Anonymous (lambda) function *) 90 + let increment = fun x -> x + 1 91 + 92 + (* Partial application *) 93 + let add5 = add 5 94 + let fifteen = add5 10 (* equals 15 *) 95 + ``` 96 + 97 + ## Control Flow 98 + 99 + OCaml uses expressions rather than statements for control flow: 100 + 101 + ```ocaml 102 + (* If expression *) 103 + let abs x = 104 + if x < 0 then -x else x 105 + 106 + (* Match expression (pattern matching) *) 107 + let describe_sign x = 108 + match x with 109 + | x when x < 0 -> "negative" 110 + | 0 -> "zero" 111 + | _ -> "positive" 112 + ``` 113 + 114 + ## Recursion 115 + 116 + Functions need the `rec` keyword to be recursive: 117 + 118 + ```ocaml 119 + (* Recursive function *) 120 + let rec factorial n = 121 + if n <= 1 then 1 else n * factorial (n - 1) 122 + 123 + (* Mutually recursive functions *) 124 + let rec is_even n = 125 + if n = 0 then true else is_odd (n - 1) 126 + and is_odd n = 127 + if n = 0 then false else is_even (n - 1) 128 + ``` 129 + 130 + This introduction to basic syntax sets the foundation for understanding OCaml's more advanced features, which we'll explore in the next chapters. 131 + |} 132 + }; 133 + { 134 + id = "chapter3"; 135 + title = "# Data Structures"; 136 + contents = {| 137 + # Data Structures 138 + 139 + OCaml provides several built-in data structures and makes it easy to define custom ones. 140 + 141 + ## Tuples 142 + 143 + Tuples are fixed-length collections of values that can have different types: 144 + 145 + ```ocaml 146 + (* A pair of an int and a string *) 147 + let person = (42, "Alice") 148 + 149 + (* Extracting values with pattern matching *) 150 + let (age, name) = person 151 + 152 + (* Accessing elements *) 153 + let age = fst person (* For pairs only *) 154 + let name = snd person (* For pairs only *) 155 + ``` 156 + 157 + ## Records 158 + 159 + Records are named collections of values: 160 + 161 + ```ocaml 162 + (* Defining a record type *) 163 + type person = { 164 + name: string; 165 + age: int; 166 + email: string option; 167 + } 168 + 169 + (* Creating a record *) 170 + let alice = { 171 + name = "Alice"; 172 + age = 42; 173 + email = Some "alice@example.com"; 174 + } 175 + 176 + (* Accessing fields *) 177 + let alices_name = alice.name 178 + 179 + (* Functional update (creates a new record) *) 180 + let alice_birthday = { alice with age = alice.age + 1 } 181 + ``` 182 + 183 + ## Variants 184 + 185 + Variants (also called algebraic data types) represent values that can be one of several cases: 186 + 187 + ```ocaml 188 + (* Defining a variant type *) 189 + type shape = 190 + | Circle of float (* radius *) 191 + | Rectangle of float * float (* width, height *) 192 + | Triangle of float * float * float (* sides *) 193 + 194 + (* Creating variants *) 195 + let my_circle = Circle 2.5 196 + let my_rectangle = Rectangle (4.0, 6.0) 197 + 198 + (* Pattern matching with variants *) 199 + let area shape = 200 + match shape with 201 + | Circle r -> Float.pi *. r *. r 202 + | Rectangle (w, h) -> w *. h 203 + | Triangle (a, b, c) -> 204 + let s = (a +. b +. c) /. 2.0 in 205 + sqrt (s *. (s -. a) *. (s -. b) *. (s -. c)) 206 + ``` 207 + 208 + ## Lists 209 + 210 + Lists are immutable linked lists of elements of the same type: 211 + 212 + ```ocaml 213 + (* Creating lists *) 214 + let empty = [] 215 + let numbers = [1; 2; 3; 4; 5] 216 + let constructed = 1 :: 2 :: 3 :: [] 217 + 218 + (* Pattern matching with lists *) 219 + let rec sum_list lst = 220 + match lst with 221 + | [] -> 0 222 + | head :: tail -> head + sum_list tail 223 + 224 + (* Common list functions *) 225 + let doubled = List.map (fun x -> x * 2) numbers 226 + let evens = List.filter (fun x -> x mod 2 = 0) numbers 227 + let sum = List.fold_left (+) 0 numbers 228 + ``` 229 + 230 + ## Arrays 231 + 232 + Arrays provide mutable, fixed-size collections with O(1) random access: 233 + 234 + ```ocaml 235 + (* Creating arrays *) 236 + let arr = [|1; 2; 3; 4; 5|] 237 + 238 + (* Accessing elements (0-indexed) *) 239 + let first = arr.(0) 240 + 241 + (* Modifying elements *) 242 + let () = arr.(0) <- 10 243 + 244 + (* Array functions *) 245 + let doubled = Array.map (fun x -> x * 2) arr 246 + ``` 247 + 248 + ## Option Type 249 + 250 + The option type represents values that might be absent: 251 + 252 + ```ocaml 253 + (* Option type *) 254 + type 'a option = None | Some of 'a 255 + 256 + (* Using options *) 257 + let safe_divide x y = 258 + if y = 0 then None else Some (x / y) 259 + 260 + (* Working with options *) 261 + match safe_divide 10 2 with 262 + | None -> print_endline "Division by zero" 263 + | Some result -> Printf.printf "Result: %d\n" result 264 + ``` 265 + 266 + These data structures form the backbone of OCaml programming and allow for expressing complex data relationships in a type-safe way. 267 + |} 268 + }; 269 + { 270 + id = "chapter4"; 271 + title = "# Modules and Functors"; 272 + contents = {| 273 + # Modules and Functors 274 + 275 + OCaml's module system is one of its most powerful features. It allows for organizing code into reusable components with clear interfaces. 276 + 277 + ## Basic Modules 278 + 279 + A module is a collection of related definitions (types, values, submodules, etc.): 280 + 281 + ```ocaml 282 + (* Defining a module *) 283 + module Math = struct 284 + let pi = 3.14159 285 + let square x = x *. x 286 + let cube x = x *. x *. x 287 + end 288 + 289 + (* Using a module *) 290 + let area_of_circle r = Math.pi *. Math.square r 291 + ``` 292 + 293 + ## Module Signatures 294 + 295 + Module signatures define the interface of a module, hiding implementation details: 296 + 297 + ```ocaml 298 + (* Defining a signature *) 299 + module type MATH = sig 300 + val pi : float 301 + val square : float -> float 302 + val cube : float -> float 303 + end 304 + 305 + (* Implementing a signature *) 306 + module Math : MATH = struct 307 + let pi = 3.14159 308 + let square x = x *. x 309 + let cube x = x *. x *. x 310 + 311 + (* This is hidden because it's not in the signature *) 312 + let private_helper x = x +. 1.0 313 + end 314 + ``` 315 + 316 + ## Functors 317 + 318 + Functors are functions from modules to modules, allowing for higher-order modularity: 319 + 320 + ```ocaml 321 + (* Module signature for collections *) 322 + module type COLLECTION = sig 323 + type 'a t 324 + val empty : 'a t 325 + val add : 'a -> 'a t -> 'a t 326 + val mem : 'a -> 'a t -> bool 327 + end 328 + 329 + (* Functor that creates a set implementation given an element type with comparison *) 330 + module MakeSet (Element : sig type t val compare : t -> t -> int end) : COLLECTION with type 'a t = Element.t list = struct 331 + type 'a t = Element.t list 332 + 333 + let empty = [] 334 + 335 + let rec add x lst = 336 + match lst with 337 + | [] -> [x] 338 + | y :: ys -> 339 + let c = Element.compare x y in 340 + if c < 0 then x :: lst 341 + else if c = 0 then lst (* Element already exists *) 342 + else y :: add x ys 343 + 344 + let rec mem x lst = 345 + match lst with 346 + | [] -> false 347 + | y :: ys -> 348 + let c = Element.compare x y in 349 + if c = 0 then true 350 + else if c < 0 then false 351 + else mem x ys 352 + end 353 + 354 + (* Creating an integer set *) 355 + module IntElement = struct 356 + type t = int 357 + let compare = Int.compare 358 + end 359 + 360 + module IntSet = MakeSet(IntElement) 361 + 362 + (* Using the set *) 363 + let my_set = IntSet.empty 364 + |> IntSet.add 3 365 + |> IntSet.add 1 366 + |> IntSet.add 4 367 + |> IntSet.add 1 (* Duplicate, not added *) 368 + 369 + let has_three = IntSet.mem 3 my_set (* true *) 370 + let has_five = IntSet.mem 5 my_set (* false *) 371 + ``` 372 + 373 + ## First-Class Modules 374 + 375 + OCaml also supports first-class modules, allowing modules to be passed as values: 376 + 377 + ```ocaml 378 + (* Module type for number operations *) 379 + module type NUMBER = sig 380 + type t 381 + val zero : t 382 + val add : t -> t -> t 383 + val to_string : t -> string 384 + end 385 + 386 + (* Implementations for different number types *) 387 + module Int : NUMBER with type t = int = struct 388 + type t = int 389 + let zero = 0 390 + let add = (+) 391 + let to_string = string_of_int 392 + end 393 + 394 + module Float : NUMBER with type t = float = struct 395 + type t = float 396 + let zero = 0.0 397 + let add = (+.) 398 + let to_string = string_of_float 399 + end 400 + 401 + (* Function that works with any NUMBER module *) 402 + let sum_as_string (type a) (module N : NUMBER with type t = a) numbers = 403 + let sum = List.fold_left N.add N.zero numbers in 404 + N.to_string sum 405 + 406 + (* Using first-class modules *) 407 + let int_sum = sum_as_string (module Int) [1; 2; 3; 4] 408 + let float_sum = sum_as_string (module Float) [1.0; 2.5; 3.7] 409 + ``` 410 + 411 + ## Open and Include 412 + 413 + OCaml provides ways to bring module contents into scope: 414 + 415 + ```ocaml 416 + (* Open brings module contents into scope temporarily *) 417 + let area = 418 + let open Math in 419 + pi *. square 2.0 420 + 421 + (* Local opening with the modern syntax *) 422 + let area = Math.(pi *. square 2.0) 423 + 424 + (* Include actually extends a module with another module's contents *) 425 + module ExtendedMath = struct 426 + include Math 427 + let tau = 2.0 *. pi 428 + let circumference r = tau *. r 429 + end 430 + ``` 431 + 432 + The module system enables OCaml programmers to build highly modular, reusable code with clear boundaries between components. 433 + |} 434 + }; 435 + { 436 + id = "chapter5"; 437 + title = "# Advanced Features"; 438 + contents = {| 439 + # Advanced Features 440 + 441 + OCaml offers several advanced features that set it apart from other languages. This chapter explores some of the more powerful language constructs. 442 + 443 + ## Polymorphic Variants 444 + 445 + Unlike regular variants, polymorphic variants don't need to be predefined: 446 + 447 + ```ocaml 448 + (* Using polymorphic variants directly *) 449 + let weekend = `Saturday | `Sunday 450 + let is_weekend day = 451 + match day with 452 + | `Saturday | `Sunday -> true 453 + | `Monday .. `Friday -> false 454 + 455 + (* Can be used in mixed contexts *) 456 + let shape_area = function 457 + | `Circle r -> Float.pi *. r *. r 458 + | `Rectangle (w, h) -> w *. h 459 + | `Triangle (b, h) -> 0.5 *. b *. h 460 + | `Regular_polygon(n, s) when n >= 3 -> 461 + let apothem = s /. (2.0 *. tan (Float.pi /. float_of_int n)) in 462 + n *. s *. apothem /. 2.0 463 + | _ -> failwith "Invalid shape" 464 + ``` 465 + 466 + ## Objects and Classes 467 + 468 + OCaml supports object-oriented programming: 469 + 470 + ```ocaml 471 + (* Simple class definition *) 472 + class point x_init y_init = 473 + object (self) 474 + val mutable x = x_init 475 + val mutable y = y_init 476 + 477 + method get_x = x 478 + method get_y = y 479 + method move dx dy = x <- x + dx; y <- y + dy 480 + method distance_from_origin = 481 + sqrt (float_of_int (x * x + y * y)) 482 + 483 + (* Private method *) 484 + method private to_string = 485 + Printf.sprintf "(%d, %d)" x y 486 + 487 + (* Calling another method *) 488 + method print = print_endline self#to_string 489 + end 490 + 491 + (* Using a class *) 492 + let p = new point 3 4 493 + let () = p#move 2 1 494 + let d = p#distance_from_origin 495 + ``` 496 + 497 + ## Generalized Algebraic Data Types (GADTs) 498 + 499 + GADTs provide more type control than regular variants: 500 + 501 + ```ocaml 502 + (* A GADT for type-safe expressions *) 503 + type _ expr = 504 + | Int : int -> int expr 505 + | Bool : bool -> bool expr 506 + | Add : int expr * int expr -> int expr 507 + | Eq : 'a expr * 'a expr -> bool expr 508 + 509 + (* Type-safe evaluation *) 510 + let rec eval : type a. a expr -> a = function 511 + | Int n -> n 512 + | Bool b -> b 513 + | Add (e1, e2) -> eval e1 + eval e2 514 + | Eq (e1, e2) -> eval e1 = eval e2 515 + 516 + (* These expressions are statically type-checked *) 517 + let e1 = Add (Int 1, Int 2) (* OK: int expr *) 518 + let e2 = Eq (Int 1, Int 2) (* OK: bool expr *) 519 + (* let e3 = Add (Int 1, Bool true) (* Type error! *) *) 520 + (* let e4 = Eq (Int 1, Bool true) (* Type error! *) *) 521 + ``` 522 + 523 + ## Type Extensions 524 + 525 + OCaml allows extending existing types: 526 + 527 + ```ocaml 528 + (* Original type *) 529 + type shape = Circle of float | Rectangle of float * float 530 + 531 + (* Extending the type in another module *) 532 + type shape += Triangle of float * float * float 533 + 534 + (* Pattern matching must now handle unknown cases *) 535 + let area = function 536 + | Circle r -> Float.pi *. r *. r 537 + | Rectangle (w, h) -> w *. h 538 + | Triangle (a, b, c) -> 539 + let s = (a +. b +. c) /. 2.0 in 540 + sqrt (s *. (s -. a) *. (s -. b) *. (s -. c)) 541 + | _ -> failwith "Unknown shape" 542 + ``` 543 + 544 + ## Effects and Effect Handlers 545 + 546 + OCaml 5 introduced algebraic effects for managing control flow: 547 + 548 + ```ocaml 549 + (* Defining an effect *) 550 + type _ Effect.t += Ask : string -> string Effect.t 551 + 552 + (* Handler for the Ask effect *) 553 + let prompt_user () = 554 + Effect.Deep.try_with 555 + (fun () -> 556 + let name = Effect.perform (Ask "What is your name?") in 557 + Printf.printf "Hello, %s!\n" name) 558 + { Effect.Deep.effc = fun (type a) (effect : a Effect.t) -> 559 + match effect with 560 + | Ask prompt -> fun k -> 561 + Printf.printf "%s " prompt; 562 + let response = read_line () in 563 + k response 564 + | _ -> None } 565 + ``` 566 + 567 + ## Higher-Ranked Polymorphism 568 + 569 + Using the `Obj.magic` escape hatch (with caution): 570 + 571 + ```ocaml 572 + (* This would normally not be permitted due to rank-2 polymorphism *) 573 + let apply_to_all_types f = 574 + let magic_f : 'a -> string = Obj.magic f in 575 + [ 576 + magic_f 42; 577 + magic_f "hello"; 578 + magic_f 3.14; 579 + magic_f true; 580 + ] 581 + 582 + (* Usage - with great care! *) 583 + let result = apply_to_all_types (fun x -> Printf.sprintf "Value: %s" (Obj.magic x)) 584 + ``` 585 + 586 + ## Metaprogramming with PPX 587 + 588 + OCaml's PPX system enables powerful metaprogramming: 589 + 590 + ```ocaml 591 + (* With ppx_deriving *) 592 + type person = { 593 + name: string; 594 + age: int; 595 + email: string option; 596 + } [@@deriving show, eq, ord] 597 + 598 + (* With ppx_sexp_conv *) 599 + type config = { 600 + server: string; 601 + port: int; 602 + timeout: float; 603 + } [@@deriving sexp] 604 + 605 + (* With ppx_let for monadic operations *) 606 + let computation = 607 + [%m.let 608 + let* x = get_value_from_db "key1" in 609 + let* y = get_value_from_db "key2" in 610 + return (x + y) 611 + ] 612 + ``` 613 + 614 + ## Modules for Advanced Typing 615 + 616 + Using modules to encode complex type relationships: 617 + 618 + ```ocaml 619 + (* Phantom types for added type safety *) 620 + module SafeString : sig 621 + type 'a t 622 + 623 + (* Constructors for different string types *) 624 + val of_raw : string -> [`Raw] t 625 + val sanitize : [`Raw] t -> [`Sanitized] t 626 + val validate : [`Sanitized] t -> [`Validated] t option 627 + 628 + (* Operations that require specific string types *) 629 + val to_html : [`Sanitized] t -> string 630 + val to_sql : [`Validated] t -> string 631 + 632 + (* Common operations for all string types *) 633 + val length : _ t -> int 634 + val concat : _ t -> _ t -> [`Raw] t 635 + end = struct 636 + type 'a t = string 637 + 638 + let of_raw s = s 639 + let sanitize s = String.map (function '<' | '>' -> '_' | c -> c) s 640 + let validate s = if String.length s > 0 then Some s else None 641 + 642 + let to_html s = s 643 + let to_sql s = "'" ^ String.map (function '\'' -> '\'' | c -> c) s ^ "'" 644 + 645 + let length = String.length 646 + let concat s1 s2 = s1 ^ s2 647 + end 648 + ``` 649 + 650 + These advanced features make OCaml a uniquely powerful language for expressing complex programs with strong guarantees about correctness. 651 + |} 652 + }; 653 + ] 654 + 655 + (* Get a chapter by ID *) 656 + let get_by_id id = 657 + try Some (List.find (fun c -> c.id = id) chapters) 658 + with Not_found -> None 659 + 660 + (* Get chapter titles *) 661 + let get_all_titles () = 662 + List.map (fun c -> (c.id, c.title)) chapters 663 + end 664 + 665 + (* Create a server *) 666 + let server = create_server 667 + ~name:"OCaml MCP Book Resource Example" 668 + ~version:"0.1.0" () |> 669 + fun server -> 670 + (* Set default capabilities *) 671 + configure_server server 672 + ~with_tools:false 673 + ~with_resources:true 674 + ~with_resource_templates:true 675 + ~with_prompts:false () 676 + 677 + (* Add a resource template to get book chapters *) 678 + let _ = add_resource_template server 679 + ~uri_template:"book/chapter/{id}" 680 + ~name:"Chapter Resource" 681 + ~description:"Get a specific chapter from the OCaml book by its ID" 682 + ~mime_type:"text/markdown" 683 + (fun params -> 684 + match params with 685 + | [id] -> 686 + (match BookChapter.get_by_id id with 687 + | Some chapter -> chapter.contents 688 + | None -> Printf.sprintf "# Error\n\nChapter with ID '%s' not found." id) 689 + | _ -> "# Error\n\nInvalid parameters. Expected chapter ID." 690 + ) 691 + 692 + (* Add a regular resource to get table of contents (no variables) *) 693 + let _ = add_resource server 694 + ~uri:"book/toc" 695 + ~name:"Table of Contents" 696 + ~description:"Get the table of contents for the OCaml book" 697 + ~mime_type:"text/markdown" 698 + (fun _params -> 699 + let titles = BookChapter.get_all_titles() in 700 + let toc = "# OCaml Book - Table of Contents\n\n" ^ 701 + (List.mapi (fun i (id, title) -> 702 + Printf.sprintf "%d. [%s](book/chapter/%s)\n" 703 + (i + 1) 704 + (String.sub title 2 (String.length title - 2)) (* Remove "# " prefix *) 705 + id 706 + ) titles |> String.concat "") 707 + in 708 + toc 709 + ) 710 + 711 + (* Add a regular resource for a complete book (no variables) *) 712 + let _ = add_resource server 713 + ~uri:"book/complete" 714 + ~name:"Full contents" 715 + ~description:"Get the complete OCaml book as a single document" 716 + ~mime_type:"text/markdown" 717 + (fun _params -> 718 + let chapter_contents = List.map (fun c -> c.BookChapter.contents) BookChapter.chapters in 719 + let content = "# The OCaml Book\n\n*A comprehensive guide to OCaml programming*\n\n" ^ 720 + (String.concat "\n\n---\n\n" chapter_contents) 721 + in 722 + content 723 + ) 724 + 725 + (* Run the server with the default scheduler *) 726 + let () = 727 + Eio_main.run @@ fun env -> 728 + Mcp_server.run_server env server