Skip to content

Commit 0d13e18

Browse files
qrencode accepts arguments
1 parent 761005b commit 0d13e18

File tree

5 files changed

+52
-25
lines changed

5 files changed

+52
-25
lines changed

prompts/examples/qrencode.md

+12-5
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
11
---
2+
name: qrencode
3+
description: Generate QR codes
24
tools:
35
- name: qrencode
6+
arguments:
7+
- name: content
8+
description: the content to encode in the QR code
9+
required: true
10+
parameter-values:
11+
content: https://github.com/docker/labs-ai-tools-for-devs
412
---
513

6-
# Prompt user
14+
# prompt
715

8-
Generate a QR code for the content
9-
'https://github.com/docker/labs-ai-tools-for-devs'.
10-
Save the generated image to `qrcode.png`.
16+
Generate a QR code for the content '{{content}}'.
17+
Save the generated image to `/thread/resources/qrcode.png`.
1118
If the command fails, read the man page and try again.
1219
If successful, output the path to the generated image in markdown syntax.
1320

@@ -16,6 +23,6 @@ If successful, output the path to the generated image in markdown syntax.
1623
After running the above prompt, there should be a file named `qrcode.png` in the current project's host directory.
1724

1825
```bash
19-
open ~/vonwig/altaservice/qrcode.png
26+
open ~/docker/labs-ai-tools-for-devs/qrcode.png
2027
```
2128

src/graph.clj

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
(let [[chunk-handler sample] (providers (llm-provider (or (:model metadata) model)))
4949
[c h] (chunk-handler)
5050
request (merge
51-
(dissoc metadata :agent :host-dir :workdir :prompt-format :description :name :parameter-values) ; TODO should we just select relevant keys instead of removing bad ones
51+
(dissoc metadata :agent :host-dir :workdir :prompt-format :description :name :parameter-values :arguments) ; TODO should we just select relevant keys instead of removing bad ones
5252
{:messages messages
5353
:level level}
5454
(when (seq functions) {:tools functions})

src/jsonrpc/db.clj

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
(add {:register ["github:docker/labs-ai-tools-for-devs?path=prompts/examples/explain_dockerfile.md"
3939
"github:docker/labs-ai-tools-for-devs?path=prompts/examples/hello_world.md"]}))
4040

41+
#_{:clj-kondo/ignore [:redefined-var]}
4142
(defn merge [{:keys [registry-content] :as opts}]
4243
(logger/info "adding dynamic prompts" registry-content)
4344
(try

src/jsonrpc/server.clj

+8-13
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@
7474
;; merges client-info capabilities and client protocol-version
7575
(swap! db* merge params)
7676
{:protocol-version "2024-11-05"
77-
:capabilities {:prompts {}
78-
:tools {}}
77+
:capabilities {:prompts {:listChanged true}
78+
:tools {:listChanged true}}
7979
:server-info {:name "docker-mcp-server"
8080
:version "0.0.1"}})
8181

@@ -96,29 +96,24 @@
9696
(defn entry->prompt-listing [k v _messages]
9797
(merge
9898
{:name (str k)}
99-
(select-keys (:metadata v) [:description])))
99+
(select-keys (:metadata v) [:description :arguments])))
100100

101101
(defmethod lsp.server/receive-request "prompts/list" [_ {:keys [db*]} params]
102102
;; TODO might contain a cursor
103103
(logger/info "prompts/list" params)
104104
(let [prompts
105105
{:prompts (->> (:mcp.prompts/registry @db*)
106-
(mapcat (fn [[k v]] (map (partial entry->prompt-listing k v) (:messages v))))
106+
(mapcat
107+
(fn [[k v]] (map (partial entry->prompt-listing k v) (:messages v))))
107108
(into []))}]
108109
(logger/info prompts)
109110
prompts))
110111

111-
(defmethod lsp.server/receive-request "prompts/get" [_ {:keys [db*]} {:keys [name]}]
112-
;; TODO resolve arguments
112+
(defmethod lsp.server/receive-request "prompts/get" [_ {:keys [db*]} {:keys [name arguments]}]
113113
(logger/info "prompts/get " name)
114-
(let [{:keys [messages metadata] :as entry} (-> @db* :mcp.prompts/registry (get name))]
114+
(let [{:keys [prompt-function metadata]} (-> @db* :mcp.prompts/registry (get name))]
115115
{:description (or (:description metadata) name)
116-
:messages (->> messages
117-
(map (fn [m] (-> m
118-
(update :content (fn [content]
119-
{:type "text"
120-
:text content})))))
121-
(into []))}))
116+
:messages (prompt-function (or arguments {}))}))
122117

123118
(defmethod lsp.server/receive-request "resources/list" [_ _ _]
124119
{:resources []})

src/prompts.clj

+30-6
Original file line numberDiff line numberDiff line change
@@ -154,9 +154,20 @@
154154

155155
(def prompt-file-pattern #".*_(.*)_.*.md")
156156

157+
(defn ->message [{:keys [content] :as m}] (assoc m :content {:text content :type "text"}))
158+
157159
(defn get-prompts
158-
"run extractors and then render prompt templates
159-
returns map of messages, functions, metadata and optionally error"
160+
"run extractors and then render prompt templates (possibly)
161+
parameters
162+
mandatory
163+
either prompts or prompt-content
164+
prompts should be a markdown file
165+
prompts used to be a directory but that's deprecated
166+
optional
167+
user, platform, host-dir - create default facts for template rendering]
168+
parameters - external params bound at rendering time
169+
170+
returns a :schema/prompts-file"
160171
[{:keys [parameters prompts user platform host-dir prompt-content] :as opts}]
161172
(let [{:keys [metadata] :as prompt-data}
162173
(cond
@@ -184,16 +195,29 @@
184195
parameters
185196
(-> metadata :parameter-values))
186197
renderer (if (= "django" (:prompt-format metadata))
187-
(partial selmer-render (facts m user platform host-dir))
188-
(partial moustache-render prompts (facts m user platform host-dir)))]
198+
(fn [arguments message]
199+
(selmer-render (merge (facts m user platform host-dir) arguments) message))
200+
(fn [arguments message]
201+
(moustache-render prompts (merge (facts m user platform host-dir) arguments) message)))]
189202
((schema/validate :schema/prompts-file)
190203
(-> prompt-data
191-
(update :messages #(map renderer %))
204+
((fn [m] (assoc m :prompt-function (fn [arguments]
205+
(->> (:messages m)
206+
(map (comp ->message (partial renderer arguments)))
207+
(into []))))))
208+
(update :messages #(map (partial renderer {}) %))
192209
(update :metadata dissoc :functions :tools :extractors)
193210
(assoc :functions (->> (or (:tools metadata) (:functions metadata)) (mapcat function-definition)))))))
194211

195212
(comment
196213
(get-prompts {:prompts (fs/file "./prompts/examples/curl.md")})
197214
(get-prompts {:prompts (fs/file "./prompts/examples/generate-dockerfile.md")})
198-
(get-prompts {:prompts (fs/file "./README.md")}))
215+
(get-prompts {:prompts (fs/file "./README.md")})
216+
(=
217+
((:prompt-function (get-prompts {:prompts (fs/file "./prompts/examples/qrencode.md")})) {:content "mycontent"})
218+
[{:role "user",
219+
:content
220+
{:text
221+
"\nGenerate a QR code for the content 'mycontent'.\nSave the generated image to `/thread/resources/qrcode.png`.\nIf the command fails, read the man page and try again.\nIf successful, output the path to the generated image in markdown syntax.",
222+
:type "text"}}]))
199223

0 commit comments

Comments
 (0)