From bb1842c5aecb62f36d272988dbc1b507203f1851 Mon Sep 17 00:00:00 2001 From: Taksh Date: Sat, 29 Aug 2026 16:16:00 +0530 Subject: [PATCH 1/2] fix(desktop): give preset harnesses buzz-dev-mcp Preset catalog entries left mcp_command empty and spawn only consulted KNOWN_ACP_RUNTIMES, so Hermes and friends opened sessions with no MCP server and could never post a reply. Signed-off-by: Taksh --- .../src-tauri/src/managed_agents/discovery.rs | 12 ++++- .../src/managed_agents/discovery/presets.rs | 50 ++++++++++++++++++- .../src-tauri/src/managed_agents/runtime.rs | 6 +-- .../src/managed_agents/spawn_snapshot.rs | 3 +- 4 files changed, 63 insertions(+), 8 deletions(-) diff --git a/desktop/src-tauri/src/managed_agents/discovery.rs b/desktop/src-tauri/src/managed_agents/discovery.rs index 1ee7e6e5562..ca467650931 100644 --- a/desktop/src-tauri/src/managed_agents/discovery.rs +++ b/desktop/src-tauri/src/managed_agents/discovery.rs @@ -23,7 +23,7 @@ pub(crate) use login_shell::{ }; pub(crate) use presets::{ canonical_harness_command, command_for_runtime_id, preset_harness_definitions, - preset_harness_ids, + preset_harness_ids, preset_mcp_command_for, }; use presets::{preset_catalog_entry, PRESET_HARNESSES}; pub(crate) use runtime_metadata::KnownAcpRuntime; @@ -286,6 +286,16 @@ pub(crate) fn known_acp_runtime(command: &str) -> Option<&'static KnownAcpRuntim }) } +/// Resolve the MCP sidecar command for an agent harness. +/// +/// Builtins declare `mcp_command` on `KNOWN_ACP_RUNTIMES`. Presets are not in +/// that table, so fall through to `preset_mcp_command_for` (#7023). +pub(crate) fn resolve_mcp_command(command: &str) -> Option<&'static str> { + known_acp_runtime(command) + .and_then(|runtime| runtime.mcp_command) + .or_else(|| preset_mcp_command_for(command)) +} + pub(crate) fn known_acp_runtime_exact(id: &str) -> Option<&'static KnownAcpRuntime> { KNOWN_ACP_RUNTIMES.iter().find(|p| p.id == id) } diff --git a/desktop/src-tauri/src/managed_agents/discovery/presets.rs b/desktop/src-tauri/src/managed_agents/discovery/presets.rs index fd853094515..fe69bec9cd0 100644 --- a/desktop/src-tauri/src/managed_agents/discovery/presets.rs +++ b/desktop/src-tauri/src/managed_agents/discovery/presets.rs @@ -63,7 +63,9 @@ pub(super) fn preset_catalog_entry( def.command, def.args.iter().map(|arg| arg.to_string()).collect(), ), - mcp_command: None, + // Preset ACP harnesses publish replies through buzz-dev-mcp, same as + // the built-in runtimes that already carry an MCP command (#7023). + mcp_command: Some("buzz-dev-mcp".to_string()), model_env_var: None, provider_env_var: None, thinking_env_var: None, @@ -217,6 +219,20 @@ pub(super) fn preset_command_for_id(id: &str) -> Option<&'static str> { .map(|p| p.command) } +/// MCP command for a preset harness matched by command (or path basename). +/// +/// Presets are absent from `KNOWN_ACP_RUNTIMES`, so spawn must consult this +/// when resolving `BUZZ_ACP_MCP_COMMAND` (#7023). +pub(crate) fn preset_mcp_command_for(command: &str) -> Option<&'static str> { + let normalized = super::normalize_command_identity(command); + PRESET_HARNESSES + .iter() + .any(|preset| { + super::normalize_command_identity(preset.command) == normalized || preset.id == normalized + }) + .then_some("buzz-dev-mcp") +} + /// Return the primary harness command for a given runtime id, or `None`. /// /// Checks static builtins, then the static preset list (always available, @@ -317,6 +333,7 @@ mod tests { assert_eq!(entry.binary_path.as_deref(), Some("/usr/local/bin/devin")); assert_eq!(entry.auth_status, AuthStatus::NotApplicable); assert_eq!(entry.source, HarnessSource::Preset); + assert_eq!(entry.mcp_command.as_deref(), Some("buzz-dev-mcp")); let missing_entry = preset_catalog_entry(preset, |_| None); assert_eq!( @@ -470,4 +487,35 @@ mod tests { "uncapped preset (devin) must have max_parallelism: None" ); } + + #[test] + fn preset_mcp_command_resolves_for_hermes_and_paths() { + assert_eq!( + super::preset_mcp_command_for("hermes-acp"), + Some("buzz-dev-mcp") + ); + assert_eq!( + super::preset_mcp_command_for("/opt/homebrew/bin/hermes-acp"), + Some("buzz-dev-mcp") + ); + assert_eq!( + super::preset_mcp_command_for("hermes"), + Some("buzz-dev-mcp") + ); + assert_eq!(super::preset_mcp_command_for("totally-unknown-agent"), None); + } + + #[test] + fn resolve_mcp_command_prefers_builtin_then_preset() { + assert_eq!( + crate::managed_agents::resolve_mcp_command("codex-acp"), + Some("buzz-dev-mcp") + ); + assert_eq!( + crate::managed_agents::resolve_mcp_command("hermes-acp"), + Some("buzz-dev-mcp") + ); + // Goose is a builtin without an MCP sidecar declaration. + assert_eq!(crate::managed_agents::resolve_mcp_command("goose"), None); + } } diff --git a/desktop/src-tauri/src/managed_agents/runtime.rs b/desktop/src-tauri/src/managed_agents/runtime.rs index 0ce5ca7b219..6b04f4a4bd1 100644 --- a/desktop/src-tauri/src/managed_agents/runtime.rs +++ b/desktop/src-tauri/src/managed_agents/runtime.rs @@ -293,8 +293,7 @@ pub fn build_managed_agent_summary( env: Default::default(), } }); - let effective_mcp_command = known_acp_runtime(&descriptor.command) - .and_then(|r| r.mcp_command) + let effective_mcp_command = crate::managed_agents::resolve_mcp_command(&descriptor.command) .unwrap_or("") .to_string(); @@ -477,8 +476,7 @@ pub fn spawn_agent_child( .map_err(|error| format!("failed to clone log handle: {error}"))?; let resolved_acp_command = resolve_command(&record.acp_command) .ok_or_else(|| missing_command_message(&record.acp_command, "ACP harness command"))?; - let effective_mcp_command = known_acp_runtime(effective_command) - .and_then(|r| r.mcp_command) + let effective_mcp_command = crate::managed_agents::resolve_mcp_command(effective_command) .unwrap_or(""); let resolved_mcp_command: Option = if effective_mcp_command.is_empty() { None diff --git a/desktop/src-tauri/src/managed_agents/spawn_snapshot.rs b/desktop/src-tauri/src/managed_agents/spawn_snapshot.rs index 8a6f68a693d..a26469caa19 100644 --- a/desktop/src-tauri/src/managed_agents/spawn_snapshot.rs +++ b/desktop/src-tauri/src/managed_agents/spawn_snapshot.rs @@ -173,8 +173,7 @@ impl SpawnConfigSnapshot { acp_command: record.acp_command.clone(), command: descriptor.command.clone(), args: descriptor.args.clone(), - mcp_command: known_acp_runtime(&descriptor.command) - .and_then(|runtime| runtime.mcp_command) + mcp_command: crate::managed_agents::resolve_mcp_command(&descriptor.command) .unwrap_or("") .to_string(), // Effort has ONE representation in the snapshot: `effort_level` From 474a18c5eaddfd259efd9ea0953e266a46519f0f Mon Sep 17 00:00:00 2001 From: Taksh Date: Sun, 30 Aug 2026 09:37:21 +0530 Subject: [PATCH 2/2] chore: retrigger ci Signed-off-by: Chessing234