Skip to main content

devboy_mcp/
handlers.rs

1//! Built-in tool registry for MCP server.
2//!
3//! Tool execution is delegated to `devboy_executor::Executor`.
4//! This module provides the list of known built-in tool names
5//! for validation and configuration purposes.
6
7/// All known built-in tool names (provider tools + context management tools).
8///
9/// This list must stay in sync with `devboy_executor::tools::base_tool_definitions()`
10/// plus the context management tools handled by McpServer.
11pub const KNOWN_BUILTIN_TOOLS: &[&str] = &[
12    // Issue tracker tools
13    "get_issues",
14    "get_issue",
15    "get_issue_comments",
16    "get_issue_relations",
17    "create_issue",
18    "update_issue",
19    "add_issue_comment",
20    "get_available_statuses",
21    "get_users",
22    "link_issues",
23    "unlink_issues",
24    "get_assets",
25    "upload_asset",
26    "download_asset",
27    "delete_asset",
28    // Project versions (issue #238)
29    "list_project_versions",
30    "upsert_project_version",
31    // Agile / Sprint (issue #198)
32    "get_board_sprints",
33    "assign_to_sprint",
34    // Custom-field discovery
35    "get_custom_fields",
36    // Git repository tools (MR/PR, pipeline)
37    "get_merge_requests",
38    "get_merge_request",
39    "get_merge_request_discussions",
40    "get_merge_request_diffs",
41    "create_merge_request",
42    "create_merge_request_comment",
43    "update_merge_request",
44    "get_pipeline",
45    "get_job_logs",
46    // Epic tools
47    "get_epics",
48    "create_epic",
49    "update_epic",
50    // Meeting notes tools
51    "get_meeting_notes",
52    "get_meeting_transcript",
53    "search_meeting_notes",
54    // Knowledge base tools
55    "get_knowledge_base_spaces",
56    "list_knowledge_base_pages",
57    "get_knowledge_base_page",
58    "create_knowledge_base_page",
59    "update_knowledge_base_page",
60    "search_knowledge_base",
61    // Messenger tools
62    "get_messenger_chats",
63    "get_chat_messages",
64    "search_chat_messages",
65    "send_message",
66    // Jira Structure plugin tools
67    "get_structures",
68    "get_structure_forest",
69    "add_structure_rows",
70    "move_structure_rows",
71    "remove_structure_row",
72    "get_structure_values",
73    "get_structure_views",
74    "save_structure_view",
75    "create_structure",
76    // Context management (handled by McpServer directly)
77    "list_contexts",
78    "use_context",
79    "get_current_context",
80    // Layered-pipeline lifecycle (Paper 2 §Implementation Status)
81    "compact_pipeline_cache",
82];
83
84#[cfg(test)]
85mod tests {
86    use super::*;
87
88    #[test]
89    fn test_known_builtin_tools_includes_context_tools() {
90        assert!(KNOWN_BUILTIN_TOOLS.contains(&"list_contexts"));
91        assert!(KNOWN_BUILTIN_TOOLS.contains(&"use_context"));
92        assert!(KNOWN_BUILTIN_TOOLS.contains(&"get_current_context"));
93    }
94
95    #[test]
96    fn test_known_builtin_tools_includes_provider_tools() {
97        assert!(KNOWN_BUILTIN_TOOLS.contains(&"get_issues"));
98        assert!(KNOWN_BUILTIN_TOOLS.contains(&"get_merge_requests"));
99        assert!(KNOWN_BUILTIN_TOOLS.contains(&"get_meeting_notes"));
100        assert!(KNOWN_BUILTIN_TOOLS.contains(&"get_messenger_chats"));
101        assert!(KNOWN_BUILTIN_TOOLS.contains(&"get_epics"));
102    }
103
104    /// Verify that KNOWN_BUILTIN_TOOLS stays in sync with executor's base definitions.
105    #[test]
106    fn test_known_builtin_tools_matches_executor() {
107        let base_tools = devboy_executor::tools::base_tool_definitions();
108        let context_tools = &[
109            "list_contexts",
110            "use_context",
111            "get_current_context",
112            "compact_pipeline_cache",
113        ];
114
115        // Every base tool should be in KNOWN_BUILTIN_TOOLS
116        for tool in &base_tools {
117            assert!(
118                KNOWN_BUILTIN_TOOLS.contains(&tool.name.as_str()),
119                "executor tool '{}' missing from KNOWN_BUILTIN_TOOLS",
120                tool.name
121            );
122        }
123
124        // Every non-context tool in KNOWN_BUILTIN_TOOLS should be in base_tools
125        for name in KNOWN_BUILTIN_TOOLS {
126            if context_tools.contains(name) {
127                continue;
128            }
129            assert!(
130                base_tools.iter().any(|t| t.name == *name),
131                "KNOWN_BUILTIN_TOOLS contains '{}' which is not in executor base definitions",
132                name
133            );
134        }
135    }
136
137    #[test]
138    fn test_known_builtin_tools_no_duplicates() {
139        let mut sorted: Vec<&str> = KNOWN_BUILTIN_TOOLS.to_vec();
140        let original_len = sorted.len();
141        sorted.sort();
142        sorted.dedup();
143        assert_eq!(
144            sorted.len(),
145            original_len,
146            "should have no duplicate tool names"
147        );
148    }
149}