Creates a [ToolManager] based on the current fields populated, which consists of the following: - Instantiates child processes associated with the list of mcp servers in scope - Spawns a loading display task that is used to show server loading status (if applicable) - Spawns the orchestrator task (see [spawn_orchestrator_task] for more detail) (if applicable) - Finally, creates an instance of [Too
(
mut self,
os: &mut Os,
mut output: Box<dyn Write + Send + Sync + 'static>,
interactive: bool,
)
| 274 | /// applicable) |
| 275 | /// - Finally, creates an instance of [ToolManager] |
| 276 | pub async fn build( |
| 277 | mut self, |
| 278 | os: &mut Os, |
| 279 | mut output: Box<dyn Write + Send + Sync + 'static>, |
| 280 | interactive: bool, |
| 281 | ) -> eyre::Result<ToolManager> { |
| 282 | let McpServerConfig { mcp_servers } = match &self.agent { |
| 283 | Some(agent) => agent.lock().await.mcp_servers.clone(), |
| 284 | None => Default::default(), |
| 285 | }; |
| 286 | debug_assert!(self.conversation_id.is_some()); |
| 287 | let conversation_id = self.conversation_id.ok_or(eyre::eyre!("Missing conversation id"))?; |
| 288 | |
| 289 | // Separate enabled and disabled servers |
| 290 | let (enabled_servers, disabled_servers): (Vec<_>, Vec<_>) = mcp_servers |
| 291 | .into_iter() |
| 292 | .partition(|(_, server_config)| !server_config.disabled); |
| 293 | |
| 294 | // Prepare disabled servers for display |
| 295 | let disabled_servers_display: Vec<String> = disabled_servers |
| 296 | .iter() |
| 297 | .map(|(server_name, _)| server_name.clone()) |
| 298 | .collect(); |
| 299 | |
| 300 | let pre_initialized = enabled_servers |
| 301 | .iter() |
| 302 | .filter(|(server_name, _)| { |
| 303 | if server_name == "builtin" { |
| 304 | let _ = queue!( |
| 305 | output, |
| 306 | StyledText::error_fg(), |
| 307 | style::Print("✗ Invalid server name "), |
| 308 | StyledText::info_fg(), |
| 309 | style::Print(&server_name), |
| 310 | StyledText::reset(), |
| 311 | style::Print(". Server name cannot contain reserved word "), |
| 312 | StyledText::warning_fg(), |
| 313 | style::Print("builtin"), |
| 314 | StyledText::reset(), |
| 315 | style::Print(" (it is used to denote native tools)\n") |
| 316 | ); |
| 317 | false |
| 318 | } else { |
| 319 | true |
| 320 | } |
| 321 | }) |
| 322 | .collect::<Vec<_>>(); |
| 323 | |
| 324 | let mut clients = HashMap::<String, InitializedMcpClient>::new(); |
| 325 | let new_tool_specs = self.new_tool_specs; |
| 326 | let has_new_stuff = self.has_new_stuff; |
| 327 | let pending = self.pending_clients.unwrap_or(Arc::new(RwLock::new({ |
| 328 | let mut pending = HashSet::<String>::new(); |
| 329 | pending.extend(pre_initialized.iter().map(|(name, _)| name.clone())); |
| 330 | pending |
| 331 | }))); |
| 332 | let notify = Arc::new(Notify::new()); |
| 333 | let load_record = self.mcp_load_record; |