mcp_skill_framework/
describe.rs1use std::fmt::Write;
17
18use crate::capability::SkillCapability;
19use crate::family::FamilyMeta;
20use crate::skill::Skill;
21use crate::validation::rules_to_json;
22
23pub fn render_skill<S: 'static>(
29 skill: &dyn Skill<S>,
30 family: Option<&str>,
31 gating: Option<&str>,
32) -> String {
33 let mut out = String::new();
34 let _ = writeln!(out, "Tool: {}", skill.name());
35 if let Some(f) = family {
36 let _ = writeln!(out, "Family: {f}");
37 }
38 if let Some(g) = gating {
39 let _ = writeln!(out, "{g}");
40 }
41 let _ = writeln!(out);
42 let _ = writeln!(out, "Description:");
43 let _ = writeln!(out, " {}", skill.description());
44
45 let use_cases = skill.use_cases();
46 if !use_cases.is_empty() {
47 let _ = writeln!(out);
48 let _ = writeln!(out, "Use cases:");
49 for uc in use_cases {
50 let _ = writeln!(out, " - {uc}");
51 }
52 }
53
54 let examples = skill.examples();
55 if !examples.is_empty() {
56 let _ = writeln!(out);
57 let _ = writeln!(out, "Examples:");
58 for (i, ex) in examples.iter().enumerate() {
59 let _ = writeln!(out, " {}. {}", i + 1, ex.title);
60 let _ = writeln!(out, " args: {}", ex.args);
61 if let Some(note) = ex.note {
62 let _ = writeln!(out, " note: {note}");
63 }
64 }
65 }
66
67 let rules = skill.validation_rules();
68 if !rules.is_empty() {
69 let _ = writeln!(out);
70 let _ = writeln!(out, "Validation rules:");
71 let rules_json = rules_to_json(rules);
72 let rules_pretty = serde_json::to_string_pretty(&rules_json)
73 .unwrap_or_else(|_| "<could not serialize rules>".into());
74 let _ = writeln!(out, "{rules_pretty}");
75 }
76
77 let schema_json = serde_json::to_value(skill.schema().as_ref())
78 .ok()
79 .and_then(|v| serde_json::to_string_pretty(&v).ok())
80 .unwrap_or_else(|| "<could not serialize schema>".into());
81 let _ = writeln!(out);
82 let _ = writeln!(out, "Argument schema (JSON):");
83 let _ = writeln!(out, "{schema_json}");
84
85 out
86}
87
88pub fn render_family(fam: &dyn FamilyMeta, gating: Option<&str>) -> String {
93 let mut out = String::new();
94 let _ = writeln!(out, "Family: {}", fam.family());
95 let _ = writeln!(out, "Description:");
96 let _ = writeln!(out, " {}", fam.description());
97
98 let cap_line = match fam.check_capability() {
99 SkillCapability::Ready => "Capability: Ready".to_string(),
100 SkillCapability::Unavailable { reason, hint } => {
101 let mut s = format!("Capability: Unavailable — {reason}");
102 if let Some(h) = hint {
103 s.push_str(&format!("\n Hint: {h}"));
104 }
105 s
106 }
107 };
108 let _ = writeln!(out, "{cap_line}");
109
110 if let Some(g) = gating {
111 let _ = writeln!(out, "{g}");
112 }
113
114 let tools = fam.tools();
115 let _ = writeln!(out);
116 let _ = writeln!(out, "Tools ({}):", tools.len());
117 for t in &tools {
118 let _ = writeln!(out, " - {t}");
119 }
120
121 if let Some(flow) = fam.example_flow() {
122 let _ = writeln!(out);
123 let _ = writeln!(out, "Example flow:");
124 for line in flow.lines() {
125 let _ = writeln!(out, " {line}");
126 }
127 }
128
129 out
130}