Avoid local MCP gating for remote startup

This commit is contained in:
Charlie Marsh
2026-07-05 18:59:42 -04:00
parent 740a08a37f
commit 3a758d5ef6
4 changed files with 62 additions and 14 deletions
+1 -7
View File
@@ -1116,13 +1116,7 @@ See the Codex keymap documentation for supported actions and examples."
}
if allow_startup_text && let Some(startup_text) = tui.take_startup_text()? {
let expected_mcp_servers = app
.config
.mcp_servers
.get()
.iter()
.filter_map(|(name, server)| server.enabled.then_some(name.clone()))
.collect::<Vec<_>>();
let expected_mcp_servers = app.expected_mcp_startup_servers();
app.chat_widget
.restore_startup_draft(&startup_text, expected_mcp_servers);
}
+12 -6
View File
@@ -16,14 +16,20 @@ use codex_app_server_protocol::ServerNotification;
use codex_app_server_protocol::ServerRequest;
impl App {
pub(super) fn refresh_mcp_startup_expected_servers_from_config(&mut self) {
let enabled_config_mcp_servers: Vec<String> = self
.config
pub(super) fn expected_mcp_startup_servers(&self) -> Vec<String> {
if self.app_server_target.uses_remote_workspace() {
return Vec::new();
}
self.config
.mcp_servers
.get()
.iter()
.filter_map(|(name, server)| server.enabled.then_some(name.clone()))
.collect();
.collect()
}
pub(super) fn refresh_mcp_startup_expected_servers(&mut self) {
let enabled_config_mcp_servers = self.expected_mcp_startup_servers();
self.chat_widget
.set_mcp_startup_expected_servers(enabled_config_mcp_servers);
}
@@ -39,7 +45,7 @@ impl App {
skipped,
"app-server event consumer lagged; dropping ignored events"
);
self.refresh_mcp_startup_expected_servers_from_config();
self.refresh_mcp_startup_expected_servers();
self.chat_widget.finish_mcp_startup_after_lag();
}
AppServerEvent::ServerNotification(notification) => {
@@ -73,7 +79,7 @@ impl App {
}
}
ServerNotification::McpServerStatusUpdated(_) => {
self.refresh_mcp_startup_expected_servers_from_config();
self.refresh_mcp_startup_expected_servers();
}
ServerNotification::AccountRateLimitsUpdated(notification) => {
self.chat_widget
+48
View File
@@ -245,6 +245,54 @@ async fn startup_without_restored_draft_uses_normal_queued_submission() {
);
}
#[tokio::test]
async fn remote_startup_draft_does_not_wait_for_local_mcp_servers() {
let (mut app, _app_event_rx, mut op_rx) = make_test_app_with_channels().await;
let local_only_config = toml::from_str::<toml::Value>("command = 'true'")
.expect("test MCP config should parse")
.try_into()
.expect("test MCP config should deserialize");
app.config
.mcp_servers
.set(std::collections::HashMap::from([(
"local-only".to_string(),
local_only_config,
)]))
.expect("test MCP servers should accept any configuration");
assert_eq!(
app.expected_mcp_startup_servers(),
vec!["local-only".to_string()]
);
app.app_server_target = crate::AppServerTarget::Remote {
endpoint: codex_app_server_client::RemoteAppServerEndpoint::WebSocket {
websocket_url: "wss://remote.example.test".to_string(),
auth_token: None,
},
};
let expected_mcp_servers = app.expected_mcp_startup_servers();
assert_eq!(expected_mcp_servers, Vec::<String>::new());
app.chat_widget
.restore_startup_draft("captured during startup", expected_mcp_servers);
app.chat_widget.handle_thread_session(test_thread_session(
ThreadId::new(),
test_path_buf("/tmp/remote-project"),
));
app.chat_widget
.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE));
match next_user_turn_op(&mut op_rx) {
Op::UserTurn { items, .. } => assert_eq!(
items,
vec![UserInput::Text {
text: "captured during startup".to_string(),
text_elements: Vec::new(),
}]
),
other => panic!("expected remote startup draft submission, got {other:?}"),
}
}
#[tokio::test]
async fn startup_thread_start_failure_returns_error() {
let (mut app, _app_event_rx, _op_rx) = make_test_app_with_channels().await;
+1 -1
View File
@@ -1316,7 +1316,7 @@ impl App {
snapshot: ThreadEventSnapshot,
resume_restored_queue: bool,
) {
self.refresh_mcp_startup_expected_servers_from_config();
self.refresh_mcp_startup_expected_servers();
let should_buffer_replay = !snapshot.turns.is_empty() || !snapshot.events.is_empty();
if should_buffer_replay {
self.app_event_tx