refactor!: remove deprecated v3 APIs (#1066)
This commit is contained in:
parent
0dea39d101
commit
25213a271a
11 changed files with 72 additions and 249 deletions
|
|
@ -1,10 +1,6 @@
|
||||||
use std::{borrow::Cow, fmt::Display};
|
use std::{borrow::Cow, fmt::Display};
|
||||||
|
|
||||||
pub use crate::model::ErrorData;
|
pub use crate::model::ErrorData;
|
||||||
#[deprecated(
|
|
||||||
note = "Use `rmcp::ErrorData` instead, `rmcp::ErrorData` could become `RmcpError` in the future."
|
|
||||||
)]
|
|
||||||
pub type Error = ErrorData;
|
|
||||||
impl Display for ErrorData {
|
impl Display for ErrorData {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "{}: {}", self.code.0, self.message)?;
|
write!(f, "{}: {}", self.code.0, self.message)?;
|
||||||
|
|
|
||||||
|
|
@ -129,42 +129,51 @@ macro_rules! client_handler_methods {
|
||||||
/// Real clients should override this to provide user interaction.
|
/// Real clients should override this to provide user interaction.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
/// ```rust,ignore
|
/// ```rust,no_run
|
||||||
/// use rmcp::model::ElicitRequestParams;
|
|
||||||
/// use rmcp::{
|
/// use rmcp::{
|
||||||
/// model::ErrorData as McpError,
|
/// ClientHandler,
|
||||||
/// model::*,
|
/// model::{
|
||||||
/// service::{NotificationContext, RequestContext, RoleClient, Service, ServiceRole},
|
/// ElicitRequestParams, ElicitResult, ElicitationAction, ElicitationSchema,
|
||||||
|
/// ErrorData as McpError,
|
||||||
|
/// },
|
||||||
|
/// service::{RequestContext, RoleClient},
|
||||||
/// };
|
/// };
|
||||||
/// use rmcp::ClientHandler;
|
|
||||||
///
|
///
|
||||||
|
/// # struct MyClient;
|
||||||
|
/// #
|
||||||
|
/// # async fn get_user_input(
|
||||||
|
/// # _message: String,
|
||||||
|
/// # _schema: ElicitationSchema,
|
||||||
|
/// # ) -> Result<serde_json::Value, McpError> {
|
||||||
|
/// # std::future::pending().await
|
||||||
|
/// # }
|
||||||
|
/// #
|
||||||
|
/// # async fn open_url_in_browser(_url: String) -> Result<(), McpError> {
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// #
|
||||||
/// impl ClientHandler for MyClient {
|
/// impl ClientHandler for MyClient {
|
||||||
/// async fn create_elicitation(
|
/// async fn create_elicitation(
|
||||||
/// &self,
|
/// &self,
|
||||||
/// request: ElicitRequestParams,
|
/// request: ElicitRequestParams,
|
||||||
/// context: RequestContext<RoleClient>,
|
/// _context: RequestContext<RoleClient>,
|
||||||
/// ) -> Result<ElicitResult, McpError> {
|
/// ) -> Result<ElicitResult, McpError> {
|
||||||
/// match request {
|
/// match request {
|
||||||
/// ElicitRequestParams::FormElicitationParam {meta, message, requested_schema,} => {
|
/// ElicitRequestParams::FormElicitationParams {
|
||||||
/// // Display message to user and collect input according to requested_schema
|
/// message,
|
||||||
/// let user_input = get_user_input(message, requested_schema).await?;
|
/// requested_schema,
|
||||||
/// Ok(ElicitResult {
|
/// ..
|
||||||
/// action: ElicitationAction::Accept,
|
/// } => {
|
||||||
/// content: Some(user_input),
|
/// let input = get_user_input(message, requested_schema).await?;
|
||||||
/// meta: None,
|
/// Ok(ElicitResult::new(ElicitationAction::Accept).with_content(input))
|
||||||
/// })
|
/// }
|
||||||
/// }
|
/// ElicitRequestParams::UrlElicitationParams { url, .. } => {
|
||||||
/// ElicitRequestParams::UrlElicitationParam {meta, message, url, elicitation_id,} => {
|
/// open_url_in_browser(url).await?;
|
||||||
/// // Open URL in browser for user to complete elicitation
|
/// Ok(ElicitResult::new(ElicitationAction::Accept))
|
||||||
/// open_url_in_browser(url).await?;
|
/// }
|
||||||
/// Ok(ElicitResult {
|
/// _ => Ok(ElicitResult::new(ElicitationAction::Decline)),
|
||||||
/// action: ElicitationAction::Accept,
|
|
||||||
/// content: None,
|
|
||||||
/// meta: None,
|
|
||||||
/// })
|
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// }
|
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
fn create_elicitation(
|
fn create_elicitation(
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,7 @@
|
||||||
#![doc = include_str!("../README.md")]
|
#![doc = include_str!("../README.md")]
|
||||||
|
|
||||||
mod error;
|
mod error;
|
||||||
#[allow(deprecated)]
|
pub use error::{ErrorData, RmcpError};
|
||||||
pub use error::{Error, ErrorData, RmcpError};
|
|
||||||
|
|
||||||
/// Basic data types in MCP specification
|
/// Basic data types in MCP specification
|
||||||
pub mod model;
|
pub mod model;
|
||||||
|
|
|
||||||
|
|
@ -1029,10 +1029,6 @@ impl RequestParamsMeta for InitializeRequestParams {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deprecated: Use [`InitializeRequestParams`] instead (SEP-1319 compliance).
|
|
||||||
#[deprecated(since = "0.13.0", note = "Use InitializeRequestParams instead")]
|
|
||||||
pub type InitializeRequestParam = InitializeRequestParams;
|
|
||||||
|
|
||||||
/// The server's response to an initialization request.
|
/// The server's response to an initialization request.
|
||||||
///
|
///
|
||||||
/// Contains the server's protocol version, capabilities, and implementation
|
/// Contains the server's protocol version, capabilities, and implementation
|
||||||
|
|
@ -1437,9 +1433,6 @@ impl RequestParamsMeta for PaginatedRequestParams {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deprecated: Use [`PaginatedRequestParams`] instead (SEP-1319 compliance).
|
|
||||||
#[deprecated(since = "0.13.0", note = "Use PaginatedRequestParams instead")]
|
|
||||||
pub type PaginatedRequestParam = PaginatedRequestParams;
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// PROGRESS AND PAGINATION
|
// PROGRESS AND PAGINATION
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
@ -1680,10 +1673,6 @@ impl RequestParamsMeta for ReadResourceRequestParams {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deprecated: Use [`ReadResourceRequestParams`] instead (SEP-1319 compliance).
|
|
||||||
#[deprecated(since = "0.13.0", note = "Use ReadResourceRequestParams instead")]
|
|
||||||
pub type ReadResourceRequestParam = ReadResourceRequestParams;
|
|
||||||
|
|
||||||
/// Result containing the contents of a read resource
|
/// Result containing the contents of a read resource
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
|
@ -1788,10 +1777,6 @@ impl RequestParamsMeta for SubscribeRequestParams {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deprecated: Use [`SubscribeRequestParams`] instead (SEP-1319 compliance).
|
|
||||||
#[deprecated(since = "0.13.0", note = "Use SubscribeRequestParams instead")]
|
|
||||||
pub type SubscribeRequestParam = SubscribeRequestParams;
|
|
||||||
|
|
||||||
/// Request to subscribe to resource updates
|
/// Request to subscribe to resource updates
|
||||||
#[deprecated(
|
#[deprecated(
|
||||||
note = "resources/subscribe is legacy-only; use subscriptions/listen for protocol version 2026-07-28"
|
note = "resources/subscribe is legacy-only; use subscriptions/listen for protocol version 2026-07-28"
|
||||||
|
|
@ -1831,10 +1816,6 @@ impl RequestParamsMeta for UnsubscribeRequestParams {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deprecated: Use [`UnsubscribeRequestParams`] instead (SEP-1319 compliance).
|
|
||||||
#[deprecated(since = "0.13.0", note = "Use UnsubscribeRequestParams instead")]
|
|
||||||
pub type UnsubscribeRequestParam = UnsubscribeRequestParams;
|
|
||||||
|
|
||||||
/// Request to unsubscribe from resource updates
|
/// Request to unsubscribe from resource updates
|
||||||
#[deprecated(
|
#[deprecated(
|
||||||
note = "resources/unsubscribe is legacy-only; cancel the subscriptions/listen request for protocol version 2026-07-28"
|
note = "resources/unsubscribe is legacy-only; cancel the subscriptions/listen request for protocol version 2026-07-28"
|
||||||
|
|
@ -2333,10 +2314,6 @@ impl RequestParamsMeta for GetPromptRequestParams {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deprecated: Use [`GetPromptRequestParams`] instead (SEP-1319 compliance).
|
|
||||||
#[deprecated(since = "0.13.0", note = "Use GetPromptRequestParams instead")]
|
|
||||||
pub type GetPromptRequestParam = GetPromptRequestParams;
|
|
||||||
|
|
||||||
/// Request to get a specific prompt
|
/// Request to get a specific prompt
|
||||||
pub type GetPromptRequest = Request<GetPromptRequestMethod, GetPromptRequestParams>;
|
pub type GetPromptRequest = Request<GetPromptRequestMethod, GetPromptRequestParams>;
|
||||||
|
|
||||||
|
|
@ -2406,10 +2383,6 @@ impl RequestParamsMeta for SetLevelRequestParams {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deprecated: Use [`SetLevelRequestParams`] instead (SEP-1319 compliance).
|
|
||||||
#[deprecated(since = "0.13.0", note = "Use SetLevelRequestParams instead")]
|
|
||||||
pub type SetLevelRequestParam = SetLevelRequestParams;
|
|
||||||
|
|
||||||
/// Request to set the logging level
|
/// Request to set the logging level
|
||||||
#[deprecated(
|
#[deprecated(
|
||||||
since = "2.0.0",
|
since = "2.0.0",
|
||||||
|
|
@ -2679,9 +2652,6 @@ pub enum SamplingMessageContentBlock {
|
||||||
ToolResult(ToolResultContent),
|
ToolResult(ToolResultContent),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deprecated(since = "2.0.0", note = "Renamed to SamplingMessageContentBlock")]
|
|
||||||
pub type SamplingMessageContent = SamplingMessageContentBlock;
|
|
||||||
|
|
||||||
impl SamplingMessageContentBlock {
|
impl SamplingMessageContentBlock {
|
||||||
/// Create a text content
|
/// Create a text content
|
||||||
pub fn text(text: impl Into<String>) -> Self {
|
pub fn text(text: impl Into<String>) -> Self {
|
||||||
|
|
@ -3008,10 +2978,6 @@ impl CreateMessageRequestParams {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deprecated: Use [`CreateMessageRequestParams`] instead (SEP-1319 compliance).
|
|
||||||
#[deprecated(since = "0.13.0", note = "Use CreateMessageRequestParams instead")]
|
|
||||||
pub type CreateMessageRequestParam = CreateMessageRequestParams;
|
|
||||||
|
|
||||||
/// Preferences for model selection and behavior in sampling requests.
|
/// Preferences for model selection and behavior in sampling requests.
|
||||||
///
|
///
|
||||||
/// This allows servers to express their preferences for which model to use
|
/// This allows servers to express their preferences for which model to use
|
||||||
|
|
@ -3201,10 +3167,6 @@ impl RequestParamsMeta for CompleteRequestParams {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deprecated: Use [`CompleteRequestParams`] instead (SEP-1319 compliance).
|
|
||||||
#[deprecated(since = "0.13.0", note = "Use CompleteRequestParams instead")]
|
|
||||||
pub type CompleteRequestParam = CompleteRequestParams;
|
|
||||||
|
|
||||||
pub type CompleteRequest = Request<CompleteRequestMethod, CompleteRequestParams>;
|
pub type CompleteRequest = Request<CompleteRequestMethod, CompleteRequestParams>;
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
|
||||||
|
|
@ -3391,9 +3353,6 @@ impl ResourceTemplateReference {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deprecated(since = "2.0.0", note = "Renamed to ResourceTemplateReference")]
|
|
||||||
pub type ResourceReference = ResourceTemplateReference;
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
|
||||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
|
@ -3545,21 +3504,20 @@ pub enum ElicitationAction {
|
||||||
Cancel,
|
Cancel,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper enum for deserializing CreateElicitationRequestParam with backward compatibility.
|
/// Wire representation for tagged elicitation parameters and legacy forms without `mode`.
|
||||||
/// When mode is missing, it defaults to FormElicitationParam.
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
|
||||||
#[serde(tag = "mode")]
|
#[serde(tag = "mode")]
|
||||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||||
enum CreateElicitationRequestParamDeserializeHelper {
|
enum ElicitRequestParamsWire {
|
||||||
#[serde(rename = "form", rename_all = "camelCase")]
|
#[serde(rename = "form", rename_all = "camelCase")]
|
||||||
FormElicitationParam {
|
Form {
|
||||||
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
|
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
|
||||||
meta: Option<RequestMetaObject>,
|
meta: Option<RequestMetaObject>,
|
||||||
message: String,
|
message: String,
|
||||||
requested_schema: ElicitationSchema,
|
requested_schema: ElicitationSchema,
|
||||||
},
|
},
|
||||||
#[serde(rename = "url", rename_all = "camelCase")]
|
#[serde(rename = "url", rename_all = "camelCase")]
|
||||||
UrlElicitationParam {
|
Url {
|
||||||
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
|
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
|
||||||
meta: Option<RequestMetaObject>,
|
meta: Option<RequestMetaObject>,
|
||||||
message: String,
|
message: String,
|
||||||
|
|
@ -3567,7 +3525,7 @@ enum CreateElicitationRequestParamDeserializeHelper {
|
||||||
elicitation_id: String,
|
elicitation_id: String,
|
||||||
},
|
},
|
||||||
#[serde(untagged, rename_all = "camelCase")]
|
#[serde(untagged, rename_all = "camelCase")]
|
||||||
FormElicitationParamBackwardsCompat {
|
LegacyForm {
|
||||||
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
|
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
|
||||||
meta: Option<RequestMetaObject>,
|
meta: Option<RequestMetaObject>,
|
||||||
message: String,
|
message: String,
|
||||||
|
|
@ -3575,19 +3533,17 @@ enum CreateElicitationRequestParamDeserializeHelper {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<CreateElicitationRequestParamDeserializeHelper> for ElicitRequestParams {
|
impl TryFrom<ElicitRequestParamsWire> for ElicitRequestParams {
|
||||||
type Error = serde_json::Error;
|
type Error = serde_json::Error;
|
||||||
|
|
||||||
fn try_from(
|
fn try_from(value: ElicitRequestParamsWire) -> Result<Self, Self::Error> {
|
||||||
value: CreateElicitationRequestParamDeserializeHelper,
|
|
||||||
) -> Result<Self, Self::Error> {
|
|
||||||
match value {
|
match value {
|
||||||
CreateElicitationRequestParamDeserializeHelper::FormElicitationParam {
|
ElicitRequestParamsWire::Form {
|
||||||
meta,
|
meta,
|
||||||
message,
|
message,
|
||||||
requested_schema,
|
requested_schema,
|
||||||
}
|
}
|
||||||
| CreateElicitationRequestParamDeserializeHelper::FormElicitationParamBackwardsCompat {
|
| ElicitRequestParamsWire::LegacyForm {
|
||||||
meta,
|
meta,
|
||||||
message,
|
message,
|
||||||
requested_schema,
|
requested_schema,
|
||||||
|
|
@ -3596,7 +3552,7 @@ impl TryFrom<CreateElicitationRequestParamDeserializeHelper> for ElicitRequestPa
|
||||||
message,
|
message,
|
||||||
requested_schema,
|
requested_schema,
|
||||||
}),
|
}),
|
||||||
CreateElicitationRequestParamDeserializeHelper::UrlElicitationParam {
|
ElicitRequestParamsWire::Url {
|
||||||
meta,
|
meta,
|
||||||
message,
|
message,
|
||||||
url,
|
url,
|
||||||
|
|
@ -3642,10 +3598,7 @@ impl TryFrom<CreateElicitationRequestParamDeserializeHelper> for ElicitRequestPa
|
||||||
/// };
|
/// };
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
|
||||||
#[serde(
|
#[serde(tag = "mode", try_from = "ElicitRequestParamsWire")]
|
||||||
tag = "mode",
|
|
||||||
try_from = "CreateElicitationRequestParamDeserializeHelper"
|
|
||||||
)]
|
|
||||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub enum ElicitRequestParams {
|
pub enum ElicitRequestParams {
|
||||||
|
|
@ -3697,13 +3650,6 @@ impl RequestParamsMeta for ElicitRequestParams {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deprecated: Use [`ElicitRequestParams`] instead (SEP-1319 compliance).
|
|
||||||
#[deprecated(since = "0.13.0", note = "Use ElicitRequestParams instead")]
|
|
||||||
pub type CreateElicitationRequestParam = ElicitRequestParams;
|
|
||||||
|
|
||||||
#[deprecated(since = "2.0.0", note = "Renamed to ElicitRequestParams")]
|
|
||||||
pub type CreateElicitationRequestParams = ElicitRequestParams;
|
|
||||||
|
|
||||||
/// The result returned by a client in response to an elicitation request.
|
/// The result returned by a client in response to an elicitation request.
|
||||||
///
|
///
|
||||||
/// Contains the user's decision (accept/decline/cancel) and optionally their input data
|
/// Contains the user's decision (accept/decline/cancel) and optionally their input data
|
||||||
|
|
@ -3750,15 +3696,9 @@ impl ElicitResult {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deprecated(since = "2.0.0", note = "Renamed to ElicitResult")]
|
|
||||||
pub type CreateElicitationResult = ElicitResult;
|
|
||||||
|
|
||||||
/// Request type for creating an elicitation to gather user input
|
/// Request type for creating an elicitation to gather user input
|
||||||
pub type ElicitRequest = Request<ElicitationCreateRequestMethod, ElicitRequestParams>;
|
pub type ElicitRequest = Request<ElicitationCreateRequestMethod, ElicitRequestParams>;
|
||||||
|
|
||||||
#[deprecated(since = "2.0.0", note = "Renamed to ElicitRequest")]
|
|
||||||
pub type CreateElicitationRequest = ElicitRequest;
|
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// TOOL EXECUTION RESULTS
|
// TOOL EXECUTION RESULTS
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
@ -4088,10 +4028,6 @@ impl RequestParamsMeta for CallToolRequestParams {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deprecated: Use [`CallToolRequestParams`] instead (SEP-1319 compliance).
|
|
||||||
#[deprecated(since = "0.13.0", note = "Use CallToolRequestParams instead")]
|
|
||||||
pub type CallToolRequestParam = CallToolRequestParams;
|
|
||||||
|
|
||||||
/// Request to call a specific tool
|
/// Request to call a specific tool
|
||||||
pub type CallToolRequest = Request<CallToolRequestMethod, CallToolRequestParams>;
|
pub type CallToolRequest = Request<CallToolRequestMethod, CallToolRequestParams>;
|
||||||
|
|
||||||
|
|
@ -4625,14 +4561,6 @@ mod tests {
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[allow(deprecated)]
|
|
||||||
fn deprecated_aliases_still_resolve() {
|
|
||||||
// 하위호환: 구 이름이 새 타입으로 여전히 resolve되는지 확인.
|
|
||||||
let _: CreateElicitationResult = ElicitResult::new(ElicitationAction::Accept);
|
|
||||||
let _: ResourceReference = ResourceTemplateReference::new("res://x");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "transport-streamable-http-client")]
|
#[cfg(feature = "transport-streamable-http-client")]
|
||||||
#[test]
|
#[test]
|
||||||
fn transport_closed_marker_accepts_only_the_process_local_token() {
|
fn transport_closed_marker_accepts_only_the_process_local_token() {
|
||||||
|
|
@ -4853,12 +4781,11 @@ mod tests {
|
||||||
serde_json::from_value(request.clone()).expect("invalid request");
|
serde_json::from_value(request.clone()).expect("invalid request");
|
||||||
let (request, id) = request.into_request().expect("should be a request");
|
let (request, id) = request.into_request().expect("should be a request");
|
||||||
assert_eq!(id, RequestId::Number(1));
|
assert_eq!(id, RequestId::Number(1));
|
||||||
#[allow(deprecated)]
|
|
||||||
match request {
|
match request {
|
||||||
ClientRequest::InitializeRequest(Request {
|
ClientRequest::InitializeRequest(Request {
|
||||||
method: _,
|
method: _,
|
||||||
params:
|
params:
|
||||||
InitializeRequestParam {
|
InitializeRequestParams {
|
||||||
meta: _,
|
meta: _,
|
||||||
protocol_version: _,
|
protocol_version: _,
|
||||||
capabilities,
|
capabilities,
|
||||||
|
|
@ -5124,8 +5051,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_elicitation_deserialization_untagged() {
|
fn elicitation_without_mode_deserializes_as_form() {
|
||||||
// Test deserialization without the "type" field (should default to FormElicitationParam)
|
|
||||||
let json_data_without_tag = json!({
|
let json_data_without_tag = json!({
|
||||||
"message": "Please provide more details.",
|
"message": "Please provide more details.",
|
||||||
"requestedSchema": {
|
"requestedSchema": {
|
||||||
|
|
@ -5151,7 +5077,7 @@ mod tests {
|
||||||
assert_eq!(requested_schema.title, Some(Cow::from("User Details")));
|
assert_eq!(requested_schema.title, Some(Cow::from("User Details")));
|
||||||
assert_eq!(requested_schema.type_, ObjectTypeConst);
|
assert_eq!(requested_schema.type_, ObjectTypeConst);
|
||||||
} else {
|
} else {
|
||||||
panic!("Expected FormElicitationParam");
|
panic!("Expected FormElicitationParams");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5189,7 +5115,7 @@ mod tests {
|
||||||
assert_eq!(requested_schema.title, Some(Cow::from("User Details")));
|
assert_eq!(requested_schema.title, Some(Cow::from("User Details")));
|
||||||
assert_eq!(requested_schema.type_, ObjectTypeConst);
|
assert_eq!(requested_schema.type_, ObjectTypeConst);
|
||||||
} else {
|
} else {
|
||||||
panic!("Expected FormElicitationParam");
|
panic!("Expected FormElicitationParams");
|
||||||
}
|
}
|
||||||
|
|
||||||
let json_data_url = json!({
|
let json_data_url = json!({
|
||||||
|
|
@ -5218,7 +5144,7 @@ mod tests {
|
||||||
assert_eq!(url, "https://example.com/form");
|
assert_eq!(url, "https://example.com/form");
|
||||||
assert_eq!(elicitation_id, "elicitation-123");
|
assert_eq!(elicitation_id, "elicitation-123");
|
||||||
} else {
|
} else {
|
||||||
panic!("Expected UrlElicitationParam");
|
panic!("Expected UrlElicitationParams");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,9 +63,6 @@ pub enum PrimitiveSchemaDefinition {
|
||||||
Boolean(BooleanSchema),
|
Boolean(BooleanSchema),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deprecated(since = "2.0.0", note = "Renamed to PrimitiveSchemaDefinition")]
|
|
||||||
pub type PrimitiveSchema = PrimitiveSchemaDefinition;
|
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// STRING SCHEMA
|
// STRING SCHEMA
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
@ -1600,44 +1597,6 @@ impl ElicitationSchemaBuilder {
|
||||||
self.property(name, PrimitiveSchemaDefinition::Enum(enum_schema))
|
self.property(name, PrimitiveSchemaDefinition::Enum(enum_schema))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a required enum property using values. Creates an untitled single-select enum.
|
|
||||||
#[deprecated(
|
|
||||||
since = "0.13.0",
|
|
||||||
note = "Use ElicitationSchemaBuilder::required_enum_schema with EnumSchema::builder instead"
|
|
||||||
)]
|
|
||||||
pub fn required_enum(self, name: impl Into<String>, values: Vec<String>) -> Self {
|
|
||||||
self.required_property(
|
|
||||||
name,
|
|
||||||
PrimitiveSchemaDefinition::Enum(EnumSchema::Legacy(LegacyEnumSchema {
|
|
||||||
type_: StringTypeConst,
|
|
||||||
title: None,
|
|
||||||
description: None,
|
|
||||||
enum_: values,
|
|
||||||
enum_names: None,
|
|
||||||
default: None,
|
|
||||||
})),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Add an optional enum property using values. Creates an untitled single-select enum.
|
|
||||||
#[deprecated(
|
|
||||||
since = "0.13.0",
|
|
||||||
note = "Use ElicitationSchemaBuilder::optional_enum_schema with EnumSchema::builder instead"
|
|
||||||
)]
|
|
||||||
pub fn optional_enum(self, name: impl Into<String>, values: Vec<String>) -> Self {
|
|
||||||
self.property(
|
|
||||||
name,
|
|
||||||
PrimitiveSchemaDefinition::Enum(EnumSchema::Legacy(LegacyEnumSchema {
|
|
||||||
type_: StringTypeConst,
|
|
||||||
title: None,
|
|
||||||
description: None,
|
|
||||||
enum_: values,
|
|
||||||
enum_names: None,
|
|
||||||
default: None,
|
|
||||||
})),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Mark an existing property as required
|
/// Mark an existing property as required
|
||||||
pub fn mark_required(mut self, name: impl Into<String>) -> Self {
|
pub fn mark_required(mut self, name: impl Into<String>) -> Self {
|
||||||
self.required.push(name.into());
|
self.required.push(name.into());
|
||||||
|
|
|
||||||
|
|
@ -243,15 +243,6 @@ variant_extension! {
|
||||||
#[expect(clippy::exhaustive_structs, reason = "intentionally exhaustive")]
|
#[expect(clippy::exhaustive_structs, reason = "intentionally exhaustive")]
|
||||||
pub struct MetaObject(pub JsonObject);
|
pub struct MetaObject(pub JsonObject);
|
||||||
|
|
||||||
/// Deprecated alias for [`MetaObject`].
|
|
||||||
///
|
|
||||||
/// This is a re-export rather than a type alias so the `Meta(...)` tuple
|
|
||||||
/// constructor keeps working. Request and notification metadata now have
|
|
||||||
/// dedicated types; use [`RequestMetaObject`] or [`NotificationMetaObject`]
|
|
||||||
/// where those are expected.
|
|
||||||
#[deprecated(note = "Use MetaObject (or RequestMetaObject / NotificationMetaObject)")]
|
|
||||||
pub use self::MetaObject as Meta;
|
|
||||||
|
|
||||||
impl MetaObject {
|
impl MetaObject {
|
||||||
/// Reserved `_meta` key for the W3C Trace Context `traceparent` value (SEP-414).
|
/// Reserved `_meta` key for the W3C Trace Context `traceparent` value (SEP-414).
|
||||||
const TRACEPARENT_FIELD: &str = "traceparent";
|
const TRACEPARENT_FIELD: &str = "traceparent";
|
||||||
|
|
|
||||||
|
|
@ -86,9 +86,8 @@ struct ProxyNoParam<M> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Combine the message-specific `_meta` map with a legacy [`MetaObject`]
|
/// Combine the message-specific `_meta` map with a legacy [`MetaObject`]
|
||||||
/// extension (inserted through the deprecated `Meta` name), so pre-3.x code
|
/// extension so metadata stored in [`Extensions`] is not lost on the wire.
|
||||||
/// does not silently lose metadata on the wire. On key conflicts the
|
/// On key conflicts the message-specific map wins.
|
||||||
/// message-specific map wins.
|
|
||||||
fn merge_legacy_meta<'a>(
|
fn merge_legacy_meta<'a>(
|
||||||
typed: Option<&'a JsonObject>,
|
typed: Option<&'a JsonObject>,
|
||||||
extensions: &'a Extensions,
|
extensions: &'a Extensions,
|
||||||
|
|
@ -99,7 +98,11 @@ fn merge_legacy_meta<'a>(
|
||||||
(None, Some(legacy)) => Some(Cow::Borrowed(legacy)),
|
(None, Some(legacy)) => Some(Cow::Borrowed(legacy)),
|
||||||
(Some(typed), Some(legacy)) => {
|
(Some(typed), Some(legacy)) => {
|
||||||
let mut merged = legacy.clone();
|
let mut merged = legacy.clone();
|
||||||
merged.extend(typed.clone());
|
merged.extend(
|
||||||
|
typed
|
||||||
|
.iter()
|
||||||
|
.map(|(key, value)| (key.clone(), value.clone())),
|
||||||
|
);
|
||||||
Some(Cow::Owned(merged))
|
Some(Cow::Owned(merged))
|
||||||
}
|
}
|
||||||
(None, None) => None,
|
(None, None) => None,
|
||||||
|
|
@ -778,8 +781,6 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_legacy_meta_extension_still_serializes() {
|
fn test_legacy_meta_extension_still_serializes() {
|
||||||
// Pre-3.x code inserts `MetaObject` into extensions through the
|
|
||||||
// deprecated `Meta` name; its metadata must not be silently dropped.
|
|
||||||
let mut extensions = Extensions::new();
|
let mut extensions = Extensions::new();
|
||||||
let mut legacy = crate::model::MetaObject::new();
|
let mut legacy = crate::model::MetaObject::new();
|
||||||
legacy.insert("traceId".to_string(), json!("legacy"));
|
legacy.insert("traceId".to_string(), json!("legacy"));
|
||||||
|
|
|
||||||
|
|
@ -85,13 +85,6 @@ pub enum ServerInitializeError {
|
||||||
#[error("expect initialized request, but received: {0:?}")]
|
#[error("expect initialized request, but received: {0:?}")]
|
||||||
ExpectedInitializeRequest(Option<ClientJsonRpcMessage>),
|
ExpectedInitializeRequest(Option<ClientJsonRpcMessage>),
|
||||||
|
|
||||||
#[deprecated(
|
|
||||||
since = "1.4.0",
|
|
||||||
note = "The server no longer gates on the initialized notification. This variant is never constructed and will be removed in a future major release."
|
|
||||||
)]
|
|
||||||
#[error("expect initialized notification, but received: {0:?}")]
|
|
||||||
ExpectedInitializedNotification(Option<ClientJsonRpcMessage>),
|
|
||||||
|
|
||||||
#[error("connection closed: {0}")]
|
#[error("connection closed: {0}")]
|
||||||
ConnectionClosed(String),
|
ConnectionClosed(String),
|
||||||
|
|
||||||
|
|
@ -101,13 +94,6 @@ pub enum ServerInitializeError {
|
||||||
#[error("initialize failed: {0}")]
|
#[error("initialize failed: {0}")]
|
||||||
InitializeFailed(ErrorData),
|
InitializeFailed(ErrorData),
|
||||||
|
|
||||||
#[deprecated(
|
|
||||||
since = "1.8.0",
|
|
||||||
note = "Negotiation now falls back to the server-configured version. This variant is never constructed and will be removed in a future major release."
|
|
||||||
)]
|
|
||||||
#[error("unsupported protocol version: {0}")]
|
|
||||||
UnsupportedProtocolVersion(ProtocolVersion),
|
|
||||||
|
|
||||||
#[error("Send message error {error}, when {context}")]
|
#[error("Send message error {error}, when {context}")]
|
||||||
TransportError {
|
TransportError {
|
||||||
error: DynamicTransportError,
|
error: DynamicTransportError,
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,7 @@ use std::process::Stdio;
|
||||||
|
|
||||||
use futures::future::Future;
|
use futures::future::Future;
|
||||||
use process_wrap::tokio::{ChildWrapper, CommandWrap};
|
use process_wrap::tokio::{ChildWrapper, CommandWrap};
|
||||||
use tokio::{
|
use tokio::process::{ChildStderr, ChildStdin, ChildStdout};
|
||||||
io::AsyncRead,
|
|
||||||
process::{ChildStderr, ChildStdin, ChildStdout},
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{RxJsonRpcMessage, Transport, TxJsonRpcMessage, async_rw::AsyncRwTransport};
|
use super::{RxJsonRpcMessage, Transport, TxJsonRpcMessage, async_rw::AsyncRwTransport};
|
||||||
use crate::RoleClient;
|
use crate::RoleClient;
|
||||||
|
|
@ -59,32 +56,6 @@ impl Drop for ChildWithCleanup {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// we hold the child process with stdout, for it's easier to implement AsyncRead
|
|
||||||
pin_project_lite::pin_project! {
|
|
||||||
pub struct TokioChildProcessOut {
|
|
||||||
child: ChildWithCleanup,
|
|
||||||
#[pin]
|
|
||||||
child_stdout: ChildStdout,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TokioChildProcessOut {
|
|
||||||
/// Get the process ID of the child process.
|
|
||||||
pub fn id(&self) -> Option<u32> {
|
|
||||||
self.child.inner.as_ref()?.id()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsyncRead for TokioChildProcessOut {
|
|
||||||
fn poll_read(
|
|
||||||
self: std::pin::Pin<&mut Self>,
|
|
||||||
cx: &mut std::task::Context<'_>,
|
|
||||||
buf: &mut tokio::io::ReadBuf<'_>,
|
|
||||||
) -> std::task::Poll<std::io::Result<()>> {
|
|
||||||
self.project().child_stdout.poll_read(cx, buf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TokioChildProcess {
|
impl TokioChildProcess {
|
||||||
/// Convenience: spawn with default `piped` stdio
|
/// Convenience: spawn with default `piped` stdio
|
||||||
pub fn new(command: impl Into<CommandWrap>) -> std::io::Result<Self> {
|
pub fn new(command: impl Into<CommandWrap>) -> std::io::Result<Self> {
|
||||||
|
|
@ -139,15 +110,6 @@ impl TokioChildProcess {
|
||||||
pub fn into_inner(mut self) -> Option<Box<dyn ChildWrapper>> {
|
pub fn into_inner(mut self) -> Option<Box<dyn ChildWrapper>> {
|
||||||
self.child.inner.take()
|
self.child.inner.take()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Split this helper into a reader (stdout) and writer (stdin).
|
|
||||||
#[deprecated(
|
|
||||||
since = "0.5.0",
|
|
||||||
note = "use the Transport trait implementation instead"
|
|
||||||
)]
|
|
||||||
pub fn split(self) -> (TokioChildProcessOut, ChildStdin) {
|
|
||||||
unimplemented!("This method is deprecated, use the Transport trait implementation instead");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builder for `TokioChildProcess` allowing custom `Stdio` configuration.
|
/// Builder for `TokioChildProcess` allowing custom `Stdio` configuration.
|
||||||
|
|
|
||||||
|
|
@ -1032,9 +1032,6 @@ pub enum LocalSessionWorkerError {
|
||||||
FailToSendInitializeRequest(SessionError),
|
FailToSendInitializeRequest(SessionError),
|
||||||
#[error("fail to handle message: {0}")]
|
#[error("fail to handle message: {0}")]
|
||||||
FailToHandleMessage(SessionError),
|
FailToHandleMessage(SessionError),
|
||||||
#[deprecated(note = "idle timeout now surfaces as WorkerQuitReason::IdleTimeout")]
|
|
||||||
#[error("keep alive timeout after {}ms", _0.as_millis())]
|
|
||||||
KeepAliveTimeout(Duration),
|
|
||||||
#[error("init timeout after {}ms", _0.as_millis())]
|
#[error("init timeout after {}ms", _0.as_millis())]
|
||||||
InitTimeout(Duration),
|
InitTimeout(Duration),
|
||||||
#[error("Transport closed")]
|
#[error("Transport closed")]
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ async fn test_elicitation_request_param_serialization() {
|
||||||
assert_eq!(msg1, msg2);
|
assert_eq!(msg1, msg2);
|
||||||
assert_eq!(schema1, schema2);
|
assert_eq!(schema1, schema2);
|
||||||
}
|
}
|
||||||
_ => panic!("Expected FormElicitationParam variant"),
|
_ => panic!("Expected FormElicitationParams variant"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -179,7 +179,7 @@ async fn test_elicitation_json_rpc_protocol() {
|
||||||
ElicitRequestParams::FormElicitationParams { message, .. } => {
|
ElicitRequestParams::FormElicitationParams { message, .. } => {
|
||||||
assert_eq!(message, "Do you want to continue?");
|
assert_eq!(message, "Do you want to continue?");
|
||||||
}
|
}
|
||||||
_ => panic!("Expected FormElicitationParam variant"),
|
_ => panic!("Expected FormElicitationParams variant"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -496,7 +496,7 @@ async fn test_elicitation_structured_schemas() {
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_ => panic!("Expected FormElicitationParam variant"),
|
_ => panic!("Expected FormElicitationParams variant"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -738,7 +738,7 @@ async fn test_elicitation_multi_select_enum() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => panic!("Expected FormElicitationParam variant"),
|
_ => panic!("Expected FormElicitationParams variant"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -799,7 +799,7 @@ async fn test_elicitation_single_select_enum() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => panic!("Expected FormElicitationParam variant"),
|
_ => panic!("Expected FormElicitationParams variant"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1056,10 +1056,8 @@ async fn test_client_capabilities_with_elicitation() {
|
||||||
assert!(capabilities_without.elicitation.is_none());
|
assert!(capabilities_without.elicitation.is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Test InitializeRequestParam with elicitation capability
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_initialize_request_with_elicitation() {
|
async fn test_initialize_request_with_elicitation() {
|
||||||
// Test InitializeRequestParam with elicitation capability
|
|
||||||
let init_param = InitializeRequestParams::new(
|
let init_param = InitializeRequestParams::new(
|
||||||
ClientCapabilities::builder()
|
ClientCapabilities::builder()
|
||||||
.enable_elicitation_with(
|
.enable_elicitation_with(
|
||||||
|
|
@ -1829,7 +1827,7 @@ async fn test_url_elicitation_request_param_serialization() {
|
||||||
assert_eq!(url, "https://example.com/verify");
|
assert_eq!(url, "https://example.com/verify");
|
||||||
assert_eq!(elicitation_id, "elicit-123");
|
assert_eq!(elicitation_id, "elicit-123");
|
||||||
}
|
}
|
||||||
_ => panic!("Expected UrlElicitationParam variant"),
|
_ => panic!("Expected UrlElicitationParams variant"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1878,7 +1876,7 @@ async fn test_url_elicitation_json_rpc_protocol() {
|
||||||
assert_eq!(url, "https://auth.example.com/authorize/abc123");
|
assert_eq!(url, "https://auth.example.com/authorize/abc123");
|
||||||
assert_eq!(elicitation_id, "auth-request-456");
|
assert_eq!(elicitation_id, "auth-request-456");
|
||||||
}
|
}
|
||||||
_ => panic!("Expected UrlElicitationParam variant"),
|
_ => panic!("Expected UrlElicitationParams variant"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1927,7 +1925,6 @@ async fn test_url_elicitation_capability() {
|
||||||
/// Test backward compatibility: ElicitRequestParams without mode tag
|
/// Test backward compatibility: ElicitRequestParams without mode tag
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_elicitation_backward_compatibility_no_mode() {
|
async fn test_elicitation_backward_compatibility_no_mode() {
|
||||||
// JSON without "mode" field should deserialize as FormElicitationParam
|
|
||||||
let json_without_mode = json!({
|
let json_without_mode = json!({
|
||||||
"message": "Please enter your details",
|
"message": "Please enter your details",
|
||||||
"requestedSchema": {
|
"requestedSchema": {
|
||||||
|
|
@ -1953,7 +1950,7 @@ async fn test_elicitation_backward_compatibility_no_mode() {
|
||||||
assert_eq!(requested_schema.properties.len(), 1);
|
assert_eq!(requested_schema.properties.len(), 1);
|
||||||
assert!(requested_schema.properties.contains_key("name"));
|
assert!(requested_schema.properties.contains_key("name"));
|
||||||
}
|
}
|
||||||
_ => panic!("Expected FormElicitationParam for backward compatibility"),
|
_ => panic!("Expected FormElicitationParams for backward compatibility"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue