turul_mcp_builders/traits/notification_traits.rs
1//! Framework traits for MCP notification construction
2//!
3//! **IMPORTANT**: These are framework features, NOT part of the MCP specification.
4
5use turul_mcp_protocol::notifications::{Notification, NotificationParams};
6use serde_json::Value;
7use std::collections::HashMap;
8
9pub trait HasNotificationMetadata {
10 /// The notification method name
11 fn method(&self) -> &str;
12
13 /// Optional notification type or category
14 fn notification_type(&self) -> Option<&str> {
15 None
16 }
17
18 /// Whether this notification requires acknowledgment
19 fn requires_ack(&self) -> bool {
20 false
21 }
22}
23
24/// Trait for notification payload and data structure
25pub trait HasNotificationPayload {
26 /// Get the notification payload data (owned Value for computed serialization)
27 fn payload(&self) -> Option<Value> {
28 None
29 }
30
31 /// Serialize notification to JSON
32 fn serialize_payload(&self) -> Result<String, String> {
33 match self.payload() {
34 Some(data) => {
35 serde_json::to_string(&data).map_err(|e| format!("Serialization error: {}", e))
36 }
37 None => Ok("{}".to_string()),
38 }
39 }
40}
41
42/// Trait for notification delivery rules and filtering
43pub trait HasNotificationRules {
44 /// Optional delivery priority (higher = more important)
45 fn priority(&self) -> u32 {
46 0
47 }
48
49 /// Whether this notification can be batched with others
50 fn can_batch(&self) -> bool {
51 true
52 }
53
54 /// Maximum retry attempts for delivery
55 fn max_retries(&self) -> u32 {
56 3
57 }
58
59 /// Check if notification should be delivered
60 fn should_deliver(&self) -> bool {
61 true
62 }
63}
64
65/// **Complete MCP Notification Creation** - Build real-time event broadcasting systems.
66///
67/// This trait represents a **complete, working MCP notification** that can broadcast
68/// real-time events to connected clients with structured payloads and routing rules.
69/// When you implement the required metadata traits, you automatically get
70/// `NotificationDefinition` for free via blanket implementation.
71///
72/// # What You're Building
73///
74/// A notification is a real-time event system that:
75/// - Broadcasts events to connected clients instantly
76/// - Carries structured JSON payloads with event data
77/// - Supports routing rules for targeted delivery
78/// - Provides reliable event ordering and delivery
79///
80/// # How to Create a Notification
81///
82/// Implement these three traits on your struct:
83///
84/// ```rust
85/// # use turul_mcp_protocol::notifications::*;
86/// # use turul_mcp_builders::prelude::*;
87/// # use serde_json::{Value, json};
88///
89/// // This struct will automatically implement NotificationDefinition!
90/// struct FileChangeNotification {
91/// file_path: String,
92/// change_type: String,
93/// payload_data: Value,
94/// }
95///
96/// impl FileChangeNotification {
97/// fn new(file_path: String, change_type: String) -> Self {
98/// let payload_data = json!({
99/// "path": file_path,
100/// "type": change_type,
101/// "timestamp": "2024-01-01T00:00:00Z"
102/// });
103/// Self { file_path, change_type, payload_data }
104/// }
105/// }
106///
107/// impl HasNotificationMetadata for FileChangeNotification {
108/// fn method(&self) -> &str {
109/// "file/changed"
110/// }
111/// }
112///
113/// impl HasNotificationPayload for FileChangeNotification {
114/// fn payload(&self) -> Option<Value> {
115/// Some(self.payload_data.clone())
116/// }
117/// }
118///
119/// impl HasNotificationRules for FileChangeNotification {
120/// fn priority(&self) -> u32 {
121/// 1
122/// }
123/// }
124///
125/// // Now you can use it with the server:
126/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
127/// let notification = FileChangeNotification::new(
128/// "/workspace/src/main.rs".to_string(),
129/// "modified".to_string(),
130/// );
131///
132/// // The notification automatically implements NotificationDefinition
133/// let base_notification = notification.to_notification();
134/// # Ok(())
135/// # }
136/// ```
137///
138/// # Key Benefits
139///
140/// - **Real-Time**: Instant event delivery to connected clients
141/// - **Structured Data**: JSON payloads for rich event information
142/// - **Targeted Delivery**: Client-specific routing rules
143/// - **MCP Compliant**: Fully compatible with MCP 2025-06-18 specification
144///
145/// # Common Use Cases
146///
147/// - File system watch notifications
148/// - Database change events
149/// - User activity broadcasts
150/// - System status updates
151/// - Real-time collaboration events
152pub trait NotificationDefinition:
153 HasNotificationMetadata + HasNotificationPayload + HasNotificationRules
154{
155 /// Convert this notification definition to a base Notification
156 fn to_notification(&self) -> Notification {
157 let mut notification = Notification::new(self.method());
158 if let Some(payload) = self.payload() {
159 let mut params = NotificationParams::new();
160 // Add payload data to params.other
161 if let Ok(obj) = serde_json::from_value::<HashMap<String, Value>>(payload.clone()) {
162 params.other = obj;
163 }
164 notification = notification.with_params(params);
165 }
166 notification
167 }
168
169 /// Validate this notification
170 fn validate(&self) -> Result<(), String> {
171 if self.method().is_empty() {
172 return Err("Notification method cannot be empty".to_string());
173 }
174 if !self.method().starts_with("notifications/") {
175 return Err("Notification method must start with 'notifications/'".to_string());
176 }
177 Ok(())
178 }
179}
180
181// Blanket implementation: any type implementing the fine-grained traits automatically gets NotificationDefinition
182impl<T> NotificationDefinition for T where
183 T: HasNotificationMetadata + HasNotificationPayload + HasNotificationRules
184{
185}