test(core): make mcp readiness waits state aware

This commit is contained in:
Felipe Coury
2026-05-30 15:36:48 -03:00
parent b22e26cf48
commit 3b9d2faa17
3 changed files with 26 additions and 25 deletions

View File

@@ -23,6 +23,7 @@ use codex_protocol::openai_models::ReasoningEffort;
use codex_protocol::protocol::AdditionalContextEntry;
use codex_protocol::protocol::AskForApproval;
use codex_protocol::protocol::Event;
use codex_protocol::protocol::McpStartupFailure;
use codex_protocol::protocol::Op;
use codex_protocol::protocol::SandboxPolicy;
use codex_protocol::protocol::SessionConfiguredEvent;
@@ -142,6 +143,24 @@ impl CodexThread {
self.codex.shutdown_and_wait().await
}
#[doc(hidden)]
pub async fn wait_for_mcp_servers_ready(
&self,
server_names: &[String],
) -> Vec<McpStartupFailure> {
let readiness = {
let manager = self
.codex
.session
.services
.mcp_connection_manager
.read()
.await;
manager.wait_for_servers_ready(server_names)
};
readiness.await
}
/// Wait until the underlying session loop has terminated.
pub async fn wait_until_terminated(&self) {
self.codex.session_loop_termination.clone().await;

View File

@@ -250,34 +250,12 @@ where
/// Waits for a configured MCP server to finish startup and requires it to be ready.
pub async fn wait_for_mcp_server(codex: &CodexThread, server_name: &str) -> anyhow::Result<()> {
use codex_protocol::protocol::EventMsg;
// Wait for the startup summary regardless of outcome, then interpret the
// requested server's ready, failed, or cancelled entry below.
let summary = loop {
let event = codex
.next_event()
.await
.expect("stream ended unexpectedly while waiting for MCP startup");
if let EventMsg::McpStartupComplete(summary) = event.msg {
break summary;
}
};
if let Some(failure) = summary
.failed
.iter()
.find(|failure| failure.server == server_name)
{
let server_names = vec![server_name.to_string()];
let failures = codex.wait_for_mcp_servers_ready(&server_names).await;
if let Some(failure) = failures.first() {
let error = &failure.error;
anyhow::bail!("MCP server {server_name} failed to start: {error}");
}
if summary.cancelled.iter().any(|server| server == server_name) {
anyhow::bail!("MCP server {server_name} startup was cancelled");
}
assert!(
summary.ready.iter().any(|server| server == server_name),
"expected MCP server {server_name} to be ready; startup summary: {summary:?}"
);
Ok(())
}

View File

@@ -67,6 +67,7 @@ use core_test_support::skip_if_no_network;
use core_test_support::test_codex::TestCodex;
use core_test_support::test_codex::test_codex;
use core_test_support::wait_for_event;
use core_test_support::wait_for_mcp_server;
use dunce::canonicalize as normalize_path;
use futures::StreamExt;
use pretty_assertions::assert_eq;
@@ -1273,6 +1274,9 @@ async fn includes_apps_guidance_as_developer_message_for_chatgpt_auth() {
.await
.expect("create new conversation")
.codex;
wait_for_mcp_server(&codex, "codex_apps")
.await
.expect("wait for apps MCP startup");
codex
.submit(Op::UserInput {