diff --git a/codex-rs/Cargo.lock b/codex-rs/Cargo.lock index 16616e334fe..f2d48db34da 100644 --- a/codex-rs/Cargo.lock +++ b/codex-rs/Cargo.lock @@ -7395,9 +7395,9 @@ dependencies = [ [[package]] name = "rmcp" -version = "0.14.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a621b37a548ff6ab6292d57841eb25785a7f146d89391a19c9f199414bd13da" +checksum = "1bef41ebc9ebed2c1b1d90203e9d1756091e8a00bbc3107676151f39868ca0ee" dependencies = [ "async-trait", "axum", @@ -7431,9 +7431,9 @@ dependencies = [ [[package]] name = "rmcp-macros" -version = "0.14.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b79ed92303f9262db79575aa8c3652581668e9d136be6fd0b9ededa78954c95" +checksum = "0e88ad84b8b6237a934534a62b379a5be6388915663c0cc598ceb9b3292bbbfe" dependencies = [ "darling 0.23.0", "proc-macro2", diff --git a/codex-rs/Cargo.toml b/codex-rs/Cargo.toml index a615cdac2aa..ab7e131b3ee 100644 --- a/codex-rs/Cargo.toml +++ b/codex-rs/Cargo.toml @@ -214,7 +214,7 @@ ratatui-macros = "0.6.0" regex = "1.12.3" regex-lite = "0.1.8" reqwest = "0.12" -rmcp = { version = "0.14.0", default-features = false } +rmcp = { version = "0.15.0", default-features = false } runfiles = { git = "https://github.com/dzbarsky/rules_rust", rev = "b56cbaa8465e74127f1ea216f813cd377295ad81" } rustls = { version = "0.23", default-features = false, features = [ "ring", diff --git a/codex-rs/core/src/codex.rs b/codex-rs/core/src/codex.rs index 54dd34dbb4c..9b7a393625e 100644 --- a/codex-rs/core/src/codex.rs +++ b/codex-rs/core/src/codex.rs @@ -5393,6 +5393,7 @@ mod tests { input_schema: Arc::new(JsonObject::default()), output_schema: None, annotations: None, + execution: None, icons: None, meta: None, }, diff --git a/codex-rs/core/src/mcp_connection_manager.rs b/codex-rs/core/src/mcp_connection_manager.rs index 6f6bfad6e53..edd1e13f677 100644 --- a/codex-rs/core/src/mcp_connection_manager.rs +++ b/codex-rs/core/src/mcp_connection_manager.rs @@ -43,7 +43,9 @@ use futures::future::BoxFuture; use futures::future::FutureExt; use futures::future::Shared; use rmcp::model::ClientCapabilities; +use rmcp::model::CreateElicitationRequestParams; use rmcp::model::ElicitationCapability; +use rmcp::model::FormElicitationCapability; use rmcp::model::Implementation; use rmcp::model::InitializeRequestParams; use rmcp::model::ListResourceTemplatesResult; @@ -223,7 +225,16 @@ impl ElicitationRequestManager { ProtocolRequestId::Integer(value) } }, - message: elicitation.message, + message: match elicitation { + CreateElicitationRequestParams::FormElicitationParams { + message, + .. + } + | CreateElicitationRequestParams::UrlElicitationParams { + message, + .. + } => message, + }, }), }) .await; @@ -985,12 +996,16 @@ async fn start_server_task( meta: None, capabilities: ClientCapabilities { experimental: None, + extensions: None, roots: None, sampling: None, // https://modelcontextprotocol.io/specification/2025-06-18/client/elicitation#capabilities // indicates this should be an empty object. elicitation: Some(ElicitationCapability { - schema_validation: None, + form: Some(FormElicitationCapability { + schema_validation: None, + }), + url: None, }), tasks: None, }, @@ -998,6 +1013,7 @@ async fn start_server_task( name: "codex-mcp-client".to_owned(), version: env!("CARGO_PKG_VERSION").to_owned(), title: Some("Codex".into()), + description: None, icons: None, website_url: None, }, @@ -1247,6 +1263,7 @@ mod tests { input_schema: Arc::new(JsonObject::default()), output_schema: None, annotations: None, + execution: None, icons: None, meta: None, }, diff --git a/codex-rs/core/src/tools/spec.rs b/codex-rs/core/src/tools/spec.rs index 098f640690f..b8618e0c075 100644 --- a/codex-rs/core/src/tools/spec.rs +++ b/codex-rs/core/src/tools/spec.rs @@ -1624,6 +1624,7 @@ mod tests { input_schema: std::sync::Arc::new(rmcp::model::object(input_schema)), output_schema: None, annotations: None, + execution: None, icons: None, meta: None, } @@ -1641,6 +1642,7 @@ mod tests { input_schema: std::sync::Arc::new(schema), output_schema: None, annotations: None, + execution: None, icons: None, meta: None, }; diff --git a/codex-rs/exec-server/src/posix/mcp_escalation_policy.rs b/codex-rs/exec-server/src/posix/mcp_escalation_policy.rs index 5ef1e60178f..5e6b97f1ad7 100644 --- a/codex-rs/exec-server/src/posix/mcp_escalation_policy.rs +++ b/codex-rs/exec-server/src/posix/mcp_escalation_policy.rs @@ -69,7 +69,7 @@ impl McpEscalationPolicy { .pause_for(async { context .peer - .create_elicitation(CreateElicitationRequestParams { + .create_elicitation(CreateElicitationRequestParams::FormElicitationParams { meta: None, message: format!( "Allow agent to run `{command}` in `{}`?", diff --git a/codex-rs/exec-server/tests/common/lib.rs b/codex-rs/exec-server/tests/common/lib.rs index 430eb899539..ce9fa052168 100644 --- a/codex-rs/exec-server/tests/common/lib.rs +++ b/codex-rs/exec-server/tests/common/lib.rs @@ -166,7 +166,11 @@ impl ClientHandler for InteractiveClient { .unwrap() .push(request.clone()); - let accept = self.elicitations_to_accept.contains(&request.message); + let message = match &request { + CreateElicitationRequestParams::FormElicitationParams { message, .. } + | CreateElicitationRequestParams::UrlElicitationParams { message, .. } => message, + }; + let accept = self.elicitations_to_accept.contains(message); async move { if accept { Ok(CreateElicitationResult { diff --git a/codex-rs/exec-server/tests/suite/accept_elicitation.rs b/codex-rs/exec-server/tests/suite/accept_elicitation.rs index 7cb7438a510..365a93b8377 100644 --- a/codex-rs/exec-server/tests/suite/accept_elicitation.rs +++ b/codex-rs/exec-server/tests/suite/accept_elicitation.rs @@ -138,7 +138,14 @@ prefix_rule( .lock() .unwrap() .iter() - .map(|r| r.message.clone()) + .map(|r| match r { + rmcp::model::CreateElicitationRequestParams::FormElicitationParams { + message, .. + } + | rmcp::model::CreateElicitationRequestParams::UrlElicitationParams { + message, .. + } => message.clone(), + }) .collect::>(); assert_eq!(vec![expected_elicitation_message], elicitation_messages); diff --git a/codex-rs/exec-server/tests/suite/list_tools.rs b/codex-rs/exec-server/tests/suite/list_tools.rs index 4a28dec5b32..614e8d6d359 100644 --- a/codex-rs/exec-server/tests/suite/list_tools.rs +++ b/codex-rs/exec-server/tests/suite/list_tools.rs @@ -67,6 +67,7 @@ async fn list_tools() -> Result<()> { "type": "object", }))), output_schema: None, + execution: None, annotations: None, icons: None, meta: None diff --git a/codex-rs/mcp-server/src/codex_tool_config.rs b/codex-rs/mcp-server/src/codex_tool_config.rs index 94bf4369a9d..cf34dc280ed 100644 --- a/codex-rs/mcp-server/src/codex_tool_config.rs +++ b/codex-rs/mcp-server/src/codex_tool_config.rs @@ -127,6 +127,7 @@ pub(crate) fn create_tool_for_codex_tool_call_param() -> Tool { .into(), ), annotations: None, + execution: None, icons: None, meta: None, } @@ -248,6 +249,7 @@ pub(crate) fn create_tool_for_codex_tool_call_reply_param() -> Tool { "Continue a Codex conversation by providing the thread id and prompt.".into(), ), annotations: None, + execution: None, icons: None, meta: None, } diff --git a/codex-rs/mcp-server/src/message_processor.rs b/codex-rs/mcp-server/src/message_processor.rs index c3449d50c2f..612582dae47 100644 --- a/codex-rs/mcp-server/src/message_processor.rs +++ b/codex-rs/mcp-server/src/message_processor.rs @@ -209,6 +209,7 @@ impl MessageProcessor { name: "codex-mcp-server".to_string(), title: Some("Codex".to_string()), version: env!("CARGO_PKG_VERSION").to_string(), + description: None, icons: None, website_url: None, }; diff --git a/codex-rs/mcp-server/tests/common/mcp_process.rs b/codex-rs/mcp-server/tests/common/mcp_process.rs index 34c5380818d..92b5caa65a9 100644 --- a/codex-rs/mcp-server/tests/common/mcp_process.rs +++ b/codex-rs/mcp-server/tests/common/mcp_process.rs @@ -18,6 +18,7 @@ use rmcp::model::ClientCapabilities; use rmcp::model::CustomNotification; use rmcp::model::CustomRequest; use rmcp::model::ElicitationCapability; +use rmcp::model::FormElicitationCapability; use rmcp::model::Implementation; use rmcp::model::InitializeRequestParams; use rmcp::model::JsonRpcMessage; @@ -116,9 +117,13 @@ impl McpProcess { meta: None, capabilities: ClientCapabilities { elicitation: Some(ElicitationCapability { - schema_validation: None, + form: Some(FormElicitationCapability { + schema_validation: None, + }), + url: None, }), experimental: None, + extensions: None, roots: None, sampling: None, tasks: None, @@ -127,6 +132,7 @@ impl McpProcess { name: "elicitation test".into(), title: Some("Elicitation Test".into()), version: "0.0.0".into(), + description: None, icons: None, website_url: None, }, diff --git a/codex-rs/rmcp-client/tests/resources.rs b/codex-rs/rmcp-client/tests/resources.rs index efab352ff3d..9e357bfcbd7 100644 --- a/codex-rs/rmcp-client/tests/resources.rs +++ b/codex-rs/rmcp-client/tests/resources.rs @@ -10,6 +10,7 @@ use futures::FutureExt as _; use rmcp::model::AnnotateAble; use rmcp::model::ClientCapabilities; use rmcp::model::ElicitationCapability; +use rmcp::model::FormElicitationCapability; use rmcp::model::Implementation; use rmcp::model::InitializeRequestParams; use rmcp::model::ListResourceTemplatesResult; @@ -29,10 +30,14 @@ fn init_params() -> InitializeRequestParams { meta: None, capabilities: ClientCapabilities { experimental: None, + extensions: None, roots: None, sampling: None, elicitation: Some(ElicitationCapability { - schema_validation: None, + form: Some(FormElicitationCapability { + schema_validation: None, + }), + url: None, }), tasks: None, }, @@ -40,6 +45,7 @@ fn init_params() -> InitializeRequestParams { name: "codex-test".into(), version: "0.0.0-test".into(), title: Some("Codex rmcp resource test".into()), + description: None, icons: None, website_url: None, },