Skip to content

Commit cc46100

Browse files
authored
feat: introduce FromMessage trait (#30)
1 parent c1999b2 commit cc46100

File tree

4 files changed

+310
-2
lines changed

4 files changed

+310
-2
lines changed

src/generated_schema/2024_11_05/mcp_schema.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
///
77
/// Generated from : <https://github.com/modelcontextprotocol/specification.git>
88
/// Hash : bb1446ff1810a0df57989d78366d626d2c01b9d7
9-
/// Generated at : 2025-02-19 17:00:34
9+
/// Generated at : 2025-02-19 19:59:01
1010
/// ----------------------------------------------------------------------------
1111
///
1212
/// MCP Protocol Version

src/generated_schema/2024_11_05/schema_utils.rs

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,18 @@ pub trait MCPMessage {
7171
fn message_type(&self) -> MessageTypes;
7272
}
7373

74+
/// A trait for converting a message of type `T` into `Self`.
75+
/// This is useful for transforming mcp messages into a Type that could be serialized into a JsonrpcMessage.
76+
///
77+
/// For example, a ServerMessage can be constructed from a rust_mcp_schema::PingRequest by attaching a RequestId.
78+
/// Eventually, the ServerMessage can be serialized into a valid JsonrpcMessage for transmission over the transport.
79+
pub trait FromMessage<T>
80+
where
81+
Self: Sized,
82+
{
83+
fn from_message(message: T, request_id: Option<RequestId>) -> std::result::Result<Self, JsonrpcErrorError>;
84+
}
85+
7486
//*******************************//
7587
//** RequestId Implementations **//
7688
//*******************************//
@@ -911,6 +923,148 @@ impl FromStr for JsonrpcError {
911923
}
912924
}
913925

926+
//**************************//
927+
//** MessageFromServer **//
928+
//**************************//
929+
930+
/// An enum representing various types of messages that can be sent from an MCP Server.
931+
/// It provides a typed structure for the message payload while skipping internal details like
932+
/// `requestId` and protocol version, which are used solely by the transport layer and
933+
/// do not need to be exposed to the user.
934+
#[derive(::serde::Serialize, Clone, Debug)]
935+
#[serde(untagged)]
936+
pub enum MessageFromServer {
937+
RequestFromServer(RequestFromServer),
938+
ResultFromServer(ResultFromServer),
939+
NotificationFromServer(NotificationFromServer),
940+
Error(JsonrpcErrorError),
941+
}
942+
943+
impl MCPMessage for MessageFromServer {
944+
fn is_response(&self) -> bool {
945+
matches!(self, MessageFromServer::ResultFromServer(_))
946+
}
947+
948+
fn is_request(&self) -> bool {
949+
matches!(self, MessageFromServer::RequestFromServer(_))
950+
}
951+
952+
fn is_notification(&self) -> bool {
953+
matches!(self, MessageFromServer::NotificationFromServer(_))
954+
}
955+
956+
fn is_error(&self) -> bool {
957+
matches!(self, MessageFromServer::Error(_))
958+
}
959+
960+
fn message_type(&self) -> MessageTypes {
961+
match self {
962+
MessageFromServer::RequestFromServer(_) => MessageTypes::Request,
963+
MessageFromServer::ResultFromServer(_) => MessageTypes::Response,
964+
MessageFromServer::NotificationFromServer(_) => MessageTypes::Notification,
965+
MessageFromServer::Error(_) => MessageTypes::Error,
966+
}
967+
}
968+
}
969+
970+
impl FromMessage<MessageFromServer> for ServerMessage {
971+
fn from_message(
972+
message: MessageFromServer,
973+
request_id: Option<RequestId>,
974+
) -> std::result::Result<Self, JsonrpcErrorError> {
975+
match message {
976+
MessageFromServer::RequestFromServer(request_from_server) => {
977+
let request_id = request_id
978+
.ok_or_else(|| JsonrpcErrorError::internal_error().with_message("request_id is None!".to_string()))?;
979+
Ok(ServerMessage::Request(ServerJsonrpcRequest::new(
980+
request_id,
981+
request_from_server,
982+
)))
983+
}
984+
MessageFromServer::ResultFromServer(result_from_server) => {
985+
let request_id = request_id
986+
.ok_or_else(|| JsonrpcErrorError::internal_error().with_message("request_id is None!".to_string()))?;
987+
Ok(ServerMessage::Response(ServerJsonrpcResponse::new(
988+
request_id,
989+
result_from_server,
990+
)))
991+
}
992+
MessageFromServer::NotificationFromServer(notification_from_server) => {
993+
if request_id.is_some() {
994+
return Err(JsonrpcErrorError::internal_error()
995+
.with_message("request_id expected to be None for Notifications!".to_string()));
996+
}
997+
Ok(ServerMessage::Notification(ServerJsonrpcNotification::new(
998+
notification_from_server,
999+
)))
1000+
}
1001+
MessageFromServer::Error(jsonrpc_error_error) => {
1002+
let request_id = request_id
1003+
.ok_or_else(|| JsonrpcErrorError::internal_error().with_message("request_id is None!".to_string()))?;
1004+
Ok(ServerMessage::Error(JsonrpcError::new(jsonrpc_error_error, request_id)))
1005+
}
1006+
}
1007+
}
1008+
}
1009+
1010+
//**************************//
1011+
//** MessageFromClient **//
1012+
//**************************//
1013+
1014+
/// An enum representing various types of messages that can be sent from an MCP Client.
1015+
/// It provides a typed structure for the message payload while skipping internal details like
1016+
/// `requestId` and protocol version, which are used solely by the transport layer and
1017+
/// do not need to be exposed to the user.
1018+
#[derive(::serde::Serialize, Clone, Debug)]
1019+
#[serde(untagged)]
1020+
pub enum MessageFromClient {
1021+
RequestFromClient(RequestFromClient),
1022+
ResultFromClient(ResultFromClient),
1023+
NotificationFromClient(NotificationFromClient),
1024+
Error(JsonrpcErrorError),
1025+
}
1026+
1027+
impl FromMessage<MessageFromClient> for ClientMessage {
1028+
fn from_message(
1029+
message: MessageFromClient,
1030+
request_id: Option<RequestId>,
1031+
) -> std::result::Result<Self, JsonrpcErrorError> {
1032+
match message {
1033+
MessageFromClient::RequestFromClient(request_from_client) => {
1034+
let request_id = request_id
1035+
.ok_or_else(|| JsonrpcErrorError::internal_error().with_message("request_id is None!".to_string()))?;
1036+
Ok(ClientMessage::Request(ClientJsonrpcRequest::new(
1037+
request_id,
1038+
request_from_client,
1039+
)))
1040+
}
1041+
MessageFromClient::ResultFromClient(result_from_client) => {
1042+
let request_id = request_id
1043+
.ok_or_else(|| JsonrpcErrorError::internal_error().with_message("request_id is None!".to_string()))?;
1044+
Ok(ClientMessage::Response(ClientJsonrpcResponse::new(
1045+
request_id,
1046+
result_from_client,
1047+
)))
1048+
}
1049+
MessageFromClient::NotificationFromClient(notification_from_client) => {
1050+
if request_id.is_some() {
1051+
return Err(JsonrpcErrorError::internal_error()
1052+
.with_message("request_id expected to be None for Notifications!".to_string()));
1053+
}
1054+
1055+
Ok(ClientMessage::Notification(ClientJsonrpcNotification::new(
1056+
notification_from_client,
1057+
)))
1058+
}
1059+
MessageFromClient::Error(jsonrpc_error_error) => {
1060+
let request_id = request_id
1061+
.ok_or_else(|| JsonrpcErrorError::internal_error().with_message("request_id is None!".to_string()))?;
1062+
Ok(ClientMessage::Error(JsonrpcError::new(jsonrpc_error_error, request_id)))
1063+
}
1064+
}
1065+
}
1066+
}
1067+
9141068
/// BEGIN AUTO GENERATED
9151069
impl ::serde::Serialize for ClientJsonrpcRequest {
9161070
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>

src/generated_schema/draft/mcp_schema.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
///
77
/// Generated from : <https://github.com/modelcontextprotocol/specification.git>
88
/// Hash : bb1446ff1810a0df57989d78366d626d2c01b9d7
9-
/// Generated at : 2025-02-19 17:00:35
9+
/// Generated at : 2025-02-19 19:59:01
1010
/// ----------------------------------------------------------------------------
1111
///
1212
/// MCP Protocol Version

src/generated_schema/draft/schema_utils.rs

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,18 @@ pub trait MCPMessage {
7171
fn message_type(&self) -> MessageTypes;
7272
}
7373

74+
/// A trait for converting a message of type `T` into `Self`.
75+
/// This is useful for transforming mcp messages into a Type that could be serialized into a JsonrpcMessage.
76+
///
77+
/// For example, a ServerMessage can be constructed from a rust_mcp_schema::PingRequest by attaching a RequestId.
78+
/// Eventually, the ServerMessage can be serialized into a valid JsonrpcMessage for transmission over the transport.
79+
pub trait FromMessage<T>
80+
where
81+
Self: Sized,
82+
{
83+
fn from_message(message: T, request_id: Option<RequestId>) -> std::result::Result<Self, JsonrpcErrorError>;
84+
}
85+
7486
//*******************************//
7587
//** RequestId Implementations **//
7688
//*******************************//
@@ -911,6 +923,148 @@ impl FromStr for JsonrpcError {
911923
}
912924
}
913925

926+
//**************************//
927+
//** MessageFromServer **//
928+
//**************************//
929+
930+
/// An enum representing various types of messages that can be sent from an MCP Server.
931+
/// It provides a typed structure for the message payload while skipping internal details like
932+
/// `requestId` and protocol version, which are used solely by the transport layer and
933+
/// do not need to be exposed to the user.
934+
#[derive(::serde::Serialize, Clone, Debug)]
935+
#[serde(untagged)]
936+
pub enum MessageFromServer {
937+
RequestFromServer(RequestFromServer),
938+
ResultFromServer(ResultFromServer),
939+
NotificationFromServer(NotificationFromServer),
940+
Error(JsonrpcErrorError),
941+
}
942+
943+
impl MCPMessage for MessageFromServer {
944+
fn is_response(&self) -> bool {
945+
matches!(self, MessageFromServer::ResultFromServer(_))
946+
}
947+
948+
fn is_request(&self) -> bool {
949+
matches!(self, MessageFromServer::RequestFromServer(_))
950+
}
951+
952+
fn is_notification(&self) -> bool {
953+
matches!(self, MessageFromServer::NotificationFromServer(_))
954+
}
955+
956+
fn is_error(&self) -> bool {
957+
matches!(self, MessageFromServer::Error(_))
958+
}
959+
960+
fn message_type(&self) -> MessageTypes {
961+
match self {
962+
MessageFromServer::RequestFromServer(_) => MessageTypes::Request,
963+
MessageFromServer::ResultFromServer(_) => MessageTypes::Response,
964+
MessageFromServer::NotificationFromServer(_) => MessageTypes::Notification,
965+
MessageFromServer::Error(_) => MessageTypes::Error,
966+
}
967+
}
968+
}
969+
970+
impl FromMessage<MessageFromServer> for ServerMessage {
971+
fn from_message(
972+
message: MessageFromServer,
973+
request_id: Option<RequestId>,
974+
) -> std::result::Result<Self, JsonrpcErrorError> {
975+
match message {
976+
MessageFromServer::RequestFromServer(request_from_server) => {
977+
let request_id = request_id
978+
.ok_or_else(|| JsonrpcErrorError::internal_error().with_message("request_id is None!".to_string()))?;
979+
Ok(ServerMessage::Request(ServerJsonrpcRequest::new(
980+
request_id,
981+
request_from_server,
982+
)))
983+
}
984+
MessageFromServer::ResultFromServer(result_from_server) => {
985+
let request_id = request_id
986+
.ok_or_else(|| JsonrpcErrorError::internal_error().with_message("request_id is None!".to_string()))?;
987+
Ok(ServerMessage::Response(ServerJsonrpcResponse::new(
988+
request_id,
989+
result_from_server,
990+
)))
991+
}
992+
MessageFromServer::NotificationFromServer(notification_from_server) => {
993+
if request_id.is_some() {
994+
return Err(JsonrpcErrorError::internal_error()
995+
.with_message("request_id expected to be None for Notifications!".to_string()));
996+
}
997+
Ok(ServerMessage::Notification(ServerJsonrpcNotification::new(
998+
notification_from_server,
999+
)))
1000+
}
1001+
MessageFromServer::Error(jsonrpc_error_error) => {
1002+
let request_id = request_id
1003+
.ok_or_else(|| JsonrpcErrorError::internal_error().with_message("request_id is None!".to_string()))?;
1004+
Ok(ServerMessage::Error(JsonrpcError::new(jsonrpc_error_error, request_id)))
1005+
}
1006+
}
1007+
}
1008+
}
1009+
1010+
//**************************//
1011+
//** MessageFromClient **//
1012+
//**************************//
1013+
1014+
/// An enum representing various types of messages that can be sent from an MCP Client.
1015+
/// It provides a typed structure for the message payload while skipping internal details like
1016+
/// `requestId` and protocol version, which are used solely by the transport layer and
1017+
/// do not need to be exposed to the user.
1018+
#[derive(::serde::Serialize, Clone, Debug)]
1019+
#[serde(untagged)]
1020+
pub enum MessageFromClient {
1021+
RequestFromClient(RequestFromClient),
1022+
ResultFromClient(ResultFromClient),
1023+
NotificationFromClient(NotificationFromClient),
1024+
Error(JsonrpcErrorError),
1025+
}
1026+
1027+
impl FromMessage<MessageFromClient> for ClientMessage {
1028+
fn from_message(
1029+
message: MessageFromClient,
1030+
request_id: Option<RequestId>,
1031+
) -> std::result::Result<Self, JsonrpcErrorError> {
1032+
match message {
1033+
MessageFromClient::RequestFromClient(request_from_client) => {
1034+
let request_id = request_id
1035+
.ok_or_else(|| JsonrpcErrorError::internal_error().with_message("request_id is None!".to_string()))?;
1036+
Ok(ClientMessage::Request(ClientJsonrpcRequest::new(
1037+
request_id,
1038+
request_from_client,
1039+
)))
1040+
}
1041+
MessageFromClient::ResultFromClient(result_from_client) => {
1042+
let request_id = request_id
1043+
.ok_or_else(|| JsonrpcErrorError::internal_error().with_message("request_id is None!".to_string()))?;
1044+
Ok(ClientMessage::Response(ClientJsonrpcResponse::new(
1045+
request_id,
1046+
result_from_client,
1047+
)))
1048+
}
1049+
MessageFromClient::NotificationFromClient(notification_from_client) => {
1050+
if request_id.is_some() {
1051+
return Err(JsonrpcErrorError::internal_error()
1052+
.with_message("request_id expected to be None for Notifications!".to_string()));
1053+
}
1054+
1055+
Ok(ClientMessage::Notification(ClientJsonrpcNotification::new(
1056+
notification_from_client,
1057+
)))
1058+
}
1059+
MessageFromClient::Error(jsonrpc_error_error) => {
1060+
let request_id = request_id
1061+
.ok_or_else(|| JsonrpcErrorError::internal_error().with_message("request_id is None!".to_string()))?;
1062+
Ok(ClientMessage::Error(JsonrpcError::new(jsonrpc_error_error, request_id)))
1063+
}
1064+
}
1065+
}
1066+
}
1067+
9141068
/// BEGIN AUTO GENERATED
9151069
impl ::serde::Serialize for ClientJsonrpcRequest {
9161070
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>

0 commit comments

Comments
 (0)