turul_mcp_builders/traits/
prompt_traits.rs

1//! Framework traits for MCP prompt construction
2//!
3//! **IMPORTANT**: These are framework features, NOT part of the MCP specification.
4//! The MCP specification defines concrete types only.
5
6use std::collections::HashMap;
7use serde_json::Value;
8
9// Import protocol types (spec-defined)
10use turul_mcp_protocol::Prompt;
11use turul_mcp_protocol::prompts::{PromptArgument, PromptAnnotations};
12
13pub trait HasPromptMetadata {
14    /// Programmatic identifier (fallback display name)
15    fn name(&self) -> &str;
16
17    /// Human-readable display name (UI contexts)
18    fn title(&self) -> Option<&str> {
19        None
20    }
21}
22
23/// Prompt description trait
24pub trait HasPromptDescription {
25    fn description(&self) -> Option<&str> {
26        None
27    }
28}
29
30/// Prompt arguments trait
31pub trait HasPromptArguments {
32    fn arguments(&self) -> Option<&Vec<PromptArgument>> {
33        None
34    }
35}
36
37/// Prompt annotations trait
38pub trait HasPromptAnnotations {
39    fn annotations(&self) -> Option<&PromptAnnotations> {
40        None
41    }
42}
43
44/// Prompt-specific meta trait (separate from RPC _meta)
45pub trait HasPromptMeta {
46    fn prompt_meta(&self) -> Option<&HashMap<String, Value>> {
47        None
48    }
49}
50
51/// Complete prompt definition - composed from fine-grained traits
52/// **Complete MCP Prompt Creation** - Build reusable prompt templates that generate contextual content.
53///
54/// This trait represents a **complete, working MCP prompt** that can be registered with a server
55/// and invoked by clients. When you implement the required metadata traits, you automatically
56/// get `PromptDefinition` for free via blanket implementation.
57///
58/// ## What This Enables
59///
60/// Prompts implementing `PromptDefinition` become **full MCP citizens** that are:
61/// - 🔍 **Discoverable** via `prompts/list` requests
62/// - 🎯 **Executable** via `prompts/get` requests with arguments
63/// - ✅ **Validated** against their argument specifications
64/// - 📝 **Template-driven** for consistent, reusable content generation
65///
66/// ## Complete Working Example
67///
68/// ```rust
69/// use turul_mcp_protocol::prompts::*;
70/// use turul_mcp_builders::prelude::*;  // Import framework traits
71/// use std::collections::HashMap;
72///
73/// // This struct will automatically implement PromptDefinition!
74/// struct CodeReviewPrompt {
75///     arguments: Vec<PromptArgument>,
76/// }
77///
78/// impl CodeReviewPrompt {
79///     fn new() -> Self {
80///         Self {
81///             arguments: vec![
82///                 PromptArgument {
83///                     name: "language".to_string(),
84///                     title: None,
85///                     description: Some("Programming language".to_string()),
86///                     required: Some(true),
87///                 },
88///                 PromptArgument {
89///                     name: "code".to_string(),
90///                     title: None,
91///                     description: Some("Source code to review".to_string()),
92///                     required: Some(true),
93///                 },
94///             ],
95///         }
96///     }
97/// }
98///
99/// impl HasPromptMetadata for CodeReviewPrompt {
100///     fn name(&self) -> &str { "code_review" }
101///     fn title(&self) -> Option<&str> { Some("AI Code Review") }
102/// }
103///
104/// impl HasPromptDescription for CodeReviewPrompt {
105///     fn description(&self) -> Option<&str> {
106///         Some("Generate code review comments")
107///     }
108/// }
109///
110/// impl HasPromptArguments for CodeReviewPrompt {
111///     fn arguments(&self) -> Option<&Vec<PromptArgument>> {
112///         Some(&self.arguments)
113///     }
114/// }
115///
116/// impl HasPromptAnnotations for CodeReviewPrompt {
117///     fn annotations(&self) -> Option<&PromptAnnotations> { None }
118/// }
119///
120/// impl HasPromptMeta for CodeReviewPrompt {
121///     fn prompt_meta(&self) -> Option<&HashMap<String, serde_json::Value>> { None }
122/// }
123///
124/// // 🎉 CodeReviewPrompt now automatically implements PromptDefinition!
125/// let prompt = CodeReviewPrompt::new();
126/// assert_eq!(prompt.name(), "code_review");
127/// assert_eq!(prompt.arguments().unwrap().len(), 2);
128/// ```
129///
130/// ## Usage Patterns
131///
132/// ### Easy: Use Derive Macros (see turul-mcp-derive crate)
133/// ```rust
134/// // Example of manual implementation without macros
135/// use turul_mcp_protocol::prompts::*;
136/// use turul_mcp_builders::prelude::*;  // Import framework traits
137/// use std::collections::HashMap;
138///
139/// struct DocumentationPrompt;
140///
141/// impl HasPromptMetadata for DocumentationPrompt {
142///     fn name(&self) -> &str { "doc_generator" }
143///     fn title(&self) -> Option<&str> { None }
144/// }
145///
146/// impl HasPromptDescription for DocumentationPrompt {
147///     fn description(&self) -> Option<&str> {
148///         Some("Generate API documentation")
149///     }
150/// }
151///
152/// impl HasPromptArguments for DocumentationPrompt {
153///     fn arguments(&self) -> Option<&Vec<PromptArgument>> { None }
154/// }
155///
156/// impl HasPromptAnnotations for DocumentationPrompt {
157///     fn annotations(&self) -> Option<&PromptAnnotations> { None }
158/// }
159///
160/// impl HasPromptMeta for DocumentationPrompt {
161///     fn prompt_meta(&self) -> Option<&HashMap<String, serde_json::Value>> { None }
162/// }
163///
164/// let prompt = DocumentationPrompt;
165/// assert_eq!(prompt.name(), "doc_generator");
166/// ```
167///
168/// ### Advanced: Manual Implementation (shown above)
169/// Perfect when you need complex argument validation or dynamic prompt generation.
170///
171/// ## Real-World Prompt Ideas
172///
173/// - **Code Prompts**: Code reviews, documentation generation, refactoring suggestions, test creation
174/// - **Content Prompts**: Blog post outlines, email templates, meeting summaries, report generation
175/// - **Analysis Prompts**: Data insights, security assessments, performance analysis, bug reports
176/// - **Learning Prompts**: Tutorial creation, concept explanations, example generation, Q&A formatting
177/// - **Workflow Prompts**: Task breakdowns, project planning, requirement analysis, user stories
178///
179/// ## How It Works in MCP
180///
181/// 1. **Registration**: Server registers your prompt during startup
182/// 2. **Discovery**: Client calls `prompts/list` → sees available prompts with arguments
183/// 3. **Parameter Collection**: Client gathers required arguments from user/context
184/// 4. **Generation**: Client calls `prompts/get` with prompt name and arguments
185/// 5. **Template Processing**: Your prompt generates contextual content
186/// 6. **Response**: Framework delivers generated content back to client
187///
188/// The framework handles argument validation, parameter substitution, and content delivery!
189pub trait PromptDefinition:
190    HasPromptMetadata +       // name, title (from BaseMetadata)
191    HasPromptDescription +    // description
192    HasPromptArguments +      // arguments
193    HasPromptAnnotations +    // annotations
194    HasPromptMeta +           // _meta (prompt-specific)
195    Send +
196    Sync
197{
198    /// Display name precedence: title > name (matches TypeScript spec)
199    fn display_name(&self) -> &str {
200        self.title().unwrap_or_else(|| self.name())
201    }
202
203    /// Convert to concrete Prompt struct for protocol serialization
204    fn to_prompt(&self) -> Prompt {
205        Prompt {
206            name: self.name().to_string(),
207            title: self.title().map(String::from),
208            description: self.description().map(String::from),
209            arguments: self.arguments().cloned(),
210            meta: self.prompt_meta().cloned(),
211        }
212    }
213}
214impl<T> PromptDefinition for T where
215    T: HasPromptMetadata
216        + HasPromptDescription
217        + HasPromptArguments
218        + HasPromptAnnotations
219        + HasPromptMeta
220        + Send
221        + Sync
222{
223}
224