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