github_mcp/prompts/
mod.rs1pub mod router;
6
7use rmcp::schemars;
8use serde::Deserialize;
9
10#[derive(Debug, Deserialize, schemars::JsonSchema)]
11pub struct MasterWorkflowArgs {
12 pub goal: Option<String>,
14}
15
16#[derive(Debug, Deserialize, schemars::JsonSchema)]
17pub struct PullRequestWorkflowArgs {
18 pub owner: Option<String>,
20 pub repo: Option<String>,
22 pub base_branch: Option<String>,
24 pub head_branch: Option<String>,
26}
27
28#[derive(Debug, Deserialize, schemars::JsonSchema)]
29pub struct RulesetsWorkflowArgs {
30 pub owner_or_org: Option<String>,
32 pub repo: Option<String>,
34 pub ruleset_name: Option<String>,
36 pub target_ref_pattern: Option<String>,
38}
39
40#[derive(Debug, Deserialize, schemars::JsonSchema)]
41pub struct EnvironmentsDeploymentsWorkflowArgs {
42 pub owner: Option<String>,
44 pub repo: Option<String>,
46 pub environment_name: Option<String>,
48}
49
50pub(crate) fn render_context_header(fields: &[(&str, Option<&str>)]) -> String {
55 if fields.is_empty() {
56 return String::new();
57 }
58 let mut out = String::from("## Context already provided\n");
59 let mut any_known = false;
60 for (name, value) in fields {
61 if let Some(v) = value {
62 out.push_str(&format!("- `{name}` = \"{v}\"\n"));
63 any_known = true;
64 }
65 }
66 if !any_known {
67 out.push_str("- (none — no arguments were supplied with this prompt request)\n");
68 }
69 let missing: Vec<_> = fields
70 .iter()
71 .filter(|(_, v)| v.is_none())
72 .map(|(n, _)| *n)
73 .collect();
74 if !missing.is_empty() {
75 out.push_str(&format!(
76 "\nStill unknown, ask the user before the step that needs it: {}\n",
77 missing.join(", ")
78 ));
79 }
80 out
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86
87 #[test]
88 fn empty_field_list_renders_nothing() {
89 assert_eq!(render_context_header(&[]), "");
90 }
91
92 #[test]
93 fn all_fields_supplied_lists_each_and_no_missing_section() {
94 let header =
95 render_context_header(&[("owner", Some("octocat")), ("repo", Some("hello-world"))]);
96 assert!(header.contains("`owner` = \"octocat\""));
97 assert!(header.contains("`repo` = \"hello-world\""));
98 assert!(!header.contains("Still unknown"));
99 }
100
101 #[test]
102 fn all_fields_missing_notes_none_supplied_and_lists_all_as_missing() {
103 let header = render_context_header(&[("owner", None), ("repo", None)]);
104 assert!(header.contains("(none — no arguments were supplied"));
105 assert!(
106 header
107 .contains("Still unknown, ask the user before the step that needs it: owner, repo")
108 );
109 }
110
111 #[test]
112 fn mixed_fields_report_supplied_and_missing_separately() {
113 let header = render_context_header(&[("owner", Some("octocat")), ("repo", None)]);
114 assert!(header.contains("`owner` = \"octocat\""));
115 assert!(!header.contains("`repo` ="));
116 assert!(header.contains("Still unknown, ask the user before the step that needs it: repo"));
117 }
118}