task_graph_mcp/tools/
workflows.rs1use super::make_tool;
4use crate::config::workflows::WorkflowsConfig;
5use anyhow::Result;
6use rmcp::model::Tool;
7use serde_json::{Value, json};
8
9pub fn get_tools() -> Vec<Tool> {
11 vec![make_tool(
12 "list_workflows",
13 "List all available workflows. Returns name + description for each workflow. \
14 Call BEFORE connecting to discover which workflows exist. \
15 Use the workflow name with the `connect` tool's `workflow` parameter.",
16 json!({}),
17 vec![],
18 )]
19}
20
21pub fn list_workflows(workflows: &WorkflowsConfig) -> Result<Value> {
23 let mut entries: Vec<Value> = workflows
24 .named_workflows
25 .iter()
26 .map(|(key, config)| {
27 json!({
28 "name": key,
29 "description": config.description.as_deref().unwrap_or(""),
30 })
31 })
32 .collect();
33
34 entries.sort_by(|a, b| {
36 let a_name = a.get("name").and_then(|v| v.as_str()).unwrap_or("");
37 let b_name = b.get("name").and_then(|v| v.as_str()).unwrap_or("");
38 a_name.cmp(b_name)
39 });
40
41 let mut overlay_entries: Vec<Value> = workflows
43 .named_overlays
44 .iter()
45 .map(|(key, config)| {
46 json!({
47 "name": key,
48 "description": config.description.as_deref().unwrap_or(""),
49 })
50 })
51 .collect();
52
53 overlay_entries.sort_by(|a, b| {
54 let a_name = a.get("name").and_then(|v| v.as_str()).unwrap_or("");
55 let b_name = b.get("name").and_then(|v| v.as_str()).unwrap_or("");
56 a_name.cmp(b_name)
57 });
58
59 Ok(json!({
60 "count": entries.len(),
61 "workflows": entries,
62 "overlays": overlay_entries,
63 }))
64}