From 14f2d93c8b43a99f4c5d9f7e7c86b4d72ef39449 Mon Sep 17 00:00:00 2001 From: Ali Hashemi Date: Thu, 13 Feb 2025 19:37:18 -0400 Subject: [PATCH 1/3] feat: implement builder pattern for JsonrpcErrorError --- src/generated_schema/2024_11_05/mcp_schema.rs | 54 +++++- .../2024_11_05/schema_utils.rs | 173 +++++++++++++++++- src/generated_schema/draft/mcp_schema.rs | 53 +++++- src/generated_schema/draft/schema_utils.rs | 173 +++++++++++++++++- 4 files changed, 427 insertions(+), 26 deletions(-) diff --git a/src/generated_schema/2024_11_05/mcp_schema.rs b/src/generated_schema/2024_11_05/mcp_schema.rs index 26d872d..ed00ff1 100644 --- a/src/generated_schema/2024_11_05/mcp_schema.rs +++ b/src/generated_schema/2024_11_05/mcp_schema.rs @@ -1,12 +1,12 @@ /// ---------------------------------------------------------------------------- -/// This file is auto-generated by mcp-schema-gen v0.1.1. +/// This file is auto-generated by mcp-schema-gen v0.1.2. /// WARNING: /// It is not recommended to modify this file directly. You are free to /// modify or extend the implementations as needed, but please do so at your own risk. /// /// Generated from : -/// Hash : 55c983fd85fafa458d31f729e433c60e95932178 -/// Generated at : 2025-02-11 20:13:30 +/// Hash : 63e1dbb75456b359b9ed8b27d21f4ac68cbb753e +/// Generated at : 2025-02-13 19:33:09 /// ---------------------------------------------------------------------------- /// /// MCP Protocol Version @@ -4542,7 +4542,6 @@ pub struct Result { #[serde(flatten, default, skip_serializing_if = "::std::option::Option::is_none")] pub extra: ::std::option::Option<::serde_json::Map<::std::string::String, ::serde_json::Value>>, } - ///The sender or recipient of messages and data in a conversation. /// ///
JSON schema @@ -5763,6 +5762,7 @@ impl<'de> serde::Deserialize<'de> for ClientRequest { } } impl ClientRequest { + #[deprecated(since = "0.1.4", note = "Use `method()` instead.")] pub fn get_method(&self) -> &str { match self { ClientRequest::InitializeRequest(request) => request.method(), @@ -5780,6 +5780,23 @@ impl ClientRequest { ClientRequest::CompleteRequest(request) => request.method(), } } + pub fn method(&self) -> &str { + match self { + ClientRequest::InitializeRequest(request) => request.method(), + ClientRequest::PingRequest(request) => request.method(), + ClientRequest::ListResourcesRequest(request) => request.method(), + ClientRequest::ListResourceTemplatesRequest(request) => request.method(), + ClientRequest::ReadResourceRequest(request) => request.method(), + ClientRequest::SubscribeRequest(request) => request.method(), + ClientRequest::UnsubscribeRequest(request) => request.method(), + ClientRequest::ListPromptsRequest(request) => request.method(), + ClientRequest::GetPromptRequest(request) => request.method(), + ClientRequest::ListToolsRequest(request) => request.method(), + ClientRequest::CallToolRequest(request) => request.method(), + ClientRequest::SetLevelRequest(request) => request.method(), + ClientRequest::CompleteRequest(request) => request.method(), + } + } } /// Implementing the Deserialize trait /// This allows enum to be deserialized into correct type based on the value of the "method" @@ -5817,6 +5834,7 @@ impl<'de> serde::Deserialize<'de> for ClientNotification { } } impl ClientNotification { + #[deprecated(since = "0.1.4", note = "Use `method()` instead.")] pub fn get_method(&self) -> &str { match self { ClientNotification::CancelledNotification(request) => request.method(), @@ -5825,6 +5843,14 @@ impl ClientNotification { ClientNotification::RootsListChangedNotification(request) => request.method(), } } + pub fn method(&self) -> &str { + match self { + ClientNotification::CancelledNotification(request) => request.method(), + ClientNotification::InitializedNotification(request) => request.method(), + ClientNotification::ProgressNotification(request) => request.method(), + ClientNotification::RootsListChangedNotification(request) => request.method(), + } + } } /// Implementing the Deserialize trait /// This allows enum to be deserialized into correct type based on the value of the "method" @@ -5857,6 +5883,7 @@ impl<'de> serde::Deserialize<'de> for ServerRequest { } } impl ServerRequest { + #[deprecated(since = "0.1.4", note = "Use `method()` instead.")] pub fn get_method(&self) -> &str { match self { ServerRequest::PingRequest(request) => request.method(), @@ -5864,6 +5891,13 @@ impl ServerRequest { ServerRequest::ListRootsRequest(request) => request.method(), } } + pub fn method(&self) -> &str { + match self { + ServerRequest::PingRequest(request) => request.method(), + ServerRequest::CreateMessageRequest(request) => request.method(), + ServerRequest::ListRootsRequest(request) => request.method(), + } + } } /// Implementing the Deserialize trait /// This allows enum to be deserialized into correct type based on the value of the "method" @@ -5917,6 +5951,7 @@ impl<'de> serde::Deserialize<'de> for ServerNotification { } } impl ServerNotification { + #[deprecated(since = "0.1.4", note = "Use `method()` instead.")] pub fn get_method(&self) -> &str { match self { ServerNotification::CancelledNotification(request) => request.method(), @@ -5928,4 +5963,15 @@ impl ServerNotification { ServerNotification::LoggingMessageNotification(request) => request.method(), } } + pub fn method(&self) -> &str { + match self { + ServerNotification::CancelledNotification(request) => request.method(), + ServerNotification::ProgressNotification(request) => request.method(), + ServerNotification::ResourceListChangedNotification(request) => request.method(), + ServerNotification::ResourceUpdatedNotification(request) => request.method(), + ServerNotification::PromptListChangedNotification(request) => request.method(), + ServerNotification::ToolListChangedNotification(request) => request.method(), + ServerNotification::LoggingMessageNotification(request) => request.method(), + } + } } diff --git a/src/generated_schema/2024_11_05/schema_utils.rs b/src/generated_schema/2024_11_05/schema_utils.rs index 13d3ffe..84ff6ce 100644 --- a/src/generated_schema/2024_11_05/schema_utils.rs +++ b/src/generated_schema/2024_11_05/schema_utils.rs @@ -67,7 +67,7 @@ pub struct ClientJsonrpcRequest { impl ClientJsonrpcRequest { pub fn new(id: RequestId, request: RequestFromClient) -> Self { - let method = request.get_method().to_string(); + let method = request.method().to_string(); Self { id, jsonrpc: JSONRPC_VERSION.to_string(), @@ -102,9 +102,17 @@ pub enum RequestFromClient { } impl RequestFromClient { + #[deprecated(since = "0.1.4", note = "Use `method()` instead.")] pub fn get_method(&self) -> &str { match self { - RequestFromClient::ClientRequest(request) => request.get_method(), + RequestFromClient::ClientRequest(request) => request.method(), + RequestFromClient::CustomRequest(request) => request["method"].as_str().unwrap(), + } + } + + fn method(&self) -> &str { + match self { + RequestFromClient::ClientRequest(request) => request.method(), RequestFromClient::CustomRequest(request) => request["method"].as_str().unwrap(), } } @@ -152,7 +160,7 @@ pub struct ClientJsonrpcNotification { impl ClientJsonrpcNotification { pub fn new(notification: NotificationFromClient) -> Self { - let method = notification.get_method().to_string(); + let method = notification.method().to_string(); Self { jsonrpc: JSONRPC_VERSION.to_string(), method, @@ -186,9 +194,17 @@ pub enum NotificationFromClient { } impl NotificationFromClient { + #[deprecated(since = "0.1.4", note = "Use `method()` instead.")] pub fn get_method(&self) -> &str { match self { - NotificationFromClient::ClientNotification(notification) => notification.get_method(), + NotificationFromClient::ClientNotification(notification) => notification.method(), + NotificationFromClient::CustomNotification(notification) => notification["method"].as_str().unwrap(), + } + } + + fn method(&self) -> &str { + match self { + NotificationFromClient::ClientNotification(notification) => notification.method(), NotificationFromClient::CustomNotification(notification) => notification["method"].as_str().unwrap(), } } @@ -354,7 +370,7 @@ pub struct ServerJsonrpcRequest { impl ServerJsonrpcRequest { pub fn new(id: RequestId, request: RequestFromServer) -> Self { - let method = request.get_method().to_string(); + let method = request.method().to_string(); Self { id, jsonrpc: JSONRPC_VERSION.to_string(), @@ -388,9 +404,17 @@ pub enum RequestFromServer { } impl RequestFromServer { + #[deprecated(since = "0.1.4", note = "Use `method()` instead.")] pub fn get_method(&self) -> &str { match self { - RequestFromServer::ServerRequest(request) => request.get_method(), + RequestFromServer::ServerRequest(request) => request.method(), + RequestFromServer::CustomRequest(request) => request["method"].as_str().unwrap(), + } + } + + fn method(&self) -> &str { + match self { + RequestFromServer::ServerRequest(request) => request.method(), RequestFromServer::CustomRequest(request) => request["method"].as_str().unwrap(), } } @@ -438,7 +462,7 @@ pub struct ServerJsonrpcNotification { impl ServerJsonrpcNotification { pub fn new(notification: NotificationFromServer) -> Self { - let method = notification.get_method().to_string(); + let method = notification.method().to_string(); Self { jsonrpc: JSONRPC_VERSION.to_string(), method, @@ -471,9 +495,17 @@ pub enum NotificationFromServer { } impl NotificationFromServer { + #[deprecated(since = "0.1.4", note = "Use `method()` instead.")] pub fn get_method(&self) -> &str { match self { - NotificationFromServer::ServerNotification(notification) => notification.get_method(), + NotificationFromServer::ServerNotification(notification) => notification.method(), + NotificationFromServer::CustomNotification(notification) => notification["method"].as_str().unwrap(), + } + } + + fn method(&self) -> &str { + match self { + NotificationFromServer::ServerNotification(notification) => notification.method(), NotificationFromServer::CustomNotification(notification) => notification["method"].as_str().unwrap(), } } @@ -1132,8 +1164,23 @@ impl From for i64 { code as i64 } } -/// Constructs a new JsonrpcErrorError using the provided arguments. impl JsonrpcErrorError { + /// Constructs a new `JsonrpcErrorError` with the provided arguments. + /// + /// # Arguments + /// * `error_code` - The JSON-RPC error code. + /// * `message` - A descriptive error message. + /// * `data` - Optional additional data. + /// + /// # Example + /// ``` + /// use serde_json::json; + /// use rust_mcp_schema::{JsonrpcErrorError, schema_utils::RpcErrorCodes}; + /// + /// let error = JsonrpcErrorError::new(RpcErrorCodes::INVALID_PARAMS, "Invalid params!".to_string(), Some(json!({"details": "Missing method field"}))); + /// assert_eq!(error.code, -32602); + /// assert_eq!(error.message, "Invalid params!".to_string()); + /// ``` pub fn new( error_code: RpcErrorCodes, message: ::std::string::String, @@ -1145,6 +1192,114 @@ impl JsonrpcErrorError { message, } } + /// Creates a new `JsonrpcErrorError` for "Method not found". + /// + /// # Example + /// ``` + /// use rust_mcp_schema::JsonrpcErrorError; + /// + /// let error = JsonrpcErrorError::method_not_found(); + /// assert_eq!(error.code, -32601); + /// assert_eq!(error.message, "Method not found"); + /// ``` + pub fn method_not_found() -> Self { + Self { + code: RpcErrorCodes::METHOD_NOT_FOUND.into(), + data: None, + message: "Method not found".to_string(), + } + } + /// Creates a new `JsonrpcErrorError` for "Invalid parameters". + /// + /// # Example + /// ``` + /// use rust_mcp_schema::JsonrpcErrorError; + /// + /// let error = JsonrpcErrorError::invalid_params(); + /// assert_eq!(error.code, -32602); + /// ``` + pub fn invalid_params() -> Self { + Self { + code: RpcErrorCodes::INVALID_PARAMS.into(), + data: None, + message: "Invalid params".to_string(), + } + } + /// Creates a new `JsonrpcErrorError` for "Invalid request". + /// + /// # Example + /// ``` + /// use rust_mcp_schema::JsonrpcErrorError; + /// + /// let error = JsonrpcErrorError::invalid_request(); + /// assert_eq!(error.code, -32600); + /// ``` + pub fn invalid_request() -> Self { + Self { + code: RpcErrorCodes::INVALID_REQUEST.into(), + data: None, + message: "Invalid request".to_string(), + } + } + /// Creates a new `JsonrpcErrorError` for "Internal error". + /// + /// # Example + /// ``` + /// use rust_mcp_schema::JsonrpcErrorError; + /// + /// let error = JsonrpcErrorError::internal_error(); + /// assert_eq!(error.code, -32603); + /// ``` + pub fn internal_error() -> Self { + Self { + code: RpcErrorCodes::INTERNAL_ERROR.into(), + data: None, + message: "Internal error".to_string(), + } + } + /// Creates a new `JsonrpcErrorError` for "Parse error". + /// + /// # Example + /// ``` + /// use rust_mcp_schema::JsonrpcErrorError; + /// + /// let error = JsonrpcErrorError::parse_error(); + /// assert_eq!(error.code, -32700); + /// ``` + pub fn parse_error() -> Self { + Self { + code: RpcErrorCodes::PARSE_ERROR.into(), + data: None, + message: "Parse error".to_string(), + } + } + /// Sets a custom error message. + /// + /// # Example + /// ``` + /// use rust_mcp_schema::JsonrpcErrorError; + /// + /// let error = JsonrpcErrorError::invalid_request().with_message("Request format is invalid".to_string()); + /// assert_eq!(error.message, "Request format is invalid".to_string()); + /// ``` + pub fn with_message(mut self, message: String) -> Self { + self.message = message; + self + } + /// Attaches optional data to the error. + /// + /// # Example + /// ``` + /// use serde_json::json; + /// use rust_mcp_schema::JsonrpcErrorError; + /// + /// let error = JsonrpcErrorError::invalid_request().with_data(Some(json!({"reason": "Missing ID"}))); + /// assert!(error.data.is_some()); + /// ``` + pub fn with_data(mut self, data: ::std::option::Option<::serde_json::Value>) -> Self { + self.data = data; + self + } } /// Constructs a new JsonrpcError using the provided arguments. impl JsonrpcError { diff --git a/src/generated_schema/draft/mcp_schema.rs b/src/generated_schema/draft/mcp_schema.rs index 760a0f6..9a5981f 100644 --- a/src/generated_schema/draft/mcp_schema.rs +++ b/src/generated_schema/draft/mcp_schema.rs @@ -1,12 +1,12 @@ /// ---------------------------------------------------------------------------- -/// This file is auto-generated by mcp-schema-gen v0.1.1. +/// This file is auto-generated by mcp-schema-gen v0.1.2. /// WARNING: /// It is not recommended to modify this file directly. You are free to /// modify or extend the implementations as needed, but please do so at your own risk. /// /// Generated from : -/// Hash : 55c983fd85fafa458d31f729e433c60e95932178 -/// Generated at : 2025-02-11 20:13:30 +/// Hash : 63e1dbb75456b359b9ed8b27d21f4ac68cbb753e +/// Generated at : 2025-02-13 19:33:09 /// ---------------------------------------------------------------------------- /// /// MCP Protocol Version @@ -4673,7 +4673,6 @@ pub struct Result { #[serde(flatten, default, skip_serializing_if = "::std::option::Option::is_none")] pub extra: ::std::option::Option<::serde_json::Map<::std::string::String, ::serde_json::Value>>, } - ///The sender or recipient of messages and data in a conversation. /// ///
JSON schema @@ -5892,6 +5891,7 @@ impl<'de> serde::Deserialize<'de> for ClientRequest { } } impl ClientRequest { + #[deprecated(since = "0.1.4", note = "Use `method()` instead.")] pub fn get_method(&self) -> &str { match self { ClientRequest::InitializeRequest(request) => request.method(), @@ -5908,6 +5908,22 @@ impl ClientRequest { ClientRequest::CompleteRequest(request) => request.method(), } } + pub fn method(&self) -> &str { + match self { + ClientRequest::InitializeRequest(request) => request.method(), + ClientRequest::PingRequest(request) => request.method(), + ClientRequest::ListResourcesRequest(request) => request.method(), + ClientRequest::ReadResourceRequest(request) => request.method(), + ClientRequest::SubscribeRequest(request) => request.method(), + ClientRequest::UnsubscribeRequest(request) => request.method(), + ClientRequest::ListPromptsRequest(request) => request.method(), + ClientRequest::GetPromptRequest(request) => request.method(), + ClientRequest::ListToolsRequest(request) => request.method(), + ClientRequest::CallToolRequest(request) => request.method(), + ClientRequest::SetLevelRequest(request) => request.method(), + ClientRequest::CompleteRequest(request) => request.method(), + } + } } /// Implementing the Deserialize trait /// This allows enum to be deserialized into correct type based on the value of the "method" @@ -5945,6 +5961,7 @@ impl<'de> serde::Deserialize<'de> for ClientNotification { } } impl ClientNotification { + #[deprecated(since = "0.1.4", note = "Use `method()` instead.")] pub fn get_method(&self) -> &str { match self { ClientNotification::CancelledNotification(request) => request.method(), @@ -5953,6 +5970,14 @@ impl ClientNotification { ClientNotification::RootsListChangedNotification(request) => request.method(), } } + pub fn method(&self) -> &str { + match self { + ClientNotification::CancelledNotification(request) => request.method(), + ClientNotification::InitializedNotification(request) => request.method(), + ClientNotification::ProgressNotification(request) => request.method(), + ClientNotification::RootsListChangedNotification(request) => request.method(), + } + } } /// Implementing the Deserialize trait /// This allows enum to be deserialized into correct type based on the value of the "method" @@ -5985,6 +6010,7 @@ impl<'de> serde::Deserialize<'de> for ServerRequest { } } impl ServerRequest { + #[deprecated(since = "0.1.4", note = "Use `method()` instead.")] pub fn get_method(&self) -> &str { match self { ServerRequest::PingRequest(request) => request.method(), @@ -5992,6 +6018,13 @@ impl ServerRequest { ServerRequest::ListRootsRequest(request) => request.method(), } } + pub fn method(&self) -> &str { + match self { + ServerRequest::PingRequest(request) => request.method(), + ServerRequest::CreateMessageRequest(request) => request.method(), + ServerRequest::ListRootsRequest(request) => request.method(), + } + } } /// Implementing the Deserialize trait /// This allows enum to be deserialized into correct type based on the value of the "method" @@ -6045,6 +6078,7 @@ impl<'de> serde::Deserialize<'de> for ServerNotification { } } impl ServerNotification { + #[deprecated(since = "0.1.4", note = "Use `method()` instead.")] pub fn get_method(&self) -> &str { match self { ServerNotification::CancelledNotification(request) => request.method(), @@ -6056,4 +6090,15 @@ impl ServerNotification { ServerNotification::LoggingMessageNotification(request) => request.method(), } } + pub fn method(&self) -> &str { + match self { + ServerNotification::CancelledNotification(request) => request.method(), + ServerNotification::ProgressNotification(request) => request.method(), + ServerNotification::ResourceListChangedNotification(request) => request.method(), + ServerNotification::ResourceUpdatedNotification(request) => request.method(), + ServerNotification::PromptListChangedNotification(request) => request.method(), + ServerNotification::ToolListChangedNotification(request) => request.method(), + ServerNotification::LoggingMessageNotification(request) => request.method(), + } + } } diff --git a/src/generated_schema/draft/schema_utils.rs b/src/generated_schema/draft/schema_utils.rs index 09a0986..f995ce0 100644 --- a/src/generated_schema/draft/schema_utils.rs +++ b/src/generated_schema/draft/schema_utils.rs @@ -67,7 +67,7 @@ pub struct ClientJsonrpcRequest { impl ClientJsonrpcRequest { pub fn new(id: RequestId, request: RequestFromClient) -> Self { - let method = request.get_method().to_string(); + let method = request.method().to_string(); Self { id, jsonrpc: JSONRPC_VERSION.to_string(), @@ -102,9 +102,17 @@ pub enum RequestFromClient { } impl RequestFromClient { + #[deprecated(since = "0.1.4", note = "Use `method()` instead.")] pub fn get_method(&self) -> &str { match self { - RequestFromClient::ClientRequest(request) => request.get_method(), + RequestFromClient::ClientRequest(request) => request.method(), + RequestFromClient::CustomRequest(request) => request["method"].as_str().unwrap(), + } + } + + fn method(&self) -> &str { + match self { + RequestFromClient::ClientRequest(request) => request.method(), RequestFromClient::CustomRequest(request) => request["method"].as_str().unwrap(), } } @@ -152,7 +160,7 @@ pub struct ClientJsonrpcNotification { impl ClientJsonrpcNotification { pub fn new(notification: NotificationFromClient) -> Self { - let method = notification.get_method().to_string(); + let method = notification.method().to_string(); Self { jsonrpc: JSONRPC_VERSION.to_string(), method, @@ -186,9 +194,17 @@ pub enum NotificationFromClient { } impl NotificationFromClient { + #[deprecated(since = "0.1.4", note = "Use `method()` instead.")] pub fn get_method(&self) -> &str { match self { - NotificationFromClient::ClientNotification(notification) => notification.get_method(), + NotificationFromClient::ClientNotification(notification) => notification.method(), + NotificationFromClient::CustomNotification(notification) => notification["method"].as_str().unwrap(), + } + } + + fn method(&self) -> &str { + match self { + NotificationFromClient::ClientNotification(notification) => notification.method(), NotificationFromClient::CustomNotification(notification) => notification["method"].as_str().unwrap(), } } @@ -354,7 +370,7 @@ pub struct ServerJsonrpcRequest { impl ServerJsonrpcRequest { pub fn new(id: RequestId, request: RequestFromServer) -> Self { - let method = request.get_method().to_string(); + let method = request.method().to_string(); Self { id, jsonrpc: JSONRPC_VERSION.to_string(), @@ -388,9 +404,17 @@ pub enum RequestFromServer { } impl RequestFromServer { + #[deprecated(since = "0.1.4", note = "Use `method()` instead.")] pub fn get_method(&self) -> &str { match self { - RequestFromServer::ServerRequest(request) => request.get_method(), + RequestFromServer::ServerRequest(request) => request.method(), + RequestFromServer::CustomRequest(request) => request["method"].as_str().unwrap(), + } + } + + fn method(&self) -> &str { + match self { + RequestFromServer::ServerRequest(request) => request.method(), RequestFromServer::CustomRequest(request) => request["method"].as_str().unwrap(), } } @@ -438,7 +462,7 @@ pub struct ServerJsonrpcNotification { impl ServerJsonrpcNotification { pub fn new(notification: NotificationFromServer) -> Self { - let method = notification.get_method().to_string(); + let method = notification.method().to_string(); Self { jsonrpc: JSONRPC_VERSION.to_string(), method, @@ -471,9 +495,17 @@ pub enum NotificationFromServer { } impl NotificationFromServer { + #[deprecated(since = "0.1.4", note = "Use `method()` instead.")] pub fn get_method(&self) -> &str { match self { - NotificationFromServer::ServerNotification(notification) => notification.get_method(), + NotificationFromServer::ServerNotification(notification) => notification.method(), + NotificationFromServer::CustomNotification(notification) => notification["method"].as_str().unwrap(), + } + } + + fn method(&self) -> &str { + match self { + NotificationFromServer::ServerNotification(notification) => notification.method(), NotificationFromServer::CustomNotification(notification) => notification["method"].as_str().unwrap(), } } @@ -1126,8 +1158,23 @@ impl From for i64 { code as i64 } } -/// Constructs a new JsonrpcErrorError using the provided arguments. impl JsonrpcErrorError { + /// Constructs a new `JsonrpcErrorError` with the provided arguments. + /// + /// # Arguments + /// * `error_code` - The JSON-RPC error code. + /// * `message` - A descriptive error message. + /// * `data` - Optional additional data. + /// + /// # Example + /// ``` + /// use serde_json::json; + /// use rust_mcp_schema::{JsonrpcErrorError, schema_utils::RpcErrorCodes}; + /// + /// let error = JsonrpcErrorError::new(RpcErrorCodes::INVALID_PARAMS, "Invalid params!".to_string(), Some(json!({"details": "Missing method field"}))); + /// assert_eq!(error.code, -32602); + /// assert_eq!(error.message, "Invalid params!".to_string()); + /// ``` pub fn new( error_code: RpcErrorCodes, message: ::std::string::String, @@ -1139,6 +1186,114 @@ impl JsonrpcErrorError { message, } } + /// Creates a new `JsonrpcErrorError` for "Method not found". + /// + /// # Example + /// ``` + /// use rust_mcp_schema::JsonrpcErrorError; + /// + /// let error = JsonrpcErrorError::method_not_found(); + /// assert_eq!(error.code, -32601); + /// assert_eq!(error.message, "Method not found"); + /// ``` + pub fn method_not_found() -> Self { + Self { + code: RpcErrorCodes::METHOD_NOT_FOUND.into(), + data: None, + message: "Method not found".to_string(), + } + } + /// Creates a new `JsonrpcErrorError` for "Invalid parameters". + /// + /// # Example + /// ``` + /// use rust_mcp_schema::JsonrpcErrorError; + /// + /// let error = JsonrpcErrorError::invalid_params(); + /// assert_eq!(error.code, -32602); + /// ``` + pub fn invalid_params() -> Self { + Self { + code: RpcErrorCodes::INVALID_PARAMS.into(), + data: None, + message: "Invalid params".to_string(), + } + } + /// Creates a new `JsonrpcErrorError` for "Invalid request". + /// + /// # Example + /// ``` + /// use rust_mcp_schema::JsonrpcErrorError; + /// + /// let error = JsonrpcErrorError::invalid_request(); + /// assert_eq!(error.code, -32600); + /// ``` + pub fn invalid_request() -> Self { + Self { + code: RpcErrorCodes::INVALID_REQUEST.into(), + data: None, + message: "Invalid request".to_string(), + } + } + /// Creates a new `JsonrpcErrorError` for "Internal error". + /// + /// # Example + /// ``` + /// use rust_mcp_schema::JsonrpcErrorError; + /// + /// let error = JsonrpcErrorError::internal_error(); + /// assert_eq!(error.code, -32603); + /// ``` + pub fn internal_error() -> Self { + Self { + code: RpcErrorCodes::INTERNAL_ERROR.into(), + data: None, + message: "Internal error".to_string(), + } + } + /// Creates a new `JsonrpcErrorError` for "Parse error". + /// + /// # Example + /// ``` + /// use rust_mcp_schema::JsonrpcErrorError; + /// + /// let error = JsonrpcErrorError::parse_error(); + /// assert_eq!(error.code, -32700); + /// ``` + pub fn parse_error() -> Self { + Self { + code: RpcErrorCodes::PARSE_ERROR.into(), + data: None, + message: "Parse error".to_string(), + } + } + /// Sets a custom error message. + /// + /// # Example + /// ``` + /// use rust_mcp_schema::JsonrpcErrorError; + /// + /// let error = JsonrpcErrorError::invalid_request().with_message("Request format is invalid".to_string()); + /// assert_eq!(error.message, "Request format is invalid".to_string()); + /// ``` + pub fn with_message(mut self, message: String) -> Self { + self.message = message; + self + } + /// Attaches optional data to the error. + /// + /// # Example + /// ``` + /// use serde_json::json; + /// use rust_mcp_schema::JsonrpcErrorError; + /// + /// let error = JsonrpcErrorError::invalid_request().with_data(Some(json!({"reason": "Missing ID"}))); + /// assert!(error.data.is_some()); + /// ``` + pub fn with_data(mut self, data: ::std::option::Option<::serde_json::Value>) -> Self { + self.data = data; + self + } } /// Constructs a new JsonrpcError using the provided arguments. impl JsonrpcError { From fba0a75e5c07946e7f45fee60db27411a94236ba Mon Sep 17 00:00:00 2001 From: Ali Hashemi Date: Fri, 14 Feb 2025 07:37:43 -0400 Subject: [PATCH 2/3] chore: improve test coverage --- src/generated_schema/2024_11_05/mcp_schema.rs | 4 +- .../2024_11_05/schema_utils.rs | 90 +++++++++++++ src/generated_schema/draft/mcp_schema.rs | 4 +- src/generated_schema/draft/schema_utils.rs | 90 +++++++++++++ tests/test_serialize.rs | 127 ++++++++++++++++++ 5 files changed, 311 insertions(+), 4 deletions(-) diff --git a/src/generated_schema/2024_11_05/mcp_schema.rs b/src/generated_schema/2024_11_05/mcp_schema.rs index ed00ff1..9be2f3b 100644 --- a/src/generated_schema/2024_11_05/mcp_schema.rs +++ b/src/generated_schema/2024_11_05/mcp_schema.rs @@ -1,12 +1,12 @@ /// ---------------------------------------------------------------------------- -/// This file is auto-generated by mcp-schema-gen v0.1.2. +/// This file is auto-generated by mcp-schema-gen v0.1.3. /// WARNING: /// It is not recommended to modify this file directly. You are free to /// modify or extend the implementations as needed, but please do so at your own risk. /// /// Generated from : /// Hash : 63e1dbb75456b359b9ed8b27d21f4ac68cbb753e -/// Generated at : 2025-02-13 19:33:09 +/// Generated at : 2025-02-14 07:23:05 /// ---------------------------------------------------------------------------- /// /// MCP Protocol Version diff --git a/src/generated_schema/2024_11_05/schema_utils.rs b/src/generated_schema/2024_11_05/schema_utils.rs index 84ff6ce..5af9590 100644 --- a/src/generated_schema/2024_11_05/schema_utils.rs +++ b/src/generated_schema/2024_11_05/schema_utils.rs @@ -88,6 +88,35 @@ impl Display for ClientJsonrpcRequest { } } +impl FromStr for ClientJsonrpcRequest { + type Err = serde_json::error::Error; + + /// Parses a JSON-RPC request from a string. + /// + /// This implementation allows `ClientJsonrpcRequest` to be created + /// from a JSON string using the `from_str` method. + /// + /// # Arguments + /// * `s` - A JSON string representing a JSON-RPC request. + /// + /// # Returns + /// * `Ok(ClientJsonrpcRequest)` if parsing is successful. + /// * `Err(serde_json::error::Error)` if the string is not valid JSON. + /// + /// # Example + /// ``` + /// use std::str::FromStr; + /// use your_crate::ClientJsonrpcRequest; + /// + /// let json = r#"{"jsonrpc": "2.0", "method": "initialize", "id": 1}"#; + /// let request = ClientJsonrpcRequest::from_str(json); + /// assert!(request.is_ok()); + /// ``` + fn from_str(s: &str) -> std::result::Result { + serde_json::from_str(s) + } +} + //*************************// //** Request From Client **// //*************************// @@ -180,6 +209,14 @@ impl Display for ClientJsonrpcNotification { } } +impl FromStr for ClientJsonrpcNotification { + type Err = serde_json::error::Error; + + fn from_str(s: &str) -> std::result::Result { + serde_json::from_str(s) + } +} + //*******************************// //** NotificationFromClient **// //*******************************// @@ -259,6 +296,13 @@ impl Display for ClientJsonrpcResponse { } } +impl FromStr for ClientJsonrpcResponse { + type Err = serde_json::error::Error; + + fn from_str(s: &str) -> std::result::Result { + serde_json::from_str(s) + } +} //*******************************// //** ResultFromClient **// //*******************************// @@ -390,6 +434,14 @@ impl Display for ServerJsonrpcRequest { ) } } + +impl FromStr for ServerJsonrpcRequest { + type Err = serde_json::error::Error; + + fn from_str(s: &str) -> std::result::Result { + serde_json::from_str(s) + } +} //*************************// //** Request From Server **// //*************************// @@ -481,6 +533,14 @@ impl Display for ServerJsonrpcNotification { ) } } + +impl FromStr for ServerJsonrpcNotification { + type Err = serde_json::error::Error; + + fn from_str(s: &str) -> std::result::Result { + serde_json::from_str(s) + } +} //*******************************// //** NotificationFromServer **// //*******************************// @@ -560,6 +620,13 @@ impl Display for ServerJsonrpcResponse { } } +impl FromStr for ServerJsonrpcResponse { + type Err = serde_json::error::Error; + + fn from_str(s: &str) -> std::result::Result { + serde_json::from_str(s) + } +} //*******************************// //** ResultFromServer **// //*******************************// @@ -622,6 +689,14 @@ impl Display for JsonrpcError { } } +impl FromStr for JsonrpcError { + type Err = serde_json::error::Error; + + fn from_str(s: &str) -> std::result::Result { + serde_json::from_str(s) + } +} + /// BEGIN AUTO GENERATED impl ::serde::Serialize for ClientJsonrpcRequest { fn serialize(&self, serializer: S) -> std::result::Result @@ -1301,6 +1376,21 @@ impl JsonrpcErrorError { self } } +impl Display for JsonrpcErrorError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}", + serde_json::to_string(self).unwrap_or_else(|err| format!("Serialization error: {}", err)) + ) + } +} +impl FromStr for JsonrpcErrorError { + type Err = serde_json::error::Error; + fn from_str(s: &str) -> std::result::Result { + serde_json::from_str(s) + } +} /// Constructs a new JsonrpcError using the provided arguments. impl JsonrpcError { pub fn create( diff --git a/src/generated_schema/draft/mcp_schema.rs b/src/generated_schema/draft/mcp_schema.rs index 9a5981f..12376d8 100644 --- a/src/generated_schema/draft/mcp_schema.rs +++ b/src/generated_schema/draft/mcp_schema.rs @@ -1,12 +1,12 @@ /// ---------------------------------------------------------------------------- -/// This file is auto-generated by mcp-schema-gen v0.1.2. +/// This file is auto-generated by mcp-schema-gen v0.1.3. /// WARNING: /// It is not recommended to modify this file directly. You are free to /// modify or extend the implementations as needed, but please do so at your own risk. /// /// Generated from : /// Hash : 63e1dbb75456b359b9ed8b27d21f4ac68cbb753e -/// Generated at : 2025-02-13 19:33:09 +/// Generated at : 2025-02-14 07:23:09 /// ---------------------------------------------------------------------------- /// /// MCP Protocol Version diff --git a/src/generated_schema/draft/schema_utils.rs b/src/generated_schema/draft/schema_utils.rs index f995ce0..af3ecac 100644 --- a/src/generated_schema/draft/schema_utils.rs +++ b/src/generated_schema/draft/schema_utils.rs @@ -88,6 +88,35 @@ impl Display for ClientJsonrpcRequest { } } +impl FromStr for ClientJsonrpcRequest { + type Err = serde_json::error::Error; + + /// Parses a JSON-RPC request from a string. + /// + /// This implementation allows `ClientJsonrpcRequest` to be created + /// from a JSON string using the `from_str` method. + /// + /// # Arguments + /// * `s` - A JSON string representing a JSON-RPC request. + /// + /// # Returns + /// * `Ok(ClientJsonrpcRequest)` if parsing is successful. + /// * `Err(serde_json::error::Error)` if the string is not valid JSON. + /// + /// # Example + /// ``` + /// use std::str::FromStr; + /// use your_crate::ClientJsonrpcRequest; + /// + /// let json = r#"{"jsonrpc": "2.0", "method": "initialize", "id": 1}"#; + /// let request = ClientJsonrpcRequest::from_str(json); + /// assert!(request.is_ok()); + /// ``` + fn from_str(s: &str) -> std::result::Result { + serde_json::from_str(s) + } +} + //*************************// //** Request From Client **// //*************************// @@ -180,6 +209,14 @@ impl Display for ClientJsonrpcNotification { } } +impl FromStr for ClientJsonrpcNotification { + type Err = serde_json::error::Error; + + fn from_str(s: &str) -> std::result::Result { + serde_json::from_str(s) + } +} + //*******************************// //** NotificationFromClient **// //*******************************// @@ -259,6 +296,13 @@ impl Display for ClientJsonrpcResponse { } } +impl FromStr for ClientJsonrpcResponse { + type Err = serde_json::error::Error; + + fn from_str(s: &str) -> std::result::Result { + serde_json::from_str(s) + } +} //*******************************// //** ResultFromClient **// //*******************************// @@ -390,6 +434,14 @@ impl Display for ServerJsonrpcRequest { ) } } + +impl FromStr for ServerJsonrpcRequest { + type Err = serde_json::error::Error; + + fn from_str(s: &str) -> std::result::Result { + serde_json::from_str(s) + } +} //*************************// //** Request From Server **// //*************************// @@ -481,6 +533,14 @@ impl Display for ServerJsonrpcNotification { ) } } + +impl FromStr for ServerJsonrpcNotification { + type Err = serde_json::error::Error; + + fn from_str(s: &str) -> std::result::Result { + serde_json::from_str(s) + } +} //*******************************// //** NotificationFromServer **// //*******************************// @@ -560,6 +620,13 @@ impl Display for ServerJsonrpcResponse { } } +impl FromStr for ServerJsonrpcResponse { + type Err = serde_json::error::Error; + + fn from_str(s: &str) -> std::result::Result { + serde_json::from_str(s) + } +} //*******************************// //** ResultFromServer **// //*******************************// @@ -622,6 +689,14 @@ impl Display for JsonrpcError { } } +impl FromStr for JsonrpcError { + type Err = serde_json::error::Error; + + fn from_str(s: &str) -> std::result::Result { + serde_json::from_str(s) + } +} + /// BEGIN AUTO GENERATED impl ::serde::Serialize for ClientJsonrpcRequest { fn serialize(&self, serializer: S) -> std::result::Result @@ -1295,6 +1370,21 @@ impl JsonrpcErrorError { self } } +impl Display for JsonrpcErrorError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}", + serde_json::to_string(self).unwrap_or_else(|err| format!("Serialization error: {}", err)) + ) + } +} +impl FromStr for JsonrpcErrorError { + type Err = serde_json::error::Error; + fn from_str(s: &str) -> std::result::Result { + serde_json::from_str(s) + } +} /// Constructs a new JsonrpcError using the provided arguments. impl JsonrpcError { pub fn create( diff --git a/tests/test_serialize.rs b/tests/test_serialize.rs index 005f511..7184b8e 100644 --- a/tests/test_serialize.rs +++ b/tests/test_serialize.rs @@ -2,6 +2,7 @@ pub mod common; mod test_serialize { + use std::str::FromStr; use std::vec; use rust_mcp_schema::schema_utils::*; @@ -570,4 +571,130 @@ mod test_serialize { assert!(matches!(message, ServerMessage::Error(_))); } + + /* ---------------------- JsonrpcErrorError ---------------------- */ + #[test] + fn test_new() { + let error_object = JsonrpcErrorError::new( + RpcErrorCodes::METHOD_NOT_FOUND, + "Error Message!".to_string(), + Some(json!({"details":"error detail"})), + ); + + let error_object: JsonrpcErrorError = re_serialize(error_object); + + assert_eq!(error_object.code, -32601); + assert_eq!(error_object.message, "Error Message!".to_string()); + matches!(error_object.data, Some(data) if data["details"].as_str().unwrap() == "error detail".to_string()); + } + + #[test] + fn test_method_not_found() { + let error_object = JsonrpcErrorError::method_not_found(); + assert_eq!(error_object.code, -32601); + assert_eq!(error_object.message, "Method not found".to_string()); + assert!(error_object.data.is_none()); + + // builder pattern + let error_object = JsonrpcErrorError::method_not_found() + .with_message("Error Message!".to_string()) + .with_data(Some(json!({"details":"error detail"}))); + + let error_object: JsonrpcErrorError = re_serialize(error_object); + + assert_eq!(error_object.code, -32601); + assert_eq!(error_object.message, "Error Message!".to_string()); + matches!(error_object.data, Some(data) if data["details"].as_str().unwrap() == "error detail".to_string()); + } + + #[test] + fn test_invalid_params() { + let error_object = JsonrpcErrorError::invalid_params(); + assert_eq!(error_object.code, -32602); + assert_eq!(error_object.message, "Invalid params".to_string()); + assert!(error_object.data.is_none()); + + // builder pattern + let error_object = JsonrpcErrorError::invalid_params() + .with_message("Error Message!".to_string()) + .with_data(Some(json!({"details":"error detail"}))); + + let error_object: JsonrpcErrorError = re_serialize(error_object); + + assert_eq!(error_object.code, -32602); + assert_eq!(error_object.message, "Error Message!".to_string()); + matches!(error_object.data, Some(data) if data["details"].as_str().unwrap() == "error detail".to_string()); + } + + #[test] + fn test_invalid_request() { + let error_object = JsonrpcErrorError::invalid_request(); + assert_eq!(error_object.code, -32600); + assert_eq!(error_object.message, "Invalid request".to_string()); + assert!(error_object.data.is_none()); + + // builder pattern + let error_object = JsonrpcErrorError::invalid_request() + .with_message("Error Message!".to_string()) + .with_data(Some(json!({"details":"error detail"}))); + + let error_object: JsonrpcErrorError = re_serialize(error_object); + + assert_eq!(error_object.code, -32600); + assert_eq!(error_object.message, "Error Message!".to_string()); + matches!(error_object.data, Some(data) if data["details"].as_str().unwrap() == "error detail".to_string()); + } + + #[test] + fn test_internal_error() { + let error_object = JsonrpcErrorError::internal_error(); + assert_eq!(error_object.code, -32603); + assert_eq!(error_object.message, "Internal error".to_string()); + assert!(error_object.data.is_none()); + + // builder pattern + let error_object = JsonrpcErrorError::internal_error() + .with_message("Error Message!".to_string()) + .with_data(Some(json!({"details":"error detail"}))); + + let error_object: JsonrpcErrorError = re_serialize(error_object); + + assert_eq!(error_object.code, -32603); + assert_eq!(error_object.message, "Error Message!".to_string()); + matches!(error_object.data, Some(data) if data["details"].as_str().unwrap() == "error detail".to_string()); + } + + #[test] + fn test_parse_error() { + let error_object = JsonrpcErrorError::parse_error(); + assert_eq!(error_object.code, -32700); + assert_eq!(error_object.message, "Parse error".to_string()); + assert!(error_object.data.is_none()); + + // builder pattern + let error_object = JsonrpcErrorError::parse_error() + .with_message("Error Message!".to_string()) + .with_data(Some(json!({"details":"error detail"}))); + + let error_object: JsonrpcErrorError = re_serialize(error_object); + + assert_eq!(error_object.code, -32700); + assert_eq!(error_object.message, "Error Message!".to_string()); + matches!(error_object.data, Some(data) if data["details"].as_str().unwrap() == "error detail".to_string()); + } + + #[test] + fn test_client_jsonrpc_request() { + let message = ClientJsonrpcRequest::new( + RequestId::Integer(15), + RequestFromClient::ClientRequest(ClientRequest::PingRequest(PingRequest::new(None))), + ); + + let message_str = message.to_string(); + + let message: ClientJsonrpcRequest = ClientJsonrpcRequest::from_str(&message_str).unwrap(); + + assert!(matches!(&message.request, RequestFromClient::ClientRequest(client_request) + if matches!(client_request, ClientRequest::PingRequest(_)))); + } } From 2ded65c9c3f3af0e6bbf3fd399d75fbee7b53cbb Mon Sep 17 00:00:00 2001 From: Ali Hashemi Date: Fri, 14 Feb 2025 07:45:48 -0400 Subject: [PATCH 3/3] chore: clippy fix --- src/generated_schema/2024_11_05/mcp_schema.rs | 2 +- src/generated_schema/2024_11_05/schema_utils.rs | 2 +- src/generated_schema/draft/mcp_schema.rs | 2 +- src/generated_schema/draft/schema_utils.rs | 2 +- tests/test_serialize.rs | 12 ++++++------ 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/generated_schema/2024_11_05/mcp_schema.rs b/src/generated_schema/2024_11_05/mcp_schema.rs index 9be2f3b..20074ad 100644 --- a/src/generated_schema/2024_11_05/mcp_schema.rs +++ b/src/generated_schema/2024_11_05/mcp_schema.rs @@ -6,7 +6,7 @@ /// /// Generated from : /// Hash : 63e1dbb75456b359b9ed8b27d21f4ac68cbb753e -/// Generated at : 2025-02-14 07:23:05 +/// Generated at : 2025-02-14 07:43:44 /// ---------------------------------------------------------------------------- /// /// MCP Protocol Version diff --git a/src/generated_schema/2024_11_05/schema_utils.rs b/src/generated_schema/2024_11_05/schema_utils.rs index 5af9590..693043d 100644 --- a/src/generated_schema/2024_11_05/schema_utils.rs +++ b/src/generated_schema/2024_11_05/schema_utils.rs @@ -106,7 +106,7 @@ impl FromStr for ClientJsonrpcRequest { /// # Example /// ``` /// use std::str::FromStr; - /// use your_crate::ClientJsonrpcRequest; + /// use rust_mcp_schema::schema_utils::ClientJsonrpcRequest; /// /// let json = r#"{"jsonrpc": "2.0", "method": "initialize", "id": 1}"#; /// let request = ClientJsonrpcRequest::from_str(json); diff --git a/src/generated_schema/draft/mcp_schema.rs b/src/generated_schema/draft/mcp_schema.rs index 12376d8..0cc4491 100644 --- a/src/generated_schema/draft/mcp_schema.rs +++ b/src/generated_schema/draft/mcp_schema.rs @@ -6,7 +6,7 @@ /// /// Generated from : /// Hash : 63e1dbb75456b359b9ed8b27d21f4ac68cbb753e -/// Generated at : 2025-02-14 07:23:09 +/// Generated at : 2025-02-14 07:43:47 /// ---------------------------------------------------------------------------- /// /// MCP Protocol Version diff --git a/src/generated_schema/draft/schema_utils.rs b/src/generated_schema/draft/schema_utils.rs index af3ecac..a986334 100644 --- a/src/generated_schema/draft/schema_utils.rs +++ b/src/generated_schema/draft/schema_utils.rs @@ -106,7 +106,7 @@ impl FromStr for ClientJsonrpcRequest { /// # Example /// ``` /// use std::str::FromStr; - /// use your_crate::ClientJsonrpcRequest; + /// use rust_mcp_schema::schema_utils::ClientJsonrpcRequest; /// /// let json = r#"{"jsonrpc": "2.0", "method": "initialize", "id": 1}"#; /// let request = ClientJsonrpcRequest::from_str(json); diff --git a/tests/test_serialize.rs b/tests/test_serialize.rs index 7184b8e..c535cd5 100644 --- a/tests/test_serialize.rs +++ b/tests/test_serialize.rs @@ -585,7 +585,7 @@ mod test_serialize { assert_eq!(error_object.code, -32601); assert_eq!(error_object.message, "Error Message!".to_string()); - matches!(error_object.data, Some(data) if data["details"].as_str().unwrap() == "error detail".to_string()); + matches!(error_object.data, Some(data) if data["details"].as_str().unwrap() == "error detail"); } #[test] @@ -604,7 +604,7 @@ mod test_serialize { assert_eq!(error_object.code, -32601); assert_eq!(error_object.message, "Error Message!".to_string()); - matches!(error_object.data, Some(data) if data["details"].as_str().unwrap() == "error detail".to_string()); + matches!(error_object.data, Some(data) if data["details"].as_str().unwrap() == "error detail"); } #[test] @@ -623,7 +623,7 @@ mod test_serialize { assert_eq!(error_object.code, -32602); assert_eq!(error_object.message, "Error Message!".to_string()); - matches!(error_object.data, Some(data) if data["details"].as_str().unwrap() == "error detail".to_string()); + matches!(error_object.data, Some(data) if data["details"].as_str().unwrap() == "error detail"); } #[test] @@ -642,7 +642,7 @@ mod test_serialize { assert_eq!(error_object.code, -32600); assert_eq!(error_object.message, "Error Message!".to_string()); - matches!(error_object.data, Some(data) if data["details"].as_str().unwrap() == "error detail".to_string()); + matches!(error_object.data, Some(data) if data["details"].as_str().unwrap() == "error detail"); } #[test] @@ -661,7 +661,7 @@ mod test_serialize { assert_eq!(error_object.code, -32603); assert_eq!(error_object.message, "Error Message!".to_string()); - matches!(error_object.data, Some(data) if data["details"].as_str().unwrap() == "error detail".to_string()); + matches!(error_object.data, Some(data) if data["details"].as_str().unwrap() == "error detail"); } #[test] @@ -680,7 +680,7 @@ mod test_serialize { assert_eq!(error_object.code, -32700); assert_eq!(error_object.message, "Error Message!".to_string()); - matches!(error_object.data, Some(data) if data["details"].as_str().unwrap() == "error detail".to_string()); + matches!(error_object.data, Some(data) if data["details"].as_str().unwrap() == "error detail"); } #[test]