|
18 | 18 | McpSchema$Prompt |
19 | 19 | McpSchema$PromptArgument |
20 | 20 | McpSchema$PromptMessage |
| 21 | + McpSchema$ReadResourceRequest |
| 22 | + McpSchema$Resource |
| 23 | + McpSchema$ResourceContents |
21 | 24 | McpSchema$Root |
22 | 25 | McpSchema$TextContent |
| 26 | + McpSchema$TextResourceContents |
23 | 27 | McpSchema$Tool |
24 | 28 | McpTransport] |
25 | 29 | [java.time Duration] |
|
74 | 78 | :command (:command server-config) |
75 | 79 | :args (:args server-config) |
76 | 80 | :tools (get-in db [:mcp-clients mcp-name :tools]) |
| 81 | + :prompts (get-in db [:mcp-clients mcp-name :prompts]) |
| 82 | + :resources (get-in db [:mcp-clients mcp-name :resources]) |
77 | 83 | :status status}) |
78 | 84 |
|
79 | 85 | (defn ^:private ->content [^McpSchema$Content content-client] |
|
82 | 88 | :text (.text ^McpSchema$TextContent content-client)} |
83 | 89 | nil)) |
84 | 90 |
|
| 91 | +(defn ^:private ->resource-content [^McpSchema$ResourceContents resource-content-client] |
| 92 | + (cond |
| 93 | + (instance? McpSchema$TextResourceContents resource-content-client) |
| 94 | + {:type :text |
| 95 | + :uri (.uri resource-content-client) |
| 96 | + :text (.text ^McpSchema$TextResourceContents resource-content-client)} |
| 97 | + |
| 98 | + :else |
| 99 | + nil)) |
| 100 | + |
85 | 101 | (defn ^:private list-server-tools [^ObjectMapper obj-mapper ^McpSyncClient client] |
86 | 102 | (mapv (fn [^McpSchema$Tool tool-client] |
87 | 103 | {:name (.name tool-client) |
|
102 | 118 | (.arguments prompt-client))}) |
103 | 119 | (.prompts (.listPrompts client)))) |
104 | 120 |
|
| 121 | +(defn ^:private list-server-resources [^McpSyncClient client] |
| 122 | + (try |
| 123 | + (mapv (fn [^McpSchema$Resource resource-client] |
| 124 | + {:uri (.uri resource-client) |
| 125 | + :name (.name resource-client) |
| 126 | + :description (.description resource-client) |
| 127 | + :mime-type (.mimeType resource-client)}) |
| 128 | + (.resources (.listResources client))) |
| 129 | + (catch Exception e |
| 130 | + (logger/debug logger-tag "Could not list resources:" (.getMessage e)) |
| 131 | + []))) |
| 132 | + |
| 133 | +(defn ^:private mcp-client-from-db [pred db] |
| 134 | + (->> (vals (:mcp-clients db)) |
| 135 | + (keep (fn [{:keys [client resources]}] |
| 136 | + (when (some pred resources) |
| 137 | + client))) |
| 138 | + first)) |
| 139 | + |
105 | 140 | (defn ^:private initialize-server! [name db* config on-server-updated] |
106 | 141 | (let [db @db* |
107 | 142 | workspaces (:workspace-folders @db*) |
|
117 | 152 | (.initialize client) |
118 | 153 | (swap! db* assoc-in [:mcp-clients name :tools] (list-server-tools obj-mapper client)) |
119 | 154 | (swap! db* assoc-in [:mcp-clients name :prompts] (list-server-prompts client)) |
| 155 | + (swap! db* assoc-in [:mcp-clients name :resources] (list-server-resources client)) |
120 | 156 | (on-server-updated (->server name server-config :running @db*))) |
121 | 157 | (catch Exception e |
122 | 158 | (logger/warn logger-tag (format "Could not initialize MCP server %s. Error: %s" name (.getMessage e))) |
|
156 | 192 | (:mcp-clients db))) |
157 | 193 |
|
158 | 194 | (defn call-tool! [^String name ^Map arguments db] |
159 | | - (let [mcp-client (->> (vals (:mcp-clients db)) |
160 | | - (keep (fn [{:keys [client tools]}] |
161 | | - (when (some #(= name (:name %)) tools) |
162 | | - client))) |
163 | | - first) |
| 195 | + (let [mcp-client (mcp-client-from-db #(= name (:name %)) db) |
164 | 196 | result (try |
165 | 197 | (let [result (.callTool ^McpSyncClient mcp-client |
166 | 198 | (McpSchema$CallToolRequest. name arguments))] |
|
179 | 211 | (mapv #(assoc % :server (name server-name)) prompts))) |
180 | 212 | (:mcp-clients db))) |
181 | 213 |
|
| 214 | +(defn all-resources [db] |
| 215 | + (into [] |
| 216 | + (mapcat (fn [[server-name {:keys [resources]}]] |
| 217 | + (mapv #(assoc % :server (name server-name)) resources))) |
| 218 | + (:mcp-clients db))) |
| 219 | + |
182 | 220 | (defn get-prompt! [^String name ^Map arguments db] |
183 | | - (let [mcp-client (->> (vals (:mcp-clients db)) |
184 | | - (keep (fn [{:keys [client prompts]}] |
185 | | - (when (some #(= name (:name %)) prompts) |
186 | | - client))) |
187 | | - first) |
| 221 | + (let [mcp-client (mcp-client-from-db #(= name (:name %)) db) |
188 | 222 | prompt (.getPrompt ^McpSyncClient mcp-client (McpSchema$GetPromptRequest. name arguments)) |
189 | 223 | result {:description (.description prompt) |
190 | 224 | :messages (mapv (fn [^McpSchema$PromptMessage message] |
|
194 | 228 | (logger/debug logger-tag "Prompt result:" result) |
195 | 229 | result)) |
196 | 230 |
|
| 231 | +(defn get-resource! [^String uri db] |
| 232 | + (let [mcp-client (mcp-client-from-db #(= uri (:uri %)) db) |
| 233 | + resource (.readResource ^McpSyncClient mcp-client (McpSchema$ReadResourceRequest. uri)) |
| 234 | + result {:contents (mapv ->resource-content (.contents resource))}] |
| 235 | + (logger/debug logger-tag "Resource result:" result) |
| 236 | + result)) |
| 237 | + |
197 | 238 | (defn shutdown! [db*] |
198 | | - (doseq [[_name {:keys [_client]}] (:mcp-clients @db*)] |
199 | | - ;; TODO NoClassDefFound being thrown for some reason |
200 | | - #_(.closeGracefully ^McpSyncClient client)) |
| 239 | + (doseq [[_name {:keys [client]}] (:mcp-clients @db*)] |
| 240 | + (.closeGracefully ^McpSyncClient client)) |
201 | 241 | (swap! db* assoc :mcp-clients {})) |
0 commit comments