|
20 | 20 | [plumcp.core.client.stdio-client-transport :as psct] |
21 | 21 | [plumcp.core.protocol :as pp] |
22 | 22 | [plumcp.core.schema.schema-defs :as psd] |
23 | | - [plumcp.core.support.http-client :as phc]) |
| 23 | + [plumcp.core.support.http-client :as phc] |
| 24 | + [rewrite-json.core :as rj]) |
24 | 25 | (:import |
25 | 26 | [java.io IOException])) |
26 | 27 |
|
|
346 | 347 | init-result (pmc/get-initialize-result client) |
347 | 348 | version (get-in init-result [:serverInfo :version])] |
348 | 349 | (swap! db* assoc-in [:mcp-clients name] (cond-> {:client client |
349 | | - :status :starting |
350 | | - :needs-reinit?* needs-reinit?*} |
351 | | - http-client (assoc :http-client http-client))) |
| 350 | + :status :starting |
| 351 | + :needs-reinit?* needs-reinit?*} |
| 352 | + http-client (assoc :http-client http-client))) |
352 | 353 | (swap! db* assoc-in [:mcp-clients name :version] version) |
353 | 354 | (swap! db* assoc-in [:mcp-clients name :instructions] (:instructions init-result)) |
354 | 355 | (swap! db* assoc-in [:mcp-clients name :tools] (list-server-tools client)) |
|
565 | 566 | (let [fresh-config (config/all @db*)] |
566 | 567 | (restart-server! server-name db* fresh-config metrics on-server-updated)))) |
567 | 568 |
|
| 569 | +(defn ^:private update-config-file! |
| 570 | + "Apply rewrite-json edits to a config file, preserving comments and formatting. |
| 571 | + `edit-fn` receives a parsed rj root node and returns the modified root." |
| 572 | + [^java.io.File config-file edit-fn] |
| 573 | + (let [raw (if (.exists config-file) (slurp config-file) "{}") |
| 574 | + root (edit-fn (rj/parse-string raw))] |
| 575 | + (io/make-parents config-file) |
| 576 | + (spit config-file (rj/to-string root)))) |
| 577 | + |
| 578 | +(defn ^:private resolve-config-file [server-name db] |
| 579 | + (let [{:keys [source workspace-root-uri]} (find-server-config-source server-name db)] |
| 580 | + (if (= source :local) |
| 581 | + (io/file (shared/uri->filename workspace-root-uri) ".eca" "config.json") |
| 582 | + (config/global-config-file)))) |
| 583 | + |
| 584 | +(defn disable-server! |
| 585 | + "Disable an MCP server: persist disabled=true in config, stop if running, notify." |
| 586 | + [server-name db* config {:keys [on-server-updated]}] |
| 587 | + (let [db @db* |
| 588 | + config-file (resolve-config-file server-name db) |
| 589 | + server-config (get-in config [:mcpServers server-name])] |
| 590 | + (update-config-file! config-file |
| 591 | + #(rj/assoc-in % ["mcpServers" server-name "disabled"] true)) |
| 592 | + (memoize/memo-clear! config/all) |
| 593 | + (when (get-in db [:mcp-clients server-name :client]) |
| 594 | + (stop-server! server-name db* config {:on-server-updated on-server-updated})) |
| 595 | + (on-server-updated (->server server-name server-config :disabled @db*)))) |
| 596 | + |
| 597 | +(defn enable-server! |
| 598 | + "Enable an MCP server: remove disabled from config, start the server, notify." |
| 599 | + [server-name db* metrics {:keys [on-server-updated]}] |
| 600 | + (let [db @db* |
| 601 | + config-file (resolve-config-file server-name db)] |
| 602 | + (update-config-file! config-file |
| 603 | + #(rj/dissoc-in % ["mcpServers" server-name "disabled"])) |
| 604 | + (memoize/memo-clear! config/all) |
| 605 | + (let [fresh-config (config/all @db*)] |
| 606 | + (start-server! server-name db* fresh-config metrics {:on-server-updated on-server-updated})))) |
| 607 | + |
568 | 608 | (defn all-tools [db] |
569 | 609 | (into [] |
570 | 610 | (mapcat (fn [[name {:keys [tools version]}]] |
|
721 | 761 | (let [clients (vals (:mcp-clients @db*)) |
722 | 762 | latch (java.util.concurrent.CountDownLatch. (count clients)) |
723 | 763 | threads (doall |
724 | | - (map (fn [{:keys [client http-client]}] |
725 | | - (doto (Thread. |
726 | | - (fn [] |
727 | | - (try |
728 | | - (if http-client |
| 764 | + (map (fn [{:keys [client http-client]}] |
| 765 | + (doto (Thread. |
| 766 | + (fn [] |
| 767 | + (try |
| 768 | + (if http-client |
729 | 769 | ;; HTTP: force-stop (the DELETE in disconnect! always |
730 | 770 | ;; times out because the server is slow to respond) |
731 | | - (pp/stop! http-client) |
| 771 | + (pp/stop! http-client) |
732 | 772 | ;; stdio: graceful disconnect |
733 | | - (pmc/disconnect! client)) |
734 | | - (catch Exception _) |
735 | | - (finally |
736 | | - (.countDown latch))))) |
737 | | - (.setDaemon true) |
738 | | - (.start))) |
739 | | - clients))] |
| 773 | + (pmc/disconnect! client)) |
| 774 | + (catch Exception _) |
| 775 | + (finally |
| 776 | + (.countDown latch))))) |
| 777 | + (.setDaemon true) |
| 778 | + (.start))) |
| 779 | + clients))] |
740 | 780 | (when-not (.await latch disconnect-timeout-ms java.util.concurrent.TimeUnit/MILLISECONDS) |
741 | 781 | (logger/warn logger-tag "Some MCP servers did not disconnect within timeout, forcing stop") |
742 | 782 | (doseq [^Thread t threads] |
|
0 commit comments