mirror of
https://github.com/openai/codex.git
synced 2026-10-22 17:58:46 +00:00
fix(rmcp-client): accept empty one-way responses
This commit is contained in:
@@ -45,6 +45,10 @@ mod www_authenticate;
|
||||
|
||||
use self::www_authenticate::insufficient_scope_challenge;
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "http_client_adapter_tests.rs"]
|
||||
mod tests;
|
||||
|
||||
const EVENT_STREAM_MIME_TYPE: &str = "text/event-stream";
|
||||
const JSON_MIME_TYPE: &str = "application/json";
|
||||
const HEADER_SESSION_ID: &str = "Mcp-Session-Id";
|
||||
@@ -215,7 +219,14 @@ impl StreamableHttpClient for StreamableHttpClientAdapter {
|
||||
}
|
||||
Some(content_type) if content_type.starts_with(JSON_MIME_TYPE) => {
|
||||
let body = collect_body(&mut body_stream).await?;
|
||||
if body.is_empty() && matches!(message, JsonRpcMessage::Notification(_)) {
|
||||
if body.is_empty()
|
||||
&& matches!(
|
||||
message,
|
||||
JsonRpcMessage::Response(_)
|
||||
| JsonRpcMessage::Notification(_)
|
||||
| JsonRpcMessage::Error(_)
|
||||
)
|
||||
{
|
||||
return Ok(StreamableHttpPostResponse::Accepted);
|
||||
}
|
||||
let message: ServerJsonRpcMessage =
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
use codex_exec_server::Environment;
|
||||
use reqwest::header::HeaderMap;
|
||||
use rmcp::ErrorData;
|
||||
use rmcp::model::ClientJsonRpcMessage;
|
||||
use rmcp::model::ClientResult;
|
||||
use rmcp::model::RequestId;
|
||||
use rmcp::transport::streamable_http_client::StreamableHttpClient;
|
||||
use rmcp::transport::streamable_http_client::StreamableHttpPostResponse;
|
||||
use wiremock::Mock;
|
||||
use wiremock::MockServer;
|
||||
use wiremock::ResponseTemplate;
|
||||
use wiremock::matchers::method;
|
||||
use wiremock::matchers::path;
|
||||
|
||||
use super::StreamableHttpClientAdapter;
|
||||
|
||||
#[tokio::test]
|
||||
async fn accepts_empty_ok_for_one_way_client_messages() {
|
||||
let server = MockServer::start().await;
|
||||
Mock::given(method("POST"))
|
||||
.and(path("/mcp"))
|
||||
.respond_with(ResponseTemplate::new(200).insert_header("content-type", "application/json"))
|
||||
.expect(2)
|
||||
.mount(&server)
|
||||
.await;
|
||||
|
||||
let adapter = StreamableHttpClientAdapter::new(
|
||||
Environment::default_for_tests().get_http_client(),
|
||||
HeaderMap::new(),
|
||||
/*auth_provider*/ None,
|
||||
);
|
||||
let messages = [
|
||||
(
|
||||
"response",
|
||||
ClientJsonRpcMessage::response(
|
||||
ClientResult::empty(()),
|
||||
RequestId::String("response-id".into()),
|
||||
),
|
||||
),
|
||||
(
|
||||
"error",
|
||||
ClientJsonRpcMessage::error(
|
||||
ErrorData::internal_error("test error", /*data*/ None),
|
||||
Some(RequestId::String("error-id".into())),
|
||||
),
|
||||
),
|
||||
];
|
||||
|
||||
for (message_kind, message) in messages {
|
||||
let result = adapter
|
||||
.post_message(
|
||||
Arc::from(format!("{}/mcp", server.uri())),
|
||||
message,
|
||||
/*session_id*/ None,
|
||||
/*auth_token*/ None,
|
||||
HashMap::new(),
|
||||
)
|
||||
.await;
|
||||
|
||||
assert!(
|
||||
matches!(result, Ok(StreamableHttpPostResponse::Accepted)),
|
||||
"expected empty response for {message_kind} to be accepted, got {result:?}"
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user