agent: Reduce log spam for context servers (#33644)

Previously we would always run `maintain_servers` even if the settings
did not change. While this would not cause any MCP servers to restart,
we would still go through all configured servers and call the
`command(...)` function on each installed MCP extension. This can cause
lots of logs to show up when an MCP server is not configured correctly.

Release Notes:

- N/A
This commit is contained in:
Bennet Bo Fenner 2025-06-30 12:26:14 +02:00 committed by GitHub
parent f4aeeda2d9
commit aa7ccecc49
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -135,6 +135,7 @@ pub type ContextServerFactory =
Box<dyn Fn(ContextServerId, Arc<ContextServerConfiguration>) -> Arc<ContextServer>>; Box<dyn Fn(ContextServerId, Arc<ContextServerConfiguration>) -> Arc<ContextServer>>;
pub struct ContextServerStore { pub struct ContextServerStore {
context_server_settings: HashMap<Arc<str>, ContextServerSettings>,
servers: HashMap<ContextServerId, ContextServerState>, servers: HashMap<ContextServerId, ContextServerState>,
worktree_store: Entity<WorktreeStore>, worktree_store: Entity<WorktreeStore>,
registry: Entity<ContextServerDescriptorRegistry>, registry: Entity<ContextServerDescriptorRegistry>,
@ -202,6 +203,11 @@ impl ContextServerStore {
this.available_context_servers_changed(cx); this.available_context_servers_changed(cx);
}), }),
cx.observe_global::<SettingsStore>(|this, cx| { cx.observe_global::<SettingsStore>(|this, cx| {
let settings = Self::resolve_context_server_settings(&this.worktree_store, cx);
if &this.context_server_settings == settings {
return;
}
this.context_server_settings = settings.clone();
this.available_context_servers_changed(cx); this.available_context_servers_changed(cx);
}), }),
] ]
@ -211,6 +217,8 @@ impl ContextServerStore {
let mut this = Self { let mut this = Self {
_subscriptions: subscriptions, _subscriptions: subscriptions,
context_server_settings: Self::resolve_context_server_settings(&worktree_store, cx)
.clone(),
worktree_store, worktree_store,
registry, registry,
needs_server_update: false, needs_server_update: false,
@ -268,10 +276,8 @@ impl ContextServerStore {
cx.spawn(async move |this, cx| { cx.spawn(async move |this, cx| {
let this = this.upgrade().context("Context server store dropped")?; let this = this.upgrade().context("Context server store dropped")?;
let settings = this let settings = this
.update(cx, |this, cx| { .update(cx, |this, _| {
this.context_server_settings(cx) this.context_server_settings.get(&server.id().0).cloned()
.get(&server.id().0)
.cloned()
}) })
.ok() .ok()
.flatten() .flatten()
@ -439,12 +445,11 @@ impl ContextServerStore {
} }
} }
fn context_server_settings<'a>( fn resolve_context_server_settings<'a>(
&'a self, worktree_store: &'a Entity<WorktreeStore>,
cx: &'a App, cx: &'a App,
) -> &'a HashMap<Arc<str>, ContextServerSettings> { ) -> &'a HashMap<Arc<str>, ContextServerSettings> {
let location = self let location = worktree_store
.worktree_store
.read(cx) .read(cx)
.visible_worktrees(cx) .visible_worktrees(cx)
.next() .next()
@ -492,9 +497,9 @@ impl ContextServerStore {
} }
async fn maintain_servers(this: WeakEntity<Self>, cx: &mut AsyncApp) -> Result<()> { async fn maintain_servers(this: WeakEntity<Self>, cx: &mut AsyncApp) -> Result<()> {
let (mut configured_servers, registry, worktree_store) = this.update(cx, |this, cx| { let (mut configured_servers, registry, worktree_store) = this.update(cx, |this, _| {
( (
this.context_server_settings(cx).clone(), this.context_server_settings.clone(),
this.registry.clone(), this.registry.clone(),
this.worktree_store.clone(), this.worktree_store.clone(),
) )
@ -990,6 +995,33 @@ mod tests {
assert_eq!(store.read(cx).status_for_server(&server_2_id), None); assert_eq!(store.read(cx).status_for_server(&server_2_id), None);
}); });
} }
// Ensure that nothing happens if the settings do not change
{
let _server_events = assert_server_events(&store, vec![], cx);
set_context_server_configuration(
vec![(
server_1_id.0.clone(),
ContextServerSettings::Extension {
enabled: true,
settings: json!({
"somevalue": false
}),
},
)],
cx,
);
cx.run_until_parked();
cx.update(|cx| {
assert_eq!(
store.read(cx).status_for_server(&server_1_id),
Some(ContextServerStatus::Running)
);
assert_eq!(store.read(cx).status_for_server(&server_2_id), None);
});
}
} }
#[gpui::test] #[gpui::test]