|
137 | 137 | (logger/info logger-tag (format "[%s] %s" server-name msg)))}) |
138 | 138 | :needs-reinit?* nil}))) |
139 | 139 |
|
| 140 | +(defn ^:private non-blocking-handler |
| 141 | + "Wraps a notification handler so it runs on a separate thread. |
| 142 | + Prevents STDIO transport deadlock where the reader thread blocks on a |
| 143 | + synchronous fetch request inside a notification handler, making it |
| 144 | + unable to read incoming responses." |
| 145 | + [f] |
| 146 | + (pcs/wrap-initialized-check |
| 147 | + (fn [jsonrpc-notification] |
| 148 | + (future (f jsonrpc-notification))))) |
| 149 | + |
140 | 150 | (defn ^:private ->client [name transport init-timeout workspaces |
141 | 151 | {:keys [on-tools-change]}] |
142 | 152 | (let [tools-consumer (fn [tools] |
143 | 153 | (logger/info logger-tag |
144 | 154 | (format "[%s] Tools list changed, received %d tools" |
145 | 155 | name (count tools))) |
146 | 156 | (on-tools-change tools)) |
147 | | - tools-nhandler (pcs/wrap-initialized-check |
148 | | - (fn [jsonrpc-notification] |
149 | | - (pcs/fetch-tools jsonrpc-notification |
150 | | - {:on-tools tools-consumer}))) |
151 | 157 | client (pmc/make-mcp-client |
152 | 158 | {:info (pes/make-info name "current") |
153 | 159 | :client-transport transport |
154 | 160 | :primitives {:roots (mapv #(pcap/make-root-item (:uri %) |
155 | 161 | {:name (:name %)}) |
156 | 162 | workspaces)} |
157 | 163 | :notification-handlers |
158 | | - {psd/method-notifications-tools-list_changed tools-nhandler |
159 | | - psd/method-notifications-message (fn [params] |
160 | | - (logger/info logger-tag |
161 | | - (format "[MCP-%s] %s" name (:data params))))} |
| 164 | + {psd/method-notifications-tools-list_changed |
| 165 | + (non-blocking-handler |
| 166 | + (fn [notification] |
| 167 | + (pcs/fetch-tools notification |
| 168 | + {:on-tools tools-consumer}))) |
| 169 | + |
| 170 | + psd/method-notifications-resources-list_changed |
| 171 | + (non-blocking-handler |
| 172 | + (fn [notification] |
| 173 | + (pcs/fetch-resources notification))) |
| 174 | + |
| 175 | + psd/method-notifications-prompts-list_changed |
| 176 | + (non-blocking-handler |
| 177 | + (fn [notification] |
| 178 | + (pcs/fetch-prompts notification))) |
| 179 | + |
| 180 | + psd/method-notifications-message |
| 181 | + (fn [params] |
| 182 | + (logger/info logger-tag |
| 183 | + (format "[MCP-%s] %s" name (:data params))))} |
162 | 184 | :print-banner? false})] |
163 | 185 | (pmc/initialize-and-notify! client |
164 | 186 | {:timeout-millis (* 1000 init-timeout)}) |
|
0 commit comments