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