diff --git a/nori-rs/tui/src/app/config_persistence.rs b/nori-rs/tui/src/app/config_persistence.rs index 46ef3ba51..c0728e55b 100644 --- a/nori-rs/tui/src/app/config_persistence.rs +++ b/nori-rs/tui/src/app/config_persistence.rs @@ -345,6 +345,12 @@ impl App { return; } + // Sync in-memory state so that ComputeMcpAuthStatuses (which reads + // chat_widget.config_ref().mcp_servers) sees the newly added servers. + self.config.mcp_servers = servers.into_iter().collect(); + self.chat_widget + .set_mcp_servers(self.config.mcp_servers.clone()); + self.chat_widget.add_info_message( "MCP servers updated. Restart to apply changes.".to_string(), None, diff --git a/nori-rs/tui/src/chatwidget/helpers.rs b/nori-rs/tui/src/chatwidget/helpers.rs index f34017068..5db8be0d8 100644 --- a/nori-rs/tui/src/chatwidget/helpers.rs +++ b/nori-rs/tui/src/chatwidget/helpers.rs @@ -203,6 +203,15 @@ impl ChatWidget { &self.config } + /// Update the in-memory MCP server map so that subsequent reads via + /// `config_ref().mcp_servers` reflect the latest persisted state. + pub(crate) fn set_mcp_servers( + &mut self, + servers: std::collections::HashMap, + ) { + self.config.mcp_servers = servers; + } + /// Forward MCP auth statuses to the active bottom pane view. pub(crate) fn update_mcp_auth_statuses( &mut self, diff --git a/nori-rs/tui/src/chatwidget/tests/part7.rs b/nori-rs/tui/src/chatwidget/tests/part7.rs index ff35fa883..5c8762dec 100644 --- a/nori-rs/tui/src/chatwidget/tests/part7.rs +++ b/nori-rs/tui/src/chatwidget/tests/part7.rs @@ -1,4 +1,50 @@ use super::*; +use codex_core::config::types::McpServerConfig; +use codex_core::config::types::McpServerTransportConfig; + +#[test] +fn set_mcp_servers_updates_config_ref() { + let (mut chat, _rx, _op_rx) = make_chatwidget_manual(); + + // Initially empty + assert!( + chat.config_ref().mcp_servers.is_empty(), + "mcp_servers should start empty" + ); + + // Set servers + let mut servers = std::collections::HashMap::new(); + servers.insert( + "test-server".to_string(), + McpServerConfig { + transport: McpServerTransportConfig::StreamableHttp { + url: "https://example.com/mcp".to_string(), + bearer_token_env_var: None, + http_headers: None, + env_http_headers: None, + client_id: None, + client_secret_env_var: None, + }, + enabled: true, + startup_timeout_sec: None, + tool_timeout_sec: None, + enabled_tools: None, + disabled_tools: None, + }, + ); + chat.set_mcp_servers(servers.clone()); + + // config_ref should now reflect the updated servers + assert_eq!( + chat.config_ref().mcp_servers.len(), + 1, + "config_ref should show 1 server after set_mcp_servers" + ); + assert!( + chat.config_ref().mcp_servers.contains_key("test-server"), + "config_ref should contain 'test-server'" + ); +} #[test] fn cancelling_phase_keeps_task_running_until_prompt_completed() {