Skip to content

Commit 0e6276c

Browse files
Python servers require the initialized notification
1 parent 8d1e7dd commit 0e6276c

File tree

9 files changed

+253
-182
lines changed

9 files changed

+253
-182
lines changed

runbook.md

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,10 @@
1-
```sh
2-
docker buildx build \
3-
--builder hydrobuild \
4-
--platform linux/amd64,linux/arm64 \
5-
--tag mcp/docker:0.0.1 \
6-
--file Dockerfile \
7-
--push .
8-
docker pull mcp/docker:0.0.1
9-
```
101

112
```sh
123
cd src/extension && make build-extension
134
```
145

156
```sh
16-
docker extension update docker/labs-ai-tools-for-devs:0.2.7
7+
docker extension update docker/labs-ai-tools-for-devs:0.2.8
178
```
189

1910
```sh
@@ -32,10 +23,10 @@ docker pull mcp/docker:prerelease
3223
docker buildx build \
3324
--builder hydrobuild \
3425
--platform linux/amd64,linux/arm64 \
35-
--tag mcp/docker:0.0.1 \
26+
--tag mcp/docker:0.0.4 \
3627
--file Dockerfile \
3728
--push .
38-
docker pull mcp/docker:0.0.1
29+
docker pull mcp/docker:0.0.4
3930
```
4031

4132
```sh

src/docker.clj

Lines changed: 49 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -283,26 +283,6 @@
283283
(def pull (comp (status? 200 "pull-image") pull-image))
284284
(def images (comp ->json list-images))
285285

286-
(defn injected-entrypoint [secrets s]
287-
(format "%s ; %s"
288-
(->> secrets
289-
(map (fn [[k v]]
290-
(format "export %s=$(cat /secret/%s | sed -e \"s/^[[:space:]]*//\")" v (name k))))
291-
(string/join " ; "))
292-
s))
293-
294-
(defn inject-secret-transform [container-definition]
295-
(let [{:keys [Entrypoint Cmd]}
296-
(->
297-
(image-inspect
298-
(-> (images {"reference" [(:image container-definition)]})
299-
first))
300-
:Config)
301-
real-entrypoint (string/join " " (concat Entrypoint (or (:command container-definition) Cmd)))]
302-
(-> container-definition
303-
(assoc :entrypoint ["/bin/sh" "-c" (injected-entrypoint (:secrets container-definition) real-entrypoint)])
304-
(dissoc :command))))
305-
306286
(defn add-latest [image]
307287
(let [[_ tag] (re-find #".*(:.*)$" image)]
308288
(if tag
@@ -331,11 +311,56 @@
331311
(and digest (= digest Id))))
332312
(images {}))))
333313

314+
(defn check-then-pull [container-definition]
315+
(when (not (has-image? (:image container-definition)))
316+
(-pull container-definition)))
317+
318+
(defn injected-entrypoint [secrets environment s]
319+
(->> (concat
320+
(let [s (->> secrets
321+
(map (fn [[k v]]
322+
(format "export %s=$(cat /secret/%s | sed -e \"s/^[[:space:]]*//\")" v (name k))))
323+
(string/join " ; "))]
324+
(when (and s (not (= "" s)))
325+
[s]))
326+
(let [env (->> environment
327+
(map (fn [s] (when-let [[_ k v] (and s (re-find #"(.*)=(.*)" s))]
328+
[k v])))
329+
(filter identity)
330+
(map (fn [[k v]]
331+
(format "export %s=%s" k v)))
332+
(string/join " ; "))]
333+
(when (and env (not (= "" env)))
334+
[env]))
335+
[s])
336+
(string/join " ; ")))
337+
338+
(comment
339+
(injected-entrypoint {:a "A"} ["BLAH=whatever"] "my command")
340+
(injected-entrypoint nil nil "my command")
341+
(injected-entrypoint {:a "A"} nil "my command")
342+
(injected-entrypoint nil nil nil)
343+
)
344+
345+
(defn inject-secret-transform [container-definition]
346+
(check-then-pull container-definition)
347+
(let [{:keys [Entrypoint Cmd Env]}
348+
(->
349+
(image-inspect
350+
(-> (images {"reference" [(:image container-definition)]})
351+
first))
352+
:Config)
353+
real-entrypoint (string/join " " (concat
354+
(or (:entrypoint container-definition) Entrypoint)
355+
(or (:command container-definition) Cmd)))]
356+
(-> container-definition
357+
(assoc :entrypoint ["/bin/sh" "-c" (injected-entrypoint (:secrets container-definition) Env real-entrypoint)])
358+
(dissoc :command))))
359+
334360
(defn run-streaming-function-with-no-stdin
335361
"run container function with no stdin, and no timeout, but streaming stdout"
336362
[m cb]
337-
(when (not (has-image? (:image m)))
338-
(-pull m))
363+
(check-then-pull m)
339364
(let [x (-> m
340365
(update :opts
341366
(fnil merge {})
@@ -377,8 +402,7 @@
377402
(defn run-background-function
378403
"run container function with no stdin, and no streaming output"
379404
[m]
380-
(when (not (has-image? (:image m)))
381-
(-pull m))
405+
(check-then-pull m)
382406
(let [x (create m)]
383407
(start x)
384408
(shutdown/schedule-container-shutdown
@@ -391,8 +415,7 @@
391415
(defn run-function
392416
"run container function with no stdin, and no streaming output"
393417
[{:keys [timeout] :or {timeout 600000} :as m}]
394-
(when (not (has-image? (:image m)))
395-
(-pull m))
418+
(check-then-pull m)
396419
(let [x (create m)
397420
finished-channel (async/promise-chan)]
398421
(start x)

src/docker/main.clj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@
147147
(fn [m]
148148
(update-in m [:prompts] (fn [coll] (remove (fn [{:keys [type]}] (= type (second args))) coll))))))
149149
"run" (fn []
150-
(logger/setup (jsonrpc.server/->TimbreLogger))
150+
(logger/setup (jsonrpc.logger/->TimbreLogger))
151151

152152
(let [[in send]
153153
(let [[[w c] in] (user-loop/create-pipe)]

src/extension/docker-compose.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
services:
22
mcp_docker:
3-
image: mcp/docker:0.0.3
3+
image: mcp/docker:0.0.4
44
ports:
55
- 8811:8811
66
volumes:

src/jsonrpc/extras.clj

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
(ns jsonrpc.extras
2+
(:require
3+
[clojure.core.async :as async]
4+
git
5+
graph
6+
[jsonrpc.logger :as logger]
7+
[lsp4clj.server :as lsp.server]
8+
[promesa.core :as p]
9+
state
10+
volumes))
11+
12+
(defmethod lsp.server/receive-request "docker/prompts/register" [_ {:keys [db* id]} params]
13+
(logger/info "docker/prompts/register"))
14+
15+
(defmethod lsp.server/receive-request "docker/prompts/run"
16+
[_ {:keys [db* id] :as components} {:keys [thread-id] {:keys [file content uri]} :prompts :as params}]
17+
(lsp.server/discarding-stdout
18+
(let [conversation-id (str (java.util.UUID/randomUUID))
19+
prompt-string (cond
20+
file (slurp file)
21+
content content
22+
uri (slurp (git/prompt-file uri)))]
23+
(swap! db* update-in [:mcp/conversations] (fnil assoc {}) conversation-id
24+
{:state-promise
25+
(p/create
26+
(fn [resolve reject]
27+
(resolve
28+
(async/<!!
29+
(volumes/with-volume
30+
(fn [thread-id]
31+
(let [m (-> {}
32+
(assoc-in [:opts :conversation-id] conversation-id)
33+
(assoc-in [:opts :thread-id] thread-id)
34+
(assoc-in [:opts :prompt-content] prompt-string)
35+
(state/construct-initial-state-from-prompts))]
36+
(graph/stream
37+
(if (-> m :metadata :agent)
38+
((graph/require-graph (-> m :metadata :agent)) m)
39+
(graph/chat-with-tools m))
40+
m)))
41+
(if thread-id
42+
{:thread-id thread-id :save-thread-volume false}
43+
{}))))))})
44+
{:conversation-id conversation-id})))
45+

src/jsonrpc/logger.clj

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
(ns jsonrpc.logger)
1+
(ns jsonrpc.logger
2+
(:require
3+
[babashka.fs :as fs]
4+
[taoensso.timbre :as timbre]
5+
[taoensso.timbre.appenders.core :as appenders]))
26

37
(defprotocol ILogger
48
(setup [this])
@@ -53,3 +57,46 @@
5357
(defn trace [x]
5458
(info "trace " x)
5559
x)
60+
61+
(defn log! [level args fmeta]
62+
(timbre/log! level :p args {:?line (:line fmeta)
63+
:?file (:file fmeta)
64+
:?ns-str (:ns-str fmeta)}))
65+
66+
(defn decide-log-path []
67+
(let [prompts-dir (fs/file "/prompts")]
68+
(if (fs/exists? prompts-dir)
69+
(do
70+
(fs/create-dirs (fs/file prompts-dir "log"))
71+
(fs/file prompts-dir "log/docker-mcp-server.out"))
72+
(do
73+
(fs/create-dirs (fs/file "./log"))
74+
(fs/file "./log/docker-mcp-server.out")))))
75+
76+
(defrecord TimbreLogger []
77+
ILogger
78+
(setup [this]
79+
(let [log-path (str (decide-log-path))]
80+
(timbre/merge-config! {:middleware [#(assoc % :hostname_ "")]
81+
:appenders {:println {:enabled? false}
82+
:spit (appenders/spit-appender {:fname log-path})}})
83+
(timbre/handle-uncaught-jvm-exceptions!)
84+
(set-logger! this)
85+
log-path))
86+
87+
(set-log-path [_this log-path]
88+
(timbre/merge-config! {:appenders {:spit (appenders/spit-appender {:fname log-path})}}))
89+
90+
(-info [_this fmeta arg1] (log! :info [arg1] fmeta))
91+
(-info [_this fmeta arg1 arg2] (log! :info [arg1 arg2] fmeta))
92+
(-info [_this fmeta arg1 arg2 arg3] (log! :info [arg1 arg2 arg3] fmeta))
93+
(-warn [_this fmeta arg1] (log! :warn [arg1] fmeta))
94+
(-warn [_this fmeta arg1 arg2] (log! :warn [arg1 arg2] fmeta))
95+
(-warn [_this fmeta arg1 arg2 arg3] (log! :warn [arg1 arg2 arg3] fmeta))
96+
(-error [_this fmeta arg1] (log! :error [arg1] fmeta))
97+
(-error [_this fmeta arg1 arg2] (log! :error [arg1 arg2] fmeta))
98+
(-error [_this fmeta arg1 arg2 arg3] (log! :error [arg1 arg2 arg3] fmeta))
99+
(-debug [_this fmeta arg1] (log! :debug [arg1] fmeta))
100+
(-debug [_this fmeta arg1 arg2] (log! :debug [arg1 arg2] fmeta))
101+
(-debug [_this fmeta arg1 arg2 arg3] (log! :debug [arg1 arg2 arg3] fmeta)))
102+

src/jsonrpc/producer.clj

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
(ns jsonrpc.producer)
1+
(ns jsonrpc.producer
2+
(:require
3+
[jsonrpc.logger :as logger]
4+
[lsp4clj.server :as lsp.server]))
25

36
(defprotocol IProducer
47
(publish-exit [this params])
@@ -10,3 +13,37 @@
1013
(publish-tool-list-changed [this params])
1114
(publish-docker-notify [this method params]))
1215

16+
(defrecord McpProducer
17+
[server db*]
18+
IProducer
19+
20+
(publish-exit [_this p]
21+
(logger/info "publish-exit " p)
22+
(lsp.server/discarding-stdout
23+
(->> p (lsp.server/send-notification server "$/exit"))))
24+
; params is a map of progressToken, progress, and total
25+
(publish-progress [_this params]
26+
(lsp.server/discarding-stdout
27+
(->> params (lsp.server/send-notification server "notifications/progress"))))
28+
; params is a map of level, logger, data
29+
; level is debug info notice warning error critical alert emergency
30+
(publish-log [_this params]
31+
(->> params (lsp.server/send-notification server "notifications/message")))
32+
33+
(publish-prompt-list-changed [_ params]
34+
(logger/info "send prompt list changed")
35+
(->> params (lsp.server/send-notification server "notifications/prompts/list_changed")))
36+
37+
(publish-resource-list-changed [_ params]
38+
(logger/info "send resource list changed")
39+
(->> params (lsp.server/send-notification server "notifications/resources/list_changed")))
40+
41+
(publish-resource-updated [_ params]
42+
(->> params (lsp.server/send-notification server "notifications/resources/updated")))
43+
44+
(publish-tool-list-changed [_ params]
45+
(logger/info "send tool list changed")
46+
(->> params (lsp.server/send-notification server "notifications/tools/list_changed")))
47+
(publish-docker-notify [_ method params]
48+
(logger/info (format "%s - %s" method params))
49+
(lsp.server/send-notification server method params)))

0 commit comments

Comments
 (0)