Skip to content

Commit dc8c3c9

Browse files
authored
Merge branch 'master' into improve-eca__task-usage-after-compact
2 parents a9fdb56 + 2f76379 commit dc8c3c9

File tree

10 files changed

+143
-20
lines changed

10 files changed

+143
-20
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44

55
- Update the compact prompt to read the active eca__task list after compacting.
66

7+
## 0.120.0
8+
9+
- Add `mcp/disableServer` and `mcp/enableServer` notifications to toggle MCP servers from the client, persisting the `disabled` flag in config.json.
10+
711
## 0.119.0
812

913
- Add `/fork` command to clone current chat into a new chat with the same history and settings, and `chat/opened` server notification.

docs/protocol.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2174,6 +2174,44 @@ interface MCPLogoutServerParams {
21742174
}
21752175
```
21762176

2177+
### Disable MCP server (➡️)
2178+
2179+
A client notification to disable an MCP server. Persists `disabled: true` in the config file,
2180+
stops the server if running, and sends `tool/serverUpdated` with status `disabled`.
2181+
2182+
_Notification:_
2183+
2184+
* method: `mcp/disableServer`
2185+
* params: `MCPDisableServerParams` defined as follows:
2186+
2187+
```typescript
2188+
interface MCPDisableServerParams {
2189+
/**
2190+
* The MCP server name.
2191+
*/
2192+
name: string;
2193+
}
2194+
```
2195+
2196+
### Enable MCP server (➡️)
2197+
2198+
A client notification to enable a disabled MCP server. Removes the `disabled` flag from the config file,
2199+
starts the server, and sends `tool/serverUpdated` with the new status.
2200+
2201+
_Notification:_
2202+
2203+
* method: `mcp/enableServer`
2204+
* params: `MCPEnableServerParams` defined as follows:
2205+
2206+
```typescript
2207+
interface MCPEnableServerParams {
2208+
/**
2209+
* The MCP server name.
2210+
*/
2211+
name: string;
2212+
}
2213+
```
2214+
21772215
### Update MCP Server (↩️)
21782216

21792217
Updates an MCP server's connection configuration (command/args or url), persists the change to the appropriate config file (local or global), and restarts the server.

resources/ECA_VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.119.0
1+
0.120.0

src/eca/features/tools.clj

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,22 @@
332332
metrics
333333
{:on-server-updated (partial notify-server-updated metrics messenger tool-status-fn)})))
334334

335+
(defn disable-server! [name db* messenger config metrics]
336+
(let [tool-status-fn (make-tool-status-fn config nil)]
337+
(f.mcp/disable-server!
338+
name
339+
db*
340+
config
341+
{:on-server-updated (partial notify-server-updated metrics messenger tool-status-fn)})))
342+
343+
(defn enable-server! [name db* messenger config metrics]
344+
(let [tool-status-fn (make-tool-status-fn config nil)]
345+
(f.mcp/enable-server!
346+
name
347+
db*
348+
metrics
349+
{:on-server-updated (partial notify-server-updated metrics messenger tool-status-fn)})))
350+
335351
(defn tool-call-summary [all-tools full-name args config db]
336352
(when-let [summary-fn (:summary-fn (first (filter #(= full-name (:full-name %))
337353
all-tools)))]

src/eca/features/tools/mcp.clj

Lines changed: 57 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
[plumcp.core.client.stdio-client-transport :as psct]
2121
[plumcp.core.protocol :as pp]
2222
[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])
2425
(:import
2526
[java.io IOException]))
2627

@@ -346,9 +347,9 @@
346347
init-result (pmc/get-initialize-result client)
347348
version (get-in init-result [:serverInfo :version])]
348349
(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)))
352353
(swap! db* assoc-in [:mcp-clients name :version] version)
353354
(swap! db* assoc-in [:mcp-clients name :instructions] (:instructions init-result))
354355
(swap! db* assoc-in [:mcp-clients name :tools] (list-server-tools client))
@@ -565,6 +566,45 @@
565566
(let [fresh-config (config/all @db*)]
566567
(restart-server! server-name db* fresh-config metrics on-server-updated))))
567568

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+
568608
(defn all-tools [db]
569609
(into []
570610
(mapcat (fn [[name {:keys [tools version]}]]
@@ -721,22 +761,22 @@
721761
(let [clients (vals (:mcp-clients @db*))
722762
latch (java.util.concurrent.CountDownLatch. (count clients))
723763
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
729769
;; HTTP: force-stop (the DELETE in disconnect! always
730770
;; times out because the server is slow to respond)
731-
(pp/stop! http-client)
771+
(pp/stop! http-client)
732772
;; 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))]
740780
(when-not (.await latch disconnect-timeout-ms java.util.concurrent.TimeUnit/MILLISECONDS)
741781
(logger/warn logger-tag "Some MCP servers did not disconnect within timeout, forcing stop")
742782
(doseq [^Thread t threads]

src/eca/features/tools/util.clj

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
[clojure.java.io :as io]
66
[clojure.java.shell :as shell]
77
[clojure.string :as string]
8-
[clojure.string :as str]
98
[eca.cache :as cache]
109
[eca.logger :as logger]
1110
[eca.shared :as shared]))
@@ -206,4 +205,4 @@
206205

207206
(defn normalize-optional-string
208207
[value]
209-
(some-> value str/trim not-empty))
208+
(some-> value string/trim not-empty))

src/eca/handlers.clj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,14 @@
246246
(f.tools/update-server! server-name server-fields db* messenger config metrics)
247247
{})))
248248

249+
(defn mcp-disable-server [{:keys [db* messenger metrics config]} params]
250+
(metrics/task metrics :eca/mcp-disable-server
251+
(f.tools/disable-server! (:name params) db* messenger config metrics)))
252+
253+
(defn mcp-enable-server [{:keys [db* messenger metrics config]} params]
254+
(metrics/task metrics :eca/mcp-enable-server
255+
(f.tools/enable-server! (:name params) db* messenger config metrics)))
256+
249257
(defn ^:private update-agent-model-and-variants!
250258
"Updates the selected model and variants based on agent configuration."
251259
[agent-config config messenger db*]

src/eca/remote/handlers.clj

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,16 @@
271271
(handlers/mcp-logout-server (assoc components :config config) {:name server-name})
272272
(no-content)))
273273

274+
(defn handle-mcp-disable [{:keys [db*] :as components} _request server-name]
275+
(let [config (config/all @db*)]
276+
(handlers/mcp-disable-server (assoc components :config config) {:name server-name})
277+
(no-content)))
278+
279+
(defn handle-mcp-enable [{:keys [db*] :as components} _request server-name]
280+
(let [config (config/all @db*)]
281+
(handlers/mcp-enable-server (assoc components :config config) {:name server-name})
282+
(no-content)))
283+
274284
(deftype SSEBody [db* sse-connections*]
275285
ring.protocols/StreamableResponseBody
276286
(write-body-to-stream [_ _response os]

src/eca/remote/routes.clj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@
8585
"stop" [handlers/handle-mcp-stop components request server-name]
8686
"connect" [handlers/handle-mcp-connect components request server-name]
8787
"logout" [handlers/handle-mcp-logout components request server-name]
88+
"disable" [handlers/handle-mcp-disable components request server-name]
89+
"enable" [handlers/handle-mcp-enable components request server-name]
8890
nil)))
8991

9092
nil))))))

src/eca/server.clj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,12 @@
9696
(defmethod jsonrpc.server/receive-notification "mcp/logoutServer" [_ components params]
9797
(handlers/mcp-logout-server (with-config components) params))
9898

99+
(defmethod jsonrpc.server/receive-notification "mcp/disableServer" [_ components params]
100+
(handlers/mcp-disable-server (with-config components) params))
101+
102+
(defmethod jsonrpc.server/receive-notification "mcp/enableServer" [_ components params]
103+
(handlers/mcp-enable-server (with-config components) params))
104+
99105
(defmethod jsonrpc.server/receive-request "mcp/updateServer" [_ components params]
100106
(handlers/mcp-update-server (with-config components) params))
101107

0 commit comments

Comments
 (0)