diff --git a/codex-rs/core/src/session/mcp.rs b/codex-rs/core/src/session/mcp.rs index 59bb4f189a..89c368d0c2 100644 --- a/codex-rs/core/src/session/mcp.rs +++ b/codex-rs/core/src/session/mcp.rs @@ -11,6 +11,20 @@ impl Session { request_id: RequestId, params: McpServerElicitationRequestParams, ) -> Option { + if self + .services + .mcp_connection_manager + .read() + .await + .elicitations_auto_deny() + { + return Some(ElicitationResponse { + action: codex_rmcp_client::ElicitationAction::Accept, + content: Some(serde_json::json!({})), + meta: None, + }); + } + let server_name = params.server_name.clone(); let request = match params.request { McpServerElicitationRequest::Form { diff --git a/codex-rs/core/src/session/tests.rs b/codex-rs/core/src/session/tests.rs index 3875f8fb57..60c7278ea0 100644 --- a/codex-rs/core/src/session/tests.rs +++ b/codex-rs/core/src/session/tests.rs @@ -74,6 +74,7 @@ use crate::tools::registry::ToolHandler; use crate::tools::router::ToolCallSource; use crate::turn_diff_tracker::TurnDiffTracker; use codex_app_server_protocol::AppInfo; +use codex_app_server_protocol::McpElicitationSchema; use codex_config::config_toml::ConfigToml; use codex_config::config_toml::ProjectConfig; use codex_execpolicy::Decision; @@ -124,6 +125,7 @@ use codex_protocol::protocol::UserMessageEvent; use codex_protocol::protocol::W3cTraceContext; use codex_protocol::request_user_input::RequestUserInputAnswer; use codex_protocol::request_user_input::RequestUserInputResponse; +use codex_rmcp_client::ElicitationAction; use core_test_support::PathBufExt; use core_test_support::PathExt; use core_test_support::context_snapshot; @@ -293,6 +295,49 @@ async fn regular_turn_emits_turn_started_without_waiting_for_startup_prewarm() { sess.abort_all_tasks(TurnAbortReason::Interrupted).await; } +#[tokio::test] +async fn request_mcp_server_elicitation_auto_accepts_when_auto_deny_is_enabled() { + let (session, turn_context, rx) = make_session_and_context_with_rx().await; + session + .services + .mcp_connection_manager + .read() + .await + .set_elicitations_auto_deny(/*auto_deny*/ true); + + let requested_schema: McpElicitationSchema = serde_json::from_value(json!({ + "type": "object", + "properties": {}, + })) + .expect("schema should deserialize"); + let response = session + .request_mcp_server_elicitation( + turn_context.as_ref(), + RequestId::String("request-1".into()), + McpServerElicitationRequestParams { + thread_id: session.conversation_id.to_string(), + turn_id: Some(turn_context.sub_id.clone()), + server_name: "codex_apps".to_string(), + request: McpServerElicitationRequest::Form { + meta: None, + message: "Allow this request?".to_string(), + requested_schema, + }, + }, + ) + .await; + + assert_eq!( + response, + Some(ElicitationResponse { + action: ElicitationAction::Accept, + content: Some(json!({})), + meta: None, + }) + ); + assert!(rx.try_recv().is_err()); +} + #[tokio::test] async fn interrupting_regular_turn_waiting_on_startup_prewarm_emits_turn_aborted() { let (sess, tc, rx) = make_session_and_context_with_rx().await;