agent: Fix bug that prevented MCP servers to appear in the settings view (#33857)

Danilo Leal and Bennet Bo Fenner created

Closes https://github.com/zed-industries/zed/issues/33827

After #33644 was merged, we would not start MCP servers coming from
extensions correctly anymore. The optimization uncovered a bug in the
implementation of `ContextServerDescriptorRegistry`, because we never
called `cx.notify()` when adding/removing context servers.
`ContextServerStore` listens for these events, and before #33644 this
was just working because of aace condition.

Release Notes:

- agent: Fixed bug that prevented MCP servers to appear in the settings
view.

Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>

Change summary

crates/project/src/context_server_store.rs           |  4 ++--
crates/project/src/context_server_store/extension.rs |  7 ++++---
crates/project/src/context_server_store/registry.rs  | 11 +++++++++--
3 files changed, 15 insertions(+), 7 deletions(-)

Detailed changes

crates/project/src/context_server_store.rs 🔗

@@ -818,9 +818,9 @@ mod tests {
         .await;
 
         let executor = cx.executor();
-        let registry = cx.new(|_| {
+        let registry = cx.new(|cx| {
             let mut registry = ContextServerDescriptorRegistry::new();
-            registry.register_context_server_descriptor(SERVER_1_ID.into(), fake_descriptor_1);
+            registry.register_context_server_descriptor(SERVER_1_ID.into(), fake_descriptor_1, cx);
             registry
         });
         let store = cx.new(|cx| {

crates/project/src/context_server_store/extension.rs 🔗

@@ -103,19 +103,20 @@ struct ContextServerDescriptorRegistryProxy {
 impl ExtensionContextServerProxy for ContextServerDescriptorRegistryProxy {
     fn register_context_server(&self, extension: Arc<dyn Extension>, id: Arc<str>, cx: &mut App) {
         self.context_server_factory_registry
-            .update(cx, |registry, _| {
+            .update(cx, |registry, cx| {
                 registry.register_context_server_descriptor(
                     id.clone(),
                     Arc::new(ContextServerDescriptor { id, extension })
                         as Arc<dyn registry::ContextServerDescriptor>,
+                    cx,
                 )
             });
     }
 
     fn unregister_context_server(&self, server_id: Arc<str>, cx: &mut App) {
         self.context_server_factory_registry
-            .update(cx, |registry, _| {
-                registry.unregister_context_server_descriptor_by_id(&server_id)
+            .update(cx, |registry, cx| {
+                registry.unregister_context_server_descriptor_by_id(&server_id, cx)
             });
     }
 }

crates/project/src/context_server_store/registry.rs 🔗

@@ -4,7 +4,7 @@ use anyhow::Result;
 use collections::HashMap;
 use context_server::ContextServerCommand;
 use extension::ContextServerConfiguration;
-use gpui::{App, AppContext as _, AsyncApp, Entity, Global, Task};
+use gpui::{App, AppContext as _, AsyncApp, Context, Entity, Global, Task};
 
 use crate::worktree_store::WorktreeStore;
 
@@ -66,12 +66,19 @@ impl ContextServerDescriptorRegistry {
         &mut self,
         id: Arc<str>,
         descriptor: Arc<dyn ContextServerDescriptor>,
+        cx: &mut Context<Self>,
     ) {
         self.context_servers.insert(id, descriptor);
+        cx.notify();
     }
 
     /// Unregisters the [`ContextServerDescriptor`] for the server with the given ID.
-    pub fn unregister_context_server_descriptor_by_id(&mut self, server_id: &str) {
+    pub fn unregister_context_server_descriptor_by_id(
+        &mut self,
+        server_id: &str,
+        cx: &mut Context<Self>,
+    ) {
         self.context_servers.remove(server_id);
+        cx.notify();
     }
 }