Skip to content

Commit e3decb9

Browse files
committed
Refactor: move mcp tools to inside mcp-client
1 parent 1b1f887 commit e3decb9

File tree

3 files changed

+45
-69
lines changed

3 files changed

+45
-69
lines changed

src/eca/db.clj

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@
2222
"claude-3-5-haiku-latest" {:mcp-tools true
2323
:web-search true}} ;; + ollama local models
2424
:default-model "o4-mini" ;; unless a ollama model is running.
25-
})
25+
:mcp-clients {}})
2626

2727
(defonce db* (atom initial-db))
28-
29-
(comment
30-
(:client (:clojure-mcp (:mcp-clients @db*))))

src/eca/features/chat.clj

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -58,19 +58,6 @@
5858
ollama-model
5959
(:default-model db)))
6060

61-
(defn ^:private all-mcp-tools! [chat-id request-id messenger db*]
62-
(when-not (f.mcp/tools-cached? @db*)
63-
(messenger/chat-content-received
64-
messenger
65-
{:chat-id chat-id
66-
:request-id request-id
67-
:role :system
68-
:content {:type :progress
69-
:state :running
70-
:text "Finding MCPs"}})
71-
(f.mcp/cache-tools! db*))
72-
(f.mcp/all-tools @db*))
73-
7461
(defn prompt
7562
[{:keys [message model behavior contexts chat-id request-id]}
7663
db*
@@ -108,7 +95,7 @@
10895
past-messages (get-in db [:chats chat-id :messages] [])
10996
user-prompt message
11097
mcp-tools (when (get-in db [:models chosen-model :mcp-tools])
111-
(all-mcp-tools! chat-id request-id messenger db*))
98+
(f.mcp/all-tools @db*))
11299
received-msgs* (atom "")]
113100
(swap! db* update-in [:chats chat-id :messages] (fnil conj []) {:role "user" :content user-prompt})
114101
(messenger/chat-content-received

src/eca/features/mcp.clj

Lines changed: 43 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -59,62 +59,56 @@
5959
(.build)))
6060
(.build)))
6161

62-
(defn ^:private ->full-server [mcp-name server-config db]
63-
(let [tools (->> (vals (:mcp-tools db))
64-
(filterv #(= mcp-name (:mcp-name %)))
65-
(map (fn [mcp-tool]
66-
{:name (:name mcp-tool)
67-
:description (:description mcp-tool)
68-
:parameters (:parameters mcp-tool)})))]
69-
(cond-> {:name (name mcp-name)
70-
:command (:command server-config)
71-
:args (:args server-config)}
72-
(seq tools) (assoc :tools tools))))
62+
(defn ^:private ->server [mcp-name server-config status db]
63+
{:name (name mcp-name)
64+
:command (:command server-config)
65+
:args (:args server-config)
66+
:tools (get-in db [:mcp-clients mcp-name :tools])
67+
:status status})
7368

7469
(defn initialize-servers-async! [{:keys [on-server-updated]} db* config]
7570
(let [workspaces (:workspace-folders @db*)
76-
db @db*]
71+
db @db*
72+
obj-mapper (ObjectMapper.)]
7773
(doseq [[name server-config] (:mcpServers config)]
78-
(let [full-server (->full-server name server-config db)]
79-
(when-not (get-in db [:mcp-clients name])
80-
(if (get server-config :disabled false)
81-
(on-server-updated (assoc full-server :status :disabled))
82-
(future
83-
(try
84-
(let [transport (->transport server-config workspaces)
85-
client (->client transport config)]
86-
(on-server-updated (assoc full-server :status :starting))
87-
(swap! db* assoc-in [:mcp-clients name] {:client client})
88-
(doseq [{:keys [name uri]} workspaces]
89-
(.addRoot client (McpSchema$Root. uri name)))
90-
(.initialize client)
91-
(on-server-updated (assoc full-server :status :running)))
92-
(catch Exception e
93-
(logger/warn logger-tag (format "Could not initialize MCP server %s. Error: %s" name (.getMessage e)))
94-
(on-server-updated (assoc full-server :status :failed)))))))))))
95-
96-
(defn tools-cached? [db]
97-
(boolean (:mcp-tools db)))
98-
99-
(defn cache-tools! [db*]
100-
(let [obj-mapper (ObjectMapper.)]
101-
(doseq [[name {:keys [^McpSyncClient client]}] (:mcp-clients @db*)]
102-
(when (.isInitialized client)
103-
(doseq [^McpSchema$Tool tool-client (.tools (.listTools client))]
104-
(let [tool {:name (.name tool-client)
105-
:mcp-name name
106-
:mcp-client client
107-
:description (.description tool-client)
108-
;; We convert to json to then read so we have the clojure map
109-
;; TODO avoid this converting to clojure map directly
110-
:parameters (json/parse-string (.writeValueAsString obj-mapper (.inputSchema tool-client)) true)}]
111-
(swap! db* assoc-in [:mcp-tools (:name tool)] tool)))))))
74+
(when-not (get-in db [:mcp-clients name])
75+
(if (get server-config :disabled false)
76+
(on-server-updated (->server name server-config :disabled db))
77+
(future
78+
(try
79+
(let [transport (->transport server-config workspaces)
80+
client (->client transport config)]
81+
(on-server-updated (->server name server-config :starting db))
82+
(swap! db* assoc-in [:mcp-clients name] {:client client})
83+
(doseq [{:keys [name uri]} workspaces]
84+
(.addRoot client (McpSchema$Root. uri name)))
85+
(.initialize client)
86+
(let [tools (mapv (fn [^McpSchema$Tool tool-client]
87+
{:name (.name tool-client)
88+
:description (.description tool-client)
89+
;; We convert to json to then read so we have a clojure map
90+
;; TODO avoid this converting to clojure map directly
91+
:parameters (json/parse-string (.writeValueAsString obj-mapper (.inputSchema tool-client)) true)})
92+
(.tools (.listTools client)))]
93+
(swap! db* assoc-in [:mcp-clients name :tools] tools))
94+
(on-server-updated (->server name server-config :running @db*)))
95+
(catch Exception e
96+
(logger/warn logger-tag (format "Could not initialize MCP server %s. Error: %s" name (.getMessage e)))
97+
(on-server-updated (->server name server-config :failed db))))))))))
11298

11399
(defn all-tools [db]
114-
(vals (:mcp-tools db)))
100+
(into []
101+
(mapcat (fn [[_name {:keys [tools]}]]
102+
tools))
103+
(:mcp-clients db)))
115104

116105
(defn call-tool! [^String name ^Map arguments db]
117-
(let [result (.callTool ^McpSyncClient (get-in db [:mcp-tools name :mcp-client])
106+
(let [mcp-client (->> (:mcp-clients db)
107+
(keep (fn [{:keys [client tools]}]
108+
(when (some #(= name (:name %)) tools)
109+
client)))
110+
first)
111+
result (.callTool ^McpSyncClient mcp-client
118112
(McpSchema$CallToolRequest. name arguments))]
119113
(logger/debug logger-tag "ToolCall result: " result)
120114
{:contents (map (fn [content]
@@ -129,6 +123,4 @@
129123
(doseq [[_name {:keys [_client]}] (:mcp-clients @db*)]
130124
;; TODO NoClassDefFound being thrown for some reason
131125
#_(.closeGracefully ^McpSyncClient client))
132-
(swap! db* assoc
133-
:mcp-clients {}
134-
:mcp-tools {}))
126+
(swap! db* assoc :mcp-clients {}))

0 commit comments

Comments
 (0)