agentic/mcp/messages/
mcp_notification.rs1use crate::mcp::{Error, Result};
2use rpc_router::RpcNotification;
3use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error as DeError};
4use serde_json::Value;
5
6#[derive(Debug, Clone)]
7pub struct McpNotification<P = Value> {
8 pub method: String,
10
11 pub params: Option<P>,
13}
14
15impl<P: Serialize> McpNotification<P> {
16 pub fn stringify(&self) -> Result<String> {
17 serde_json::to_string(&self).map_err(Error::custom_from_err)
18 }
19 pub fn stringify_pretty(&self) -> Result<String> {
20 serde_json::to_string_pretty(&self).map_err(Error::custom_from_err)
21 }
22}
23
24pub trait IntoMcpNotification: Sized {
27 const METHOD: &'static str;
28
29 fn into_mcp_notification(self) -> McpNotification<Self> {
30 self.into()
31 }
32}
33
34impl<T: IntoMcpNotification> From<T> for McpNotification<T> {
35 fn from(params: T) -> Self {
36 McpNotification {
37 method: T::METHOD.to_string(),
38 params: Some(params),
39 }
40 }
41}
42
43impl<P> Serialize for McpNotification<P>
48where
49 P: Serialize,
50{
51 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
52 where
53 S: Serializer,
54 {
55 let params_value = match &self.params {
57 Some(p) => Some(serde_json::to_value(p).map_err(serde::ser::Error::custom)?),
58 None => None,
59 };
60
61 let rpc_request = RpcNotification {
63 method: self.method.clone(),
64 params: params_value,
65 };
66
67 rpc_request.serialize(serializer)
69 }
70}
71
72impl<'de, P> Deserialize<'de> for McpNotification<P>
73where
74 P: Deserialize<'de>,
75{
76 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
77 where
78 D: Deserializer<'de>,
79 {
80 let rpc_request = RpcNotification::deserialize(deserializer)?;
82
83 let params = match rpc_request.params {
85 Some(value) => {
86 let p = P::deserialize(value).map_err(DeError::custom)?;
87 Some(p)
88 }
89 None => None,
90 };
91
92 Ok(McpNotification {
94 method: rpc_request.method,
95 params,
96 })
97 }
98}
99
100