claude_code_acp/mcp/tools/
ask_user_question.rs1use async_trait::async_trait;
9use serde_json::{Value, json};
10
11use crate::mcp::{Tool, ToolContext, ToolResult};
12
13#[derive(Debug, Clone, Default)]
15pub struct AskUserQuestionTool;
16
17impl AskUserQuestionTool {
18 pub fn new() -> Self {
19 Self
20 }
21}
22
23#[async_trait]
24impl Tool for AskUserQuestionTool {
25 fn name(&self) -> &str {
26 "AskUserQuestion"
27 }
28
29 fn description(&self) -> &str {
30 "Ask the user a question during execution"
31 }
32
33 fn input_schema(&self) -> Value {
34 json!({
35 "type": "object",
36 "title": "ask_user_question",
37 "description": "Ask the user a question during execution",
38 "properties": {
39 "question": {
40 "type": "string",
41 "description": "The question to ask the user"
42 },
43 "options": {
44 "type": "array",
45 "items": {"type": "string"},
46 "description": "Optional predefined options for the user to choose from"
47 },
48 "allow_freeform": {
49 "type": "boolean",
50 "description": "Whether to allow free-form text input",
51 "default": false
52 }
53 },
54 "required": ["question"]
55 })
56 }
57
58 async fn execute(&self, input: Value, _context: &ToolContext) -> ToolResult {
59 let question = input.get("question").and_then(|v| v.as_str()).unwrap_or("");
61
62 let options = input.get("options").and_then(|v| v.as_array());
63 let allow_freeform = input
64 .get("allow_freeform")
65 .and_then(|v| v.as_bool())
66 .unwrap_or(false);
67
68 ToolResult::success(format!("Question: '{}'", question)).with_metadata(json!({
70 "question": question,
71 "has_options": options.is_some(),
72 "allow_freeform": allow_freeform
73 }))
74 }
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80
81 #[test]
82 fn test_ask_user_question_name() {
83 let tool = AskUserQuestionTool;
84 assert_eq!(tool.name(), "AskUserQuestion");
85 }
86
87 #[test]
88 fn test_ask_user_question_input_schema() {
89 let tool = AskUserQuestionTool;
90 let schema = tool.input_schema();
91
92 assert_eq!(schema["type"], "object");
93 assert_eq!(schema["title"], "ask_user_question");
94 assert!(schema["properties"]["question"].is_object());
95 }
96
97 #[tokio::test]
98 async fn test_ask_user_question_execute() {
99 let tool = AskUserQuestionTool;
100 let context = ToolContext::new("test-session", std::path::Path::new("/tmp"));
101
102 let input = json!({
103 "question": "What is your favorite color?",
104 "options": ["Red", "Green", "Blue"],
105 "allow_freeform": true
106 });
107
108 let result = tool.execute(input, &context).await;
109
110 assert!(!result.is_error);
112 }
113}