mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
Upgrade rmcp to 3.0.0-beta.3 (#35720)
## What changed - Update the `rmcp` model and transport integrations for `3.0.0-beta.3`. - Preserve legacy `elicitation/create` form requests, schema defaults, metadata, and wire-format compatibility while adopting the new elicitation types. - Harden OAuth discovery by using GET-first discovery without starting an MCP session, preventing cross-origin header redirects, validating authorization-server and callback issuers, and retaining compatibility with metadata that omits an issuer. - Keep stored OAuth credentials readable and avoid requiring reauthorization after transient refresh failures. ## Testing - Add coverage for legacy elicitation round trips, OAuth discovery variants, callback issuer validation, credential migration, and refresh failures. GitOrigin-RevId: 756197d26f3fd347c28c400228f6b3d06ed493b7
This commit is contained in:
1 parent
899539c03a
commit
61de0d8fe8
48 files changed
+1391
-639
No files matched your search
@@ -287,6 +287,7 @@ impl From<rmcp::model::ElicitationAction> for McpServerElicitationAction {
|
||||
rmcp::model::ElicitationAction::Accept => Self::Accept,
|
||||
rmcp::model::ElicitationAction::Decline => Self::Decline,
|
||||
rmcp::model::ElicitationAction::Cancel => Self::Cancel,
|
||||
_ => Self::Cancel,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -344,10 +345,38 @@ pub enum McpElicitationObjectType {
|
||||
pub enum McpElicitationPrimitiveSchema {
|
||||
Enum(McpElicitationEnumSchema),
|
||||
String(McpElicitationStringSchema),
|
||||
#[serde(serialize_with = "serialize_mcp_elicitation_number_schema")]
|
||||
Number(McpElicitationNumberSchema),
|
||||
Boolean(McpElicitationBooleanSchema),
|
||||
}
|
||||
|
||||
fn serialize_mcp_elicitation_number_schema<S>(
|
||||
schema: &McpElicitationNumberSchema,
|
||||
serializer: S,
|
||||
) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
if schema.type_ != McpElicitationNumberType::Integer {
|
||||
return schema.serialize(serializer);
|
||||
}
|
||||
|
||||
let mut value = serde_json::to_value(schema).map_err(serde::ser::Error::custom)?;
|
||||
if let Some(object) = value.as_object_mut() {
|
||||
for key in ["minimum", "maximum", "default"] {
|
||||
if let Some(value) = object.get_mut(key)
|
||||
&& let Some(number) = value.as_f64()
|
||||
&& number.fract() == 0.0
|
||||
&& number >= i64::MIN as f64
|
||||
&& number < -(i64::MIN as f64)
|
||||
{
|
||||
*value = serde_json::Value::from(number as i64);
|
||||
}
|
||||
}
|
||||
}
|
||||
value.serialize(serializer)
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
#[ts(export_to = "v2/")]
|
||||
@@ -716,18 +745,16 @@ pub struct McpServerElicitationRequestResponse {
|
||||
pub meta: Option<JsonValue>,
|
||||
}
|
||||
|
||||
impl From<McpServerElicitationRequestResponse> for rmcp::model::CreateElicitationResult {
|
||||
impl From<McpServerElicitationRequestResponse> for rmcp::model::ElicitResult {
|
||||
fn from(value: McpServerElicitationRequestResponse) -> Self {
|
||||
Self {
|
||||
action: value.action.into(),
|
||||
content: value.content,
|
||||
meta: None,
|
||||
}
|
||||
let mut result = Self::new(value.action.into());
|
||||
result.content = value.content;
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
impl From<rmcp::model::CreateElicitationResult> for McpServerElicitationRequestResponse {
|
||||
fn from(value: rmcp::model::CreateElicitationResult) -> Self {
|
||||
impl From<rmcp::model::ElicitResult> for McpServerElicitationRequestResponse {
|
||||
fn from(value: rmcp::model::ElicitResult) -> Self {
|
||||
Self {
|
||||
action: value.action.into(),
|
||||
content: value.content,
|
||||
|
||||
@@ -1989,13 +1989,10 @@ fn client_request_turn_start_granular_approval_policy_is_marked_experimental() {
|
||||
|
||||
#[test]
|
||||
fn mcp_server_elicitation_response_round_trips_rmcp_result() {
|
||||
let rmcp_result = rmcp::model::CreateElicitationResult {
|
||||
action: rmcp::model::ElicitationAction::Accept,
|
||||
content: Some(json!({
|
||||
let rmcp_result = rmcp::model::ElicitResult::new(rmcp::model::ElicitationAction::Accept)
|
||||
.with_content(json!({
|
||||
"confirmed": true,
|
||||
})),
|
||||
meta: None,
|
||||
};
|
||||
}));
|
||||
|
||||
let v2_response = McpServerElicitationRequestResponse::from(rmcp_result.clone());
|
||||
assert_eq!(
|
||||
@@ -2008,10 +2005,7 @@ fn mcp_server_elicitation_response_round_trips_rmcp_result() {
|
||||
meta: None,
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
rmcp::model::CreateElicitationResult::from(v2_response),
|
||||
rmcp_result
|
||||
);
|
||||
assert_eq!(rmcp::model::ElicitResult::from(v2_response), rmcp_result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -2204,6 +2198,45 @@ fn mcp_elicitation_schema_matches_mcp_2025_11_25_primitives() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mcp_elicitation_preserves_integer_and_number_schema_wire_values() {
|
||||
for (number_type, expected_type, expected_minimum, expected_maximum, expected_default) in [
|
||||
(
|
||||
McpElicitationNumberType::Integer,
|
||||
"integer",
|
||||
json!(1),
|
||||
json!(99),
|
||||
json!(30),
|
||||
),
|
||||
(
|
||||
McpElicitationNumberType::Number,
|
||||
"number",
|
||||
json!(1.0),
|
||||
json!(99.0),
|
||||
json!(30.0),
|
||||
),
|
||||
] {
|
||||
let schema = McpElicitationPrimitiveSchema::Number(McpElicitationNumberSchema {
|
||||
type_: number_type,
|
||||
title: None,
|
||||
description: None,
|
||||
minimum: Some(1.0),
|
||||
maximum: Some(99.0),
|
||||
default: Some(30.0),
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
serde_json::to_value(schema).expect("numeric elicitation schema must serialize"),
|
||||
json!({
|
||||
"type": expected_type,
|
||||
"minimum": expected_minimum,
|
||||
"maximum": expected_maximum,
|
||||
"default": expected_default,
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mcp_server_elicitation_request_rejects_null_core_form_schema() {
|
||||
let result = McpServerElicitationRequest::try_from(CoreElicitationRequest::Form {
|
||||
|
||||
Reference in new issue
Block a user