Skip to main content

turul_mcp_builders/traits/
tool_traits.rs

1//! Framework traits for MCP tool construction
2//!
3//! **IMPORTANT**: These are framework features, NOT part of the MCP specification.
4//! The MCP specification defines concrete types only.
5
6use serde_json::Value;
7use std::collections::HashMap;
8
9// Import protocol types (spec-defined)
10use turul_mcp_protocol::tools::ToolAnnotations;
11use turul_mcp_protocol::{Tool, ToolSchema};
12
13/// Base metadata trait - matches TypeScript BaseMetadata interface
14pub trait HasBaseMetadata {
15    /// Programmatic identifier (fallback display name)
16    fn name(&self) -> &str;
17
18    /// Human-readable display name (UI contexts)
19    fn title(&self) -> Option<&str> {
20        None
21    }
22}
23
24/// Tool description trait
25pub trait HasDescription {
26    fn description(&self) -> Option<&str> {
27        None
28    }
29}
30
31/// Input schema trait
32pub trait HasInputSchema {
33    fn input_schema(&self) -> &ToolSchema;
34}
35
36/// Output schema trait
37pub trait HasOutputSchema {
38    fn output_schema(&self) -> Option<&ToolSchema> {
39        None
40    }
41}
42
43/// Annotations trait
44pub trait HasAnnotations {
45    fn annotations(&self) -> Option<&ToolAnnotations> {
46        None
47    }
48}
49
50/// Tool-specific meta trait (separate from RPC _meta)
51pub trait HasToolMeta {
52    fn tool_meta(&self) -> Option<&HashMap<String, Value>> {
53        None
54    }
55}
56
57/// Complete tool definition - composed from fine-grained traits
58///
59/// This trait represents a complete MCP tool that can be registered with a server
60/// and invoked by clients. When you implement the required metadata traits, you automatically
61/// get `ToolDefinition` for free via blanket implementation.
62pub trait ToolDefinition:
63    HasBaseMetadata +           // name, title
64    HasDescription +            // description
65    HasInputSchema +            // inputSchema
66    HasOutputSchema +           // outputSchema
67    HasAnnotations +            // annotations
68    HasToolMeta +               // _meta (tool-specific)
69    super::icon_traits::HasIcons + // icons (MCP 2025-11-25)
70    super::execution_traits::HasExecution + // execution.taskSupport (MCP 2025-11-25)
71    Send +
72    Sync
73{
74    /// Display name precedence: title > name (matches TypeScript spec)
75    fn display_name(&self) -> &str {
76        if let Some(title) = self.title() {
77            title
78        } else {
79            self.name()
80        }
81    }
82
83    /// Convert to concrete Tool struct for protocol serialization
84    fn to_tool(&self) -> Tool {
85        Tool {
86            name: self.name().to_string(),
87            title: self.title().map(String::from),
88            description: self.description().map(String::from),
89            input_schema: self.input_schema().clone(),
90            output_schema: self.output_schema().cloned(),
91            annotations: self.annotations().cloned(),
92            execution: self.execution(),
93            icons: self.icons().cloned(),
94            meta: self.tool_meta().cloned(),
95        }
96    }
97}
98
99/// Blanket implementation: any type implementing all required traits gets ToolDefinition
100impl<T> ToolDefinition for T
101where
102    T: HasBaseMetadata
103        + HasDescription
104        + HasInputSchema
105        + HasOutputSchema
106        + HasAnnotations
107        + HasToolMeta
108        + super::icon_traits::HasIcons
109        + super::execution_traits::HasExecution
110        + Send
111        + Sync,
112{
113    // Default implementations provided by trait definition
114}