Files
codex/codex-rs/rmcp-client/src/incoming_jsonrpc.rs
T
thomas a05bcda3db Upgrade rmcp to 3.0.0 (#36001)
## What changed

- Update the Rust MCP SDK from `3.0.0-beta.3` to `3.0.0` and adapt to its renamed metadata and server discovery types.
- Accept discovery responses without server identity metadata, using the configured server name as a fallback, and rely on the SDK's native support for namespaced server identity metadata.
- Preserve typed OAuth HTTP errors so transport failures, cross-origin redirects, and transient HTTP responses are reported instead of being treated as anonymous access.

## Testing

- Cover modern discovery with namespaced or missing server identity over HTTP, SSE, and stdio.
- Cover OAuth discovery error propagation for transport failures, redirects, and transient status codes.

GitOrigin-RevId: 12c1e45136cca89ce4fb15986c2b5df14608682a
2026-07-29 17:38:20 +00:00

59 lines
1.8 KiB
Rust

//! Compatibility decoding for multi-round-trip tool results that rmcp's
//! untagged result union does not yet represent correctly.
use rmcp::model::InputRequiredResult;
use rmcp::model::JsonRpcResponse;
use rmcp::model::ServerJsonRpcMessage;
use rmcp::model::ServerResult;
use serde_json::Value;
/// Decode at the transport boundary, before rmcp's untagged `ServerResult`
/// deserializer can mistake a modern result for a completed tool call.
pub(crate) fn deserialize_incoming_jsonrpc_message(
bytes: &[u8],
) -> serde_json::Result<ServerJsonRpcMessage> {
let message: Value = serde_json::from_slice(bytes)?;
if message
.pointer("/result/resultType")
.and_then(Value::as_str)
== Some("input_required")
{
let response: JsonRpcResponse<InputRequiredResult> = serde_json::from_value(message)?;
return Ok(ServerJsonRpcMessage::response(
ServerResult::InputRequiredResult(response.result),
response.id,
));
}
serde_json::from_value(message)
}
/// Normalize an SSE payload before rmcp parses it internally. SSE does not
/// expose a typed-message hook, so response-level MRTR metadata cannot be
/// retained until the upstream untagged-result decoder is fixed.
pub(crate) fn normalize_sse_jsonrpc_message(payload: &str, modern_session: bool) -> Option<String> {
if !modern_session {
return None;
}
let mut message: Value = serde_json::from_str(payload).ok()?;
if message
.pointer("/result/resultType")
.and_then(Value::as_str)
!= Some("input_required")
{
return None;
}
message
.get_mut("result")
.and_then(Value::as_object_mut)?
.remove("_meta")?;
serde_json::to_string(&message).ok()
}
#[cfg(test)]
#[path = "incoming_jsonrpc_tests.rs"]
mod tests;