Fix Codex Apps auth elicitation hang (#29615)

## Summary
- Require the reserved Codex Apps MCP server name to be present in the
connection manager before treating it as host-owned.
- Update auth elicitation tests to model an installed host-owned Codex
Apps server without sending startup events to the test session.

## Why
PR #29518 replaced the old host-owned flag with a name-only check. That
made non-host-owned tests with the reserved codex_apps name enter auth
elicitation and wait forever for a response.
This commit is contained in:
jif
2026-06-23 12:45:42 +01:00
committed by GitHub
Unverified
parent 63f8f547c0
commit 55bc38a22b
3 changed files with 49 additions and 4 deletions
+1 -1
View File
@@ -391,7 +391,7 @@ impl McpConnectionManager {
}
pub fn is_host_owned_codex_apps_server(&self, server_name: &str) -> bool {
server_name == CODEX_APPS_MCP_SERVER_NAME
server_name == CODEX_APPS_MCP_SERVER_NAME && self.server_metadata.contains_key(server_name)
}
pub fn set_approval_policy(&self, approval_policy: &Constrained<AskForApproval>) {
@@ -1177,6 +1177,41 @@ fn server_metadata_preserves_tool_approval_policy() {
);
}
#[test]
fn host_owned_codex_apps_requires_server_metadata() {
let approval_policy = Constrained::allow_any(AskForApproval::OnFailure);
let permission_profile = Constrained::allow_any(PermissionProfile::default());
let manager = McpConnectionManager::new_uninitialized(
&approval_policy,
&permission_profile,
/*prefix_mcp_tool_names*/ true,
);
assert!(!manager.is_host_owned_codex_apps_server(CODEX_APPS_MCP_SERVER_NAME));
}
#[test]
fn host_owned_codex_apps_matches_reserved_name_with_server_metadata() {
let approval_policy = Constrained::allow_any(AskForApproval::OnFailure);
let permission_profile = Constrained::allow_any(PermissionProfile::default());
let mut manager = McpConnectionManager::new_uninitialized(
&approval_policy,
&permission_profile,
/*prefix_mcp_tool_names*/ true,
);
let server = EffectiveMcpServer::configured(crate::codex_apps_mcp_server_config(
"https://chatgpt.com",
/*apps_mcp_product_sku*/ None,
));
manager.server_metadata.insert(
CODEX_APPS_MCP_SERVER_NAME.to_string(),
McpServerMetadata::from(&server),
);
assert!(manager.is_host_owned_codex_apps_server(CODEX_APPS_MCP_SERVER_NAME));
assert!(!manager.is_host_owned_codex_apps_server("docs"));
}
#[tokio::test]
async fn no_local_runtime_fails_local_stdio_but_keeps_local_http_server() {
let approval_policy = Constrained::allow_any(AskForApproval::OnFailure);
+13 -3
View File
@@ -1335,15 +1335,25 @@ fn codex_apps_auth_failure_metadata() -> McpToolApprovalMetadata {
async fn install_host_owned_codex_apps_manager(session: &Session, turn_context: &TurnContext) {
let auth = session.services.auth_manager.auth().await;
let startup_cancellation_token = CancellationToken::new();
startup_cancellation_token.cancel();
let (tx_event, _rx_event) = async_channel::unbounded();
let mcp_servers = HashMap::from([(
CODEX_APPS_MCP_SERVER_NAME.to_string(),
codex_mcp::EffectiveMcpServer::configured(codex_mcp::codex_apps_mcp_server_config(
"https://chatgpt.com",
/*apps_mcp_product_sku*/ None,
)),
)]);
let manager = codex_mcp::McpConnectionManager::new(
&HashMap::new(),
&mcp_servers,
turn_context.config.mcp_oauth_credentials_store_mode,
turn_context.config.auth_keyring_backend_kind(),
HashMap::new(),
&turn_context.approval_policy,
turn_context.sub_id.clone(),
session.get_tx_event(),
CancellationToken::new(),
tx_event,
startup_cancellation_token,
turn_context.permission_profile(),
codex_mcp::McpRuntimeContext::new(
session.services.turn_environments.environment_manager(),