Skip to content

Commit 1b1f887

Browse files
committed
Add mcp/serverUpdated server notification
1 parent e9b8587 commit 1b1f887

File tree

7 files changed

+51
-111
lines changed

7 files changed

+51
-111
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
- Allow comments on `json` configs.
66
- Improve MCP tool call feedback.
77
- Add support for env vars in mcp configs.
8-
- Add `mcp/listServers` request.
8+
- Add `mcp/serverUpdated` server notification.
99

1010
## 0.0.4
1111

docs/protocol.md

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -647,30 +647,21 @@ Soon
647647

648648
## Configuration
649649

650-
### List MCPs (↩️)
650+
### MCP server updated (⬅️)
651651

652-
A client request listing configured MCP servers configured by server and its status.
652+
A server notification about a configured MCP server status update.
653+
This is useful for clients present to user the list of configured MCPs,
654+
their status and available tools.
653655

654656
_Request:_
655657

656-
* method: `mcp/listServers`
657-
* params: `ListMCPServersParams` defined as follows:
658-
659-
```typescript
660-
interface ListMCPServersParams {}
661-
```
658+
* method: `mcp/serverUpdated`
659+
* params: `MCPServerUpdatedParams` defined as follows:
662660

663661
_Response:_
664662

665663
```typescript
666-
interface ListMCPServersResponse {
667-
/**
668-
* The list of servers.
669-
*/
670-
servers: MCPServer[];
671-
}
672-
673-
interface MCPServer {
664+
interface MCPServerUpdatedParams {
674665
/**
675666
* The server name.
676667
*/
@@ -689,7 +680,7 @@ interface MCPServer {
689680
/**
690681
* The status of the server.
691682
*/
692-
status: 'running' | 'starting' | 'stopped' | 'disabled';
683+
status: 'running' | 'starting' | 'stopped' | 'failed' | 'disabled';
693684

694685
/**
695686
* The tools supported by this mcp server if not disabled.

src/eca/features/mcp.clj

Lines changed: 32 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -59,23 +59,39 @@
5959
(.build)))
6060
(.build)))
6161

62-
(defn initialize! [{:keys [on-error]} db* config]
63-
(let [workspaces (:workspace-folders @db*)]
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))))
73+
74+
(defn initialize-servers-async! [{:keys [on-server-updated]} db* config]
75+
(let [workspaces (:workspace-folders @db*)
76+
db @db*]
6477
(doseq [[name server-config] (:mcpServers config)]
65-
(try
66-
(when-not (and (get-in @db* [:mcp-clients name])
67-
(get server-config :disabled false))
68-
(let [transport (->transport server-config workspaces)
69-
client (->client transport config)]
70-
(swap! db* assoc-in [:mcp-clients name] {:client client
71-
:status :starting})
72-
(doseq [{:keys [name uri]} workspaces]
73-
(.addRoot client (McpSchema$Root. uri name)))
74-
(.initialize client)
75-
(swap! db* update-in [:mcp-clients name] dissoc :status)))
76-
(catch Exception e
77-
(logger/warn logger-tag (format "Could not initialize MCP server %s. Error: %s" name (.getMessage e)))
78-
(on-error name e))))))
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)))))))))))
7995

8096
(defn tools-cached? [db]
8197
(boolean (:mcp-tools db)))
@@ -116,26 +132,3 @@
116132
(swap! db* assoc
117133
:mcp-clients {}
118134
:mcp-tools {}))
119-
120-
(defn all-servers [db config]
121-
(reduce
122-
(fn [servers [name server]]
123-
(let [{:keys [status client]} (get-in db [:mcp-clients name])
124-
tools (->> (vals (:mcp-tools db))
125-
(filterv #(= name (:mcp-name %)))
126-
(map (fn [mcp-tool]
127-
{:name (:name mcp-tool)
128-
:description (:description mcp-tool)
129-
:parameters (:parameters mcp-tool)})))]
130-
(conj servers (cond-> {:name (clojure.core/name name)
131-
:command (:command server)
132-
:args (:args server)
133-
:status (or status
134-
(if client
135-
(if (.isInitialized ^McpSyncClient client)
136-
:running
137-
:stopped)
138-
:disabled))}
139-
(seq tools) (assoc :tools tools)))))
140-
[]
141-
(:mcpServers config)))

src/eca/handlers.clj

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,12 @@
3232
:chat-behavior (or (-> params :initialization-options :chat-behavior) (:chat-behavior @db*)))
3333
(let [config (config/all @db*)]
3434
(initialize-extra-models! db*)
35-
;; TODO initialize async with progress support
36-
(f.mcp/initialize!
37-
{:on-error (fn [mcp-server-name _exception]
38-
(messenger/showMessage
39-
messenger
40-
{:type :error
41-
:message (format "MCP server %s not initialized, set \"--log-level debug\" and check stderr logs for more details" mcp-server-name)}))}
42-
db*
43-
config)
35+
(future
36+
(f.mcp/initialize-servers-async!
37+
{:on-server-updated (fn [server]
38+
(messenger/mcp-server-updated messenger server))}
39+
db*
40+
config))
4441
{:models (keys (:models @db*))
4542
:chat-default-model (f.chat/default-model @db*)
4643
:chat-behaviors (:chat-behaviors @db*)
@@ -64,8 +61,3 @@
6461
(logger/logging-task
6562
:eca/chat-query-context
6663
(f.chat/query-context params db*)))
67-
68-
(defn mcp-list-servers [{:keys [db*]} _params]
69-
(logger/logging-task
70-
:eca/mcp-list-servers
71-
{:servers (f.mcp/all-servers @db* (config/all @db*))}))

src/eca/messenger.clj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@
66

77
(defprotocol IMessenger
88
(chat-content-received [this data])
9+
(mcp-server-updated [this params])
910
(showMessage [this msg]))

src/eca/server.clj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,6 @@
4545
(defmethod lsp.server/receive-request "chat/queryContext" [_ components params]
4646
(handlers/chat-query-context components params))
4747

48-
(defmethod lsp.server/receive-request "mcp/listServers" [_ components params]
49-
(handlers/mcp-list-servers components params))
50-
5148
(defn ^:private monitor-server-logs [log-ch]
5249
;; NOTE: if this were moved to `initialize`, after timbre has been configured,
5350
;; the server's startup logs and traces would appear in the regular log file
@@ -77,6 +74,9 @@
7774
(chat-content-received [_this content]
7875
(lsp.server/discarding-stdout
7976
(lsp.server/send-notification server "chat/contentReceived" content)))
77+
(mcp-server-updated [_this params]
78+
(lsp.server/discarding-stdout
79+
(lsp.server/send-notification server "mcp/serverUpdated" params)))
8080
(showMessage [_this msg]
8181
(lsp.server/discarding-stdout
8282
(lsp.server/send-notification server "$/showMessage" msg))))

test/eca/features/mcp_test.clj

Lines changed: 0 additions & 37 deletions
This file was deleted.

0 commit comments

Comments
 (0)