diff --git a/codex-rs/Cargo.lock b/codex-rs/Cargo.lock index 4961486e65..0692979a0c 100644 --- a/codex-rs/Cargo.lock +++ b/codex-rs/Cargo.lock @@ -5009,9 +5009,9 @@ dependencies = [ [[package]] name = "rmcp" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fdad1258f7259fdc0f2dfc266939c82c3b5d1fd72bcde274d600cdc27e60243" +checksum = "a2c66318b30535ccd0d3b39afaa4240d6b5a35328fb7672a28e3386c97472805" dependencies = [ "base64", "bytes", @@ -5043,9 +5043,9 @@ dependencies = [ [[package]] name = "rmcp-macros" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ede0589a208cc7ce81d1be68aa7e74b917fcd03c81528408bab0457e187dcd9b" +checksum = "49a19193e0d69bb1c96324b1b4daec078d4c8e76d734e53404c107437858a4d2" dependencies = [ "darling 0.21.3", "proc-macro2", diff --git a/codex-rs/Cargo.toml b/codex-rs/Cargo.toml index 73c401b034..3de8d47d59 100644 --- a/codex-rs/Cargo.toml +++ b/codex-rs/Cargo.toml @@ -162,7 +162,7 @@ ratatui = "0.29.0" ratatui-macros = "0.6.0" regex-lite = "0.1.7" reqwest = "0.12" -rmcp = { version = "0.8.3", default-features = false } +rmcp = { version = "0.8.4", default-features = false } schemars = "0.8.22" seccompiler = "0.5.0" sentry = "0.34.0" @@ -256,7 +256,12 @@ unwrap_used = "deny" # cargo-shear cannot see the platform-specific openssl-sys usage, so we # silence the false positive here instead of deleting a real dependency. [workspace.metadata.cargo-shear] -ignored = ["icu_provider", "openssl-sys", "codex-utils-readiness", "codex-utils-tokenizer"] +ignored = [ + "icu_provider", + "openssl-sys", + "codex-utils-readiness", + "codex-utils-tokenizer", +] [profile.release] lto = "fat" diff --git a/codex-rs/rmcp-client/src/bin/test_streamable_http_server.rs b/codex-rs/rmcp-client/src/bin/test_streamable_http_server.rs index 30d8fd7fdf..f56a858241 100644 --- a/codex-rs/rmcp-client/src/bin/test_streamable_http_server.rs +++ b/codex-rs/rmcp-client/src/bin/test_streamable_http_server.rs @@ -10,9 +10,11 @@ use axum::extract::State; use axum::http::Request; use axum::http::StatusCode; use axum::http::header::AUTHORIZATION; +use axum::http::header::CONTENT_TYPE; use axum::middleware; use axum::middleware::Next; use axum::response::Response; +use axum::routing::get; use rmcp::ErrorData as McpError; use rmcp::handler::server::ServerHandler; use rmcp::model::CallToolRequestParam; @@ -256,14 +258,35 @@ async fn main() -> Result<(), Box> { }; eprintln!("starting rmcp streamable http test server on http://{bind_addr}/mcp"); - let router = Router::new().nest_service( - "/mcp", - StreamableHttpService::new( - || Ok(TestToolServer::new()), - Arc::new(LocalSessionManager::default()), - StreamableHttpServerConfig::default(), - ), - ); + let router = Router::new() + .route( + "/.well-known/oauth-authorization-server/mcp", + get({ + move || async move { + let metadata_base = format!("http://{bind_addr}"); + #[expect(clippy::expect_used)] + Response::builder() + .status(StatusCode::OK) + .header(CONTENT_TYPE, "application/json") + .body(Body::from( + serde_json::to_vec(&json!({ + "authorization_endpoint": format!("{metadata_base}/oauth/authorize"), + "token_endpoint": format!("{metadata_base}/oauth/token"), + "scopes_supported": [""], + })).expect("failed to serialize metadata"), + )) + .expect("valid metadata response") + } + }), + ) + .nest_service( + "/mcp", + StreamableHttpService::new( + || Ok(TestToolServer::new()), + Arc::new(LocalSessionManager::default()), + StreamableHttpServerConfig::default(), + ), + ); let router = if let Ok(token) = std::env::var("MCP_EXPECT_BEARER") { let expected = Arc::new(format!("Bearer {token}")); @@ -282,6 +305,9 @@ async fn require_bearer( request: Request, next: Next, ) -> Result { + if request.uri().path().contains("/.well-known/") { + return Ok(next.run(request).await); + } if request .headers() .get(AUTHORIZATION)