sqlserver_mcp_catalog/prompts/
mod.rs1pub mod router;
7
8use rmcp::schemars;
9use serde::Deserialize;
10
11#[derive(Debug, Deserialize, schemars::JsonSchema)]
12pub struct MasterWorkflowArgs {
13 pub goal: Option<String>,
15}
16
17#[derive(Debug, Deserialize, schemars::JsonSchema)]
18pub struct SqlAgentJobsArgs {
19 pub job_name: Option<String>,
21 pub database: Option<String>,
23}
24
25#[derive(Debug, Deserialize, schemars::JsonSchema)]
26pub struct IndexesConstraintsArgs {
27 pub database: Option<String>,
29 pub schema: Option<String>,
31 pub table: Option<String>,
33}
34
35#[derive(Debug, Deserialize, schemars::JsonSchema)]
36pub struct SecurityProvisioningArgs {
37 pub login_name: Option<String>,
39 pub database: Option<String>,
41 pub role_name: Option<String>,
43}
44
45pub(crate) fn render_context_header(fields: &[(&str, Option<&str>)]) -> String {
52 if fields.is_empty() {
53 return String::new();
54 }
55
56 let mut provided = Vec::new();
57 let mut missing = Vec::new();
58 for (label, value) in fields {
59 match value {
60 Some(v) => provided.push(format!("- {label}: {v}")),
61 None => missing.push(format!("- {label}")),
62 }
63 }
64
65 let render_list = |items: &[String]| {
66 if items.is_empty() {
67 "(none)".to_string()
68 } else {
69 items.join("\n")
70 }
71 };
72
73 format!(
74 "Context already provided:\n{}\n\nStill missing (ask the user before proceeding, if needed):\n{}\n",
75 render_list(&provided),
76 render_list(&missing),
77 )
78}
79
80#[cfg(test)]
81mod tests {
82 use super::*;
83
84 #[test]
85 fn empty_fields_render_nothing() {
86 assert_eq!(render_context_header(&[]), "");
87 }
88
89 #[test]
90 fn all_supplied_lists_no_missing_fields() {
91 let header = render_context_header(&[("goal", Some("explore schema"))]);
92 assert!(header.contains("- goal: explore schema"));
93 assert!(header.contains("Still missing"));
94 assert!(header.ends_with("(none)\n"));
95 }
96
97 #[test]
98 fn all_missing_lists_no_provided_fields() {
99 let header = render_context_header(&[("goal", None)]);
100 assert!(header.starts_with("Context already provided:\n(none)"));
101 assert!(header.contains("- goal"));
102 }
103
104 #[test]
105 fn mixed_supplied_and_missing_are_both_listed() {
106 let header =
107 render_context_header(&[("job_name", Some("nightly_backup")), ("database", None)]);
108 assert!(header.contains("- job_name: nightly_backup"));
109 assert!(header.contains("- database"));
110 assert!(!header.contains("- database: "));
111 }
112}