|
3 | 3 | [mcp-toolkit.server:as server] |
4 | 4 | [mcp-toolkit.json-rpc:as json-rpc] |
5 | 5 | [promesa.core:as p] |
| 6 | + [example.server-content:as content] |
6 | 7 | #?(:clj [jsonista.core:as j]) |
7 | 8 | #?(:clj [nrepl.server:as nrepl])) |
8 | 9 | #?(:clj (:import (clojure.lang LineNumberingPushbackReader) |
9 | 10 | (java.io OutputStreamWriter)))) |
10 | 11 |
|
11 | 12 | ;; Example of usage of this library. |
12 | 13 |
|
13 | | -(deftalk-like-pirate-prompt |
14 | | - {:name"pirate_mode_prompt" |
15 | | -:description"Talk like a pirate prompt" |
16 | | -:arguments [{:name"expressions" |
17 | | -:description"Comma-separated expressions" |
18 | | -:requiredfalse}] |
19 | | -:complete-fn (fn [context name value] |
20 | | - (when (= name"expressions") |
21 | | - (when-not (str/includes? name"!") |
22 | | - {:completion {:values [(str value"!") |
23 | | - (str value"~#!") |
24 | | - (str value"!#@!!")] |
25 | | -:total3 |
26 | | -:hasMorefalse}}))) |
27 | | -:prompt-fn (fn [context {:keys [expressions]}] |
28 | | - {:description (str"A talk-like-a-pirate prompt which includes the expressions:" expressions) |
29 | | -:messages [{:role"user" |
30 | | -:content {:type"text" |
31 | | -:text (->> ["You are a sea pirate and you need to talk to the user in a tone that reassembles talk-like-a-pirate style." |
32 | | - (when-not (str/blank? expressions) |
33 | | - (str"You also need to randomly use the following expressions every few sentences:" expressions".")) |
34 | | - (str"Start by introducing yourself in a spectacular way and talk about your pet parrot sitting on your shoulder." |
35 | | -"Ask the user to choose a new and creative name for the parrot.")] |
36 | | - (filter some?) |
37 | | - (str/join""))}}]})}) |
38 | | - |
39 | | -(defhello-doc-resource |
40 | | - {:uri"file:///doc/hello.md" |
41 | | -:name"hello.md" |
42 | | -:description"First part of the\"hello world\" resources" |
43 | | -:mimeType"text/markdown; charset=UTF-8" |
44 | | -;;:blob ,,, |
45 | | -:text"Hello"}) |
46 | | - |
47 | | -(defworld-doc-resource |
48 | | - {:uri"file:///doc/world.md" |
49 | | -:name"world.md" |
50 | | -:description"Second part of the\"hello world\" resources" |
51 | | -:mimeType"text/markdown; charset=UTF-8" |
52 | | -;;:blob ,,, |
53 | | -:text"world!"}) |
54 | | - |
55 | | -(defmy-resource-templates |
56 | | - [{:uriTemplate"file:///doc/{path}" |
57 | | -:name"Documentation files" |
58 | | -:description"The documentation files" |
59 | | -:mimeType"text/markdown; charset=UTF-8"}]) |
60 | | - |
61 | | -(defnmy-resource-uri-complete-fn [context uri name value] |
62 | | - (when (and (= uri"file:///doc/{path}") |
63 | | - (= name"path")) |
64 | | - (let [paths ["hello.md""world.md"] |
65 | | - values (filterv (fn [path] (str/starts-with? path value)) paths)] |
66 | | - {:completion {:values (take100 values) |
67 | | -:total (count values) |
68 | | -:hasMore (> (count values)100)}}))) |
69 | | - |
70 | | -(defparentify-tool |
71 | | - {:name"parentify" |
72 | | -:description"Parentify a text: wraps a text within parenthesis." |
73 | | -:inputSchema {:type"object" |
74 | | -:properties {:text {:type"string" |
75 | | -:description"the text to be parentified"}} |
76 | | -:required [:text]} |
77 | | -:tool-fn (fn [context arguments] |
78 | | - (-> (p/let [text (str"(" (:text arguments)")") |
79 | | - _ (p/delay1000) |
80 | | - _ (server/notify-progress context {:progress1 |
81 | | -:total3 |
82 | | -:message"thinking ..."}) |
83 | | - _ (p/delay1000) |
84 | | - _ (server/notify-progress context {:progress2 |
85 | | -:total3 |
86 | | -:message"thinking harder ..."}) |
87 | | - _ (when @(:is-cancelled context) |
88 | | - (throw (ex-info"tool was cancelled" {:note"too bad, was almost done"}))) |
89 | | - |
90 | | - _ (p/delay1000)] |
91 | | - {:content [{:type"text" |
92 | | -:text text}] |
93 | | -:isErrorfalse}) |
94 | | - (p/catch (fn [exception] |
95 | | - {:content [{:type"text" |
96 | | -:text (str"Something went wrong:" (ex-message exception))}] |
97 | | -:isErrortrue}))))}) |
98 | | - |
99 | 14 | ;; |
100 | 15 | ;; State |
101 | 16 | ;; |
102 | 17 |
|
103 | 18 | (defsession |
104 | 19 | (atom |
105 | | - (server/create-session {:prompts [talk-like-pirate-prompt] |
106 | | -:resources [hello-doc-resource |
107 | | - world-doc-resource] |
108 | | -:tools [parentify-tool] |
109 | | -:resource-templates my-resource-templates |
110 | | -:resource-uri-complete-fn my-resource-uri-complete-fn}))) |
| 20 | + (server/create-session {:prompts [content/talk-like-pirate-prompt] |
| 21 | +:resources [content/hello-doc-resource |
| 22 | +content/world-doc-resource] |
| 23 | +:tools [content/parentify-tool] |
| 24 | +:resource-templatescontent/my-resource-templates |
| 25 | +:resource-uri-complete-fncontent/my-resource-uri-complete-fn}))) |
111 | 26 |
|
112 | 27 | ;; |
113 | 28 | ;; Platform-specific threading, transport & I/O stuffs |
|