Skip to main content

turul_mcp_builders/
protocol_impls.rs

1//! Framework trait implementations for protocol types
2//!
3//! This module provides framework trait implementations for concrete protocol types
4//! (Resource, Prompt, Tool, Root, etc.) from turul_mcp_protocol, enabling them to be used
5//! with framework features like ResourceDefinition, PromptDefinition, ToolDefinition, etc.
6//!
7//! **CRITICAL**: Every protocol type that has corresponding framework traits MUST have
8//! implementations here. Missing implementations break the trait hierarchy and cause
9//! compilation failures in user code.
10
11use crate::traits::*;
12use turul_mcp_protocol::completion::{
13    CompleteArgument, CompleteRequest, CompletionContext, CompletionReference,
14};
15use turul_mcp_protocol::elicitation::{ElicitCreateRequest, ElicitationSchema};
16use turul_mcp_protocol::logging::{LoggingLevel, LoggingMessageNotification};
17use turul_mcp_protocol::notifications::{
18    CancelledNotification, InitializedNotification, Notification, ProgressNotification,
19    PromptListChangedNotification, ResourceListChangedNotification, ResourceUpdatedNotification,
20    RootsListChangedNotification, ToolListChangedNotification,
21};
22use turul_mcp_protocol::roots::Root;
23use turul_mcp_protocol::sampling::{CreateMessageParams, ModelPreferences, SamplingMessage};
24use turul_mcp_protocol::{Prompt, Resource, Tool, ToolSchema};
25
26// ============================================================================
27// Resource trait implementations
28// ============================================================================
29
30impl HasResourceMetadata for Resource {
31    fn name(&self) -> &str {
32        &self.name
33    }
34
35    fn title(&self) -> Option<&str> {
36        self.title.as_deref()
37    }
38}
39
40impl HasResourceDescription for Resource {
41    fn description(&self) -> Option<&str> {
42        self.description.as_deref()
43    }
44}
45
46impl HasResourceUri for Resource {
47    fn uri(&self) -> &str {
48        &self.uri
49    }
50}
51
52impl HasResourceMimeType for Resource {
53    fn mime_type(&self) -> Option<&str> {
54        self.mime_type.as_deref()
55    }
56}
57
58impl HasResourceSize for Resource {
59    fn size(&self) -> Option<u64> {
60        self.size
61    }
62}
63
64impl HasResourceAnnotations for Resource {
65    fn annotations(&self) -> Option<&turul_mcp_protocol::meta::Annotations> {
66        self.annotations.as_ref()
67    }
68}
69
70impl HasResourceMeta for Resource {
71    fn resource_meta(&self) -> Option<&std::collections::HashMap<String, serde_json::Value>> {
72        self.meta.as_ref()
73    }
74}
75
76impl HasIcons for Resource {
77    fn icons(&self) -> Option<&Vec<turul_mcp_protocol::icons::Icon>> {
78        self.icons.as_ref()
79    }
80}
81
82// ResourceDefinition is automatically implemented via blanket impl
83
84// ============================================================================
85// Prompt trait implementations
86// ============================================================================
87
88impl HasPromptMetadata for Prompt {
89    fn name(&self) -> &str {
90        &self.name
91    }
92
93    fn title(&self) -> Option<&str> {
94        self.title.as_deref()
95    }
96}
97
98impl HasPromptDescription for Prompt {
99    fn description(&self) -> Option<&str> {
100        self.description.as_deref()
101    }
102}
103
104impl HasPromptArguments for Prompt {
105    fn arguments(&self) -> Option<&Vec<turul_mcp_protocol::prompts::PromptArgument>> {
106        self.arguments.as_ref()
107    }
108}
109
110impl HasPromptAnnotations for Prompt {
111    fn annotations(&self) -> Option<&turul_mcp_protocol::prompts::PromptAnnotations> {
112        // Prompt struct doesn't have annotations field in current protocol
113        None
114    }
115}
116
117impl HasPromptMeta for Prompt {
118    fn prompt_meta(&self) -> Option<&std::collections::HashMap<String, serde_json::Value>> {
119        self.meta.as_ref()
120    }
121}
122
123impl HasIcons for Prompt {
124    fn icons(&self) -> Option<&Vec<turul_mcp_protocol::icons::Icon>> {
125        self.icons.as_ref()
126    }
127}
128
129// PromptDefinition is automatically implemented via blanket impl
130
131// ============================================================================
132// Tool trait implementations
133// ============================================================================
134
135impl HasBaseMetadata for Tool {
136    fn name(&self) -> &str {
137        &self.name
138    }
139
140    fn title(&self) -> Option<&str> {
141        self.title.as_deref()
142    }
143}
144
145impl HasDescription for Tool {
146    fn description(&self) -> Option<&str> {
147        self.description.as_deref()
148    }
149}
150
151impl HasInputSchema for Tool {
152    fn input_schema(&self) -> &ToolSchema {
153        &self.input_schema
154    }
155}
156
157impl HasOutputSchema for Tool {
158    fn output_schema(&self) -> Option<&ToolSchema> {
159        self.output_schema.as_ref()
160    }
161}
162
163impl HasAnnotations for Tool {
164    fn annotations(&self) -> Option<&turul_mcp_protocol::tools::ToolAnnotations> {
165        self.annotations.as_ref()
166    }
167}
168
169impl HasToolMeta for Tool {
170    fn tool_meta(&self) -> Option<&std::collections::HashMap<String, serde_json::Value>> {
171        self.meta.as_ref()
172    }
173}
174
175impl HasIcons for Tool {
176    fn icons(&self) -> Option<&Vec<turul_mcp_protocol::icons::Icon>> {
177        self.icons.as_ref()
178    }
179}
180
181// ToolDefinition is automatically implemented via blanket impl
182
183// ============================================================================
184// Root trait implementations
185// ============================================================================
186
187impl HasRootMetadata for Root {
188    fn name(&self) -> Option<&str> {
189        self.name.as_deref()
190    }
191
192    fn uri(&self) -> &str {
193        &self.uri
194    }
195}
196
197impl HasRootPermissions for Root {
198    // Root struct doesn't have permissions field - framework can add later if needed
199}
200
201impl HasRootFiltering for Root {
202    // Root struct doesn't have filtering field - framework can add later if needed
203}
204
205impl HasRootAnnotations for Root {
206    fn annotations(&self) -> Option<&std::collections::HashMap<String, serde_json::Value>> {
207        self.meta.as_ref()
208    }
209}
210
211// RootDefinition is automatically implemented via blanket impl
212
213// ============================================================================
214// Sampling trait implementations
215// ============================================================================
216
217impl HasSamplingConfig for CreateMessageParams {
218    fn max_tokens(&self) -> u32 {
219        self.max_tokens
220    }
221
222    fn temperature(&self) -> Option<f64> {
223        self.temperature
224    }
225
226    fn stop_sequences(&self) -> Option<&Vec<String>> {
227        self.stop_sequences.as_ref()
228    }
229}
230
231impl HasSamplingContext for CreateMessageParams {
232    fn messages(&self) -> &[SamplingMessage] {
233        &self.messages
234    }
235
236    fn system_prompt(&self) -> Option<&str> {
237        self.system_prompt.as_deref()
238    }
239
240    fn include_context(&self) -> Option<&str> {
241        self.include_context.as_deref()
242    }
243}
244
245impl HasModelPreferences for CreateMessageParams {
246    fn model_preferences(&self) -> Option<&ModelPreferences> {
247        self.model_preferences.as_ref()
248    }
249
250    fn metadata(&self) -> Option<&serde_json::Value> {
251        self.metadata.as_ref()
252    }
253}
254
255impl HasSamplingTools for CreateMessageParams {
256    fn tools(&self) -> Option<&Vec<turul_mcp_protocol::Tool>> {
257        self.tools.as_ref()
258    }
259}
260
261// SamplingDefinition is automatically implemented via blanket impl
262
263impl HasSamplingMessageMetadata for SamplingMessage {
264    fn role(&self) -> &turul_mcp_protocol::sampling::Role {
265        &self.role
266    }
267
268    fn content(&self) -> &turul_mcp_protocol::prompts::ContentBlock {
269        &self.content
270    }
271}
272
273// ============================================================================
274// Logging trait implementations
275// ============================================================================
276
277impl HasLoggingMetadata for LoggingMessageNotification {
278    fn method(&self) -> &str {
279        &self.method
280    }
281
282    fn logger_name(&self) -> Option<&str> {
283        self.params.logger.as_deref()
284    }
285}
286
287impl HasLogLevel for LoggingMessageNotification {
288    fn level(&self) -> LoggingLevel {
289        self.params.level
290    }
291}
292
293impl HasLogFormat for LoggingMessageNotification {
294    fn data(&self) -> &serde_json::Value {
295        &self.params.data
296    }
297}
298
299impl HasLogTransport for LoggingMessageNotification {
300    // Use default implementations
301}
302
303// LoggerDefinition is automatically implemented via blanket impl
304
305// ============================================================================
306// Completion trait implementations
307// ============================================================================
308
309impl HasCompletionMetadata for CompleteRequest {
310    fn method(&self) -> &str {
311        &self.method
312    }
313
314    fn reference(&self) -> &CompletionReference {
315        &self.params.reference
316    }
317}
318
319impl HasCompletionContext for CompleteRequest {
320    fn argument(&self) -> &CompleteArgument {
321        &self.params.argument
322    }
323
324    fn context(&self) -> Option<&CompletionContext> {
325        self.params.context.as_ref()
326    }
327}
328
329impl HasCompletionHandling for CompleteRequest {
330    // Use default implementations
331}
332
333// CompletionDefinition is automatically implemented via blanket impl
334
335// ============================================================================
336// Elicitation trait implementations
337// ============================================================================
338
339impl HasElicitationMetadata for ElicitCreateRequest {
340    fn message(&self) -> &str {
341        &self.params.message
342    }
343
344    // title() uses default implementation which returns None
345}
346
347impl HasElicitationSchema for ElicitCreateRequest {
348    fn requested_schema(&self) -> &ElicitationSchema {
349        &self.params.requested_schema
350    }
351}
352
353impl HasElicitationHandling for ElicitCreateRequest {
354    // Use default implementations
355}
356
357// ElicitationDefinition is automatically implemented via blanket impl
358
359// ============================================================================
360// Notification trait implementations
361// ============================================================================
362
363// Base Notification type
364impl HasNotificationMetadata for Notification {
365    fn method(&self) -> &str {
366        &self.method
367    }
368}
369
370impl HasNotificationPayload for Notification {
371    fn payload(&self) -> Option<serde_json::Value> {
372        self.params.as_ref().map(|params| {
373            let mut map = serde_json::Map::new();
374
375            // Add all params.other fields
376            for (key, value) in &params.other {
377                map.insert(key.clone(), value.clone());
378            }
379
380            // Add _meta if present
381            if let Some(meta) = &params.meta
382                && let Ok(meta_value) = serde_json::to_value(meta)
383            {
384                map.insert("_meta".to_string(), meta_value);
385            }
386
387            serde_json::Value::Object(map)
388        })
389    }
390}
391
392impl HasNotificationRules for Notification {}
393
394// ResourceListChangedNotification
395impl HasNotificationMetadata for ResourceListChangedNotification {
396    fn method(&self) -> &str {
397        &self.method
398    }
399}
400
401impl HasNotificationPayload for ResourceListChangedNotification {
402    fn payload(&self) -> Option<serde_json::Value> {
403        // Serialize params if present (includes _meta)
404        self.params
405            .as_ref()
406            .and_then(|p| serde_json::to_value(p).ok())
407    }
408}
409
410impl HasNotificationRules for ResourceListChangedNotification {}
411
412// ToolListChangedNotification
413impl HasNotificationMetadata for ToolListChangedNotification {
414    fn method(&self) -> &str {
415        &self.method
416    }
417}
418
419impl HasNotificationPayload for ToolListChangedNotification {
420    fn payload(&self) -> Option<serde_json::Value> {
421        // Serialize params if present (includes _meta)
422        self.params
423            .as_ref()
424            .and_then(|p| serde_json::to_value(p).ok())
425    }
426}
427
428impl HasNotificationRules for ToolListChangedNotification {}
429
430// PromptListChangedNotification
431impl HasNotificationMetadata for PromptListChangedNotification {
432    fn method(&self) -> &str {
433        &self.method
434    }
435}
436
437impl HasNotificationPayload for PromptListChangedNotification {
438    fn payload(&self) -> Option<serde_json::Value> {
439        // Serialize params if present (includes _meta)
440        self.params
441            .as_ref()
442            .and_then(|p| serde_json::to_value(p).ok())
443    }
444}
445
446impl HasNotificationRules for PromptListChangedNotification {}
447
448// RootsListChangedNotification
449impl HasNotificationMetadata for RootsListChangedNotification {
450    fn method(&self) -> &str {
451        &self.method
452    }
453}
454
455impl HasNotificationPayload for RootsListChangedNotification {
456    fn payload(&self) -> Option<serde_json::Value> {
457        // Serialize params if present (includes _meta)
458        self.params
459            .as_ref()
460            .and_then(|p| serde_json::to_value(p).ok())
461    }
462}
463
464impl HasNotificationRules for RootsListChangedNotification {}
465
466// ProgressNotification
467impl HasNotificationMetadata for ProgressNotification {
468    fn method(&self) -> &str {
469        &self.method
470    }
471}
472
473impl HasNotificationPayload for ProgressNotification {
474    fn payload(&self) -> Option<serde_json::Value> {
475        // Serialize the entire params struct (includes progressToken, progress, total, message, _meta)
476        serde_json::to_value(&self.params).ok()
477    }
478}
479
480impl HasNotificationRules for ProgressNotification {
481    fn priority(&self) -> u32 {
482        2 // Progress notifications have higher priority
483    }
484}
485
486// ResourceUpdatedNotification
487impl HasNotificationMetadata for ResourceUpdatedNotification {
488    fn method(&self) -> &str {
489        &self.method
490    }
491}
492
493impl HasNotificationPayload for ResourceUpdatedNotification {
494    fn payload(&self) -> Option<serde_json::Value> {
495        // Serialize params (includes uri, _meta)
496        serde_json::to_value(&self.params).ok()
497    }
498}
499
500impl HasNotificationRules for ResourceUpdatedNotification {}
501
502// CancelledNotification
503impl HasNotificationMetadata for CancelledNotification {
504    fn method(&self) -> &str {
505        &self.method
506    }
507}
508
509impl HasNotificationPayload for CancelledNotification {
510    fn payload(&self) -> Option<serde_json::Value> {
511        // Serialize params (includes requestId, reason, _meta)
512        serde_json::to_value(&self.params).ok()
513    }
514}
515
516impl HasNotificationRules for CancelledNotification {
517    fn priority(&self) -> u32 {
518        3 // Cancellation has highest priority
519    }
520}
521
522// InitializedNotification
523impl HasNotificationMetadata for InitializedNotification {
524    fn method(&self) -> &str {
525        &self.method
526    }
527}
528
529impl HasNotificationPayload for InitializedNotification {
530    fn payload(&self) -> Option<serde_json::Value> {
531        // Serialize params if present (includes _meta)
532        self.params
533            .as_ref()
534            .and_then(|p| serde_json::to_value(p).ok())
535    }
536}
537
538impl HasNotificationRules for InitializedNotification {
539    fn priority(&self) -> u32 {
540        3 // Initialization has highest priority
541    }
542}
543
544// NotificationDefinition is automatically implemented via blanket impl for all notification types