diff --git a/server/src/handlers/ast.rs b/server/src/handlers/ast.rs index 8f082f6..c959b73 100644 --- a/server/src/handlers/ast.rs +++ b/server/src/handlers/ast.rs @@ -41,7 +41,7 @@ impl McpTool for ReadFileSkeletonHandler { async fn execute(&self, args: Value, _state: Arc) -> crate::error::Result { let tool_args: ReadFileSkeletonTool = - serde_json::from_value(args).map_err(|e| e.to_string())?; + serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let file_path = tool_args.file_path.clone(); validate_safe_path(&file_path)?; @@ -202,7 +202,7 @@ impl McpTool for ReplaceAstNodeHandler { async fn execute(&self, args: Value, _state: Arc) -> crate::error::Result { let tool_args: ReplaceAstNodeTool = - serde_json::from_value(args).map_err(|e| e.to_string())?; + serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let file_path = tool_args.file_path.clone(); validate_safe_path(&file_path)?; @@ -237,7 +237,7 @@ impl McpTool for ReplaceAstNodeHandler { parser .set_language(&language.into()) - .map_err(|e| e.to_string())?; + .map_err(|e| crate::error::AppError::Internal(e.to_string()))?; let tree = parser.parse(&code, None).ok_or_else(|| { crate::error::AppError::Internal("Failed to parse code".to_string()) })?; @@ -342,7 +342,7 @@ impl McpTool for ReplaceAstNodeHandler { .unwrap_or_else(|| std::path::Path::new(".")); let temp_file_path = parent_dir.join(format!(".tmp_ast_{}.tmp", uuid::Uuid::new_v4())); - std::fs::write(&temp_file_path, new_file_content).map_err(|e| e.to_string())?; + std::fs::write(&temp_file_path, new_file_content).map_err(|e| crate::error::AppError::Internal(format!("Failed to write temporary file: {}", e)))?; if let Err(e) = std::fs::rename(&temp_file_path, &target_path) { // On Windows, std::fs::rename fails if the target file already exists. // Fall back to copy-and-remove to ensure atomic-like overwrite behavior. @@ -473,7 +473,7 @@ impl McpTool for FindSymbolReferencesHandler { async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { let req: crate::tools::FindSymbolReferencesTool = - serde_json::from_value(args).map_err(|e| e.to_string())?; + serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let limit = req.limit.unwrap_or(10); let target_sym = req.symbol.clone(); @@ -527,7 +527,7 @@ impl McpTool for GetCallersHandler { async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { let req: crate::tools::GetCallersTool = - serde_json::from_value(args).map_err(|e| e.to_string())?; + serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let limit = req.limit.unwrap_or(10); let target_fn = req.function_name.clone(); let call_pattern = format!("{}(", target_fn); @@ -583,7 +583,7 @@ impl McpTool for AnalyzeImpactHandler { async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { let req: crate::tools::AnalyzeImpactTool = - serde_json::from_value(args).map_err(|e| e.to_string())?; + serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let sym = req.target_symbol.clone(); let mut callers = Vec::new(); diff --git a/server/src/handlers/env.rs b/server/src/handlers/env.rs index d1ad744..91c0507 100644 --- a/server/src/handlers/env.rs +++ b/server/src/handlers/env.rs @@ -21,7 +21,7 @@ impl McpTool for EnvironmentHandler { } async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { - let req: EnvironmentTool = serde_json::from_value(args).map_err(|e| e.to_string())?; + let req: EnvironmentTool = serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let ns = req .namespace .unwrap_or_else(crate::models::default_namespace); diff --git a/server/src/handlers/git.rs b/server/src/handlers/git.rs index afb3a36..1411356 100644 --- a/server/src/handlers/git.rs +++ b/server/src/handlers/git.rs @@ -28,7 +28,7 @@ impl McpTool for GetActiveWorktreeContextHandler { ) -> crate::error::Result { let result = tokio::task::spawn_blocking(move || -> crate::error::Result { - let cwd = env::current_dir().map_err(|e| e.to_string())?; + let cwd = env::current_dir().map_err(|e| crate::error::AppError::Internal(format!("Failed to get current directory: {}", e)))?; let repo = git2::Repository::discover(&cwd).map_err(|e| { crate::error::AppError::Internal(format!("Not in a git repository: {}", e)) })?; @@ -108,7 +108,7 @@ impl McpTool for QueryGitDiffsHandler { async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { let req: crate::tools::QueryGitDiffsTool = - serde_json::from_value(args).map_err(|e| e.to_string())?; + serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let limit = req.limit.unwrap_or(5); let q = req.query.to_lowercase(); diff --git a/server/src/handlers/graph.rs b/server/src/handlers/graph.rs index c0744e2..e8de50c 100644 --- a/server/src/handlers/graph.rs +++ b/server/src/handlers/graph.rs @@ -121,7 +121,7 @@ impl McpTool for QueryGraphPathHandler { async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { let req: crate::tools::QueryGraphPathTool = - serde_json::from_value(args).map_err(|e| e.to_string())?; + serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; tokio::task::spawn_blocking(move || { state.read_graph(|graph| { @@ -160,7 +160,7 @@ impl McpTool for CreateEntitiesHandler { } async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { - let req: CreateEntitiesTool = serde_json::from_value(args).map_err(|e| e.to_string())?; + let req: CreateEntitiesTool = serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let mut inserted = Vec::new(); state.modify_graph(|g| { for entity_input in req.entities { @@ -209,7 +209,7 @@ impl McpTool for UpdateEntitiesHandler { } async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { - let req: UpdateEntitiesTool = serde_json::from_value(args).map_err(|e| e.to_string())?; + let req: UpdateEntitiesTool = serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let mut updated_entities = Vec::new(); let mut deleted_names = Vec::new(); @@ -414,7 +414,7 @@ impl McpTool for AddObservationsHandler { } async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { - let req: AddObservationsTool = serde_json::from_value(args).map_err(|e| e.to_string())?; + let req: AddObservationsTool = serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let mut missing_entities = Vec::new(); state.read_graph(|g| { for o in &req.observations { @@ -458,7 +458,7 @@ impl McpTool for DeleteEntitiesHandler { } async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { - let req: DeleteEntitiesTool = serde_json::from_value(args).map_err(|e| e.to_string())?; + let req: DeleteEntitiesTool = serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let to_delete: std::collections::HashSet<_> = req.entity_names.into_iter().collect(); let mut missing = Vec::new(); state.read_graph(|g| { @@ -510,7 +510,7 @@ impl McpTool for DeleteObservationsHandler { async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { let req: DeleteObservationsTool = - serde_json::from_value(args).map_err(|e| e.to_string())?; + serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let mut missing_entities = Vec::new(); let mut missing_observations = Vec::new(); @@ -573,7 +573,7 @@ impl McpTool for DeleteRelationsHandler { } async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { - let req: DeleteRelationsTool = serde_json::from_value(args).map_err(|e| e.to_string())?; + let req: DeleteRelationsTool = serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let mut deleted_count = 0; let requested_count = req.relations.len(); @@ -615,7 +615,7 @@ impl McpTool for ReadGraphHandler { } async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { - let req: ReadGraphTool = serde_json::from_value(args).map_err(|e| e.to_string())?; + let req: ReadGraphTool = serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let max_tokens = req.max_tokens; let limit = req.limit; let offset = req.offset.unwrap_or(0); @@ -751,7 +751,7 @@ impl McpTool for SearchNodesHandler { } async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { - let req: SearchNodesTool = serde_json::from_value(args).map_err(|e| e.to_string())?; + let req: SearchNodesTool = serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let limit = req.limit.unwrap_or(10); let include_body = req.include_body.unwrap_or(false); @@ -801,7 +801,7 @@ impl McpTool for OpenNodesHandler { } async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { - let req: OpenNodesTool = serde_json::from_value(args).map_err(|e| e.to_string())?; + let req: OpenNodesTool = serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let data = state.read_graph(|full| -> crate::error::Result { let targets: HashSet<&str> = req.names.iter().map(|s| s.as_str()).collect(); let mut result = BorrowedGraph::default(); @@ -842,7 +842,7 @@ impl McpTool for VisualizeGraphHandler { } async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { - let req: VisualizeGraphTool = serde_json::from_value(args).map_err(|e| e.to_string())?; + let req: VisualizeGraphTool = serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let query = req.query.unwrap_or_default(); let mut output = state.read_graph(|full| { let mut included: HashSet<&str> = HashSet::new(); @@ -934,7 +934,7 @@ impl McpTool for CondenseEntityHandler { } async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { - let req: CondenseEntityTool = serde_json::from_value(args).map_err(|e| e.to_string())?; + let req: CondenseEntityTool = serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let mut missing = false; if req.summarized_observations.is_empty() { @@ -1020,7 +1020,7 @@ impl McpTool for MergeEntitiesHandler { } async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { - let req: MergeEntitiesTool = serde_json::from_value(args).map_err(|e| e.to_string())?; + let req: MergeEntitiesTool = serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let mut missing = false; state.modify_graph(|master| { if let Some(src) = master.entities.remove(&req.source_entity) { @@ -1116,7 +1116,7 @@ impl McpTool for GetSubgraphHandler { } async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { - let req: GetSubgraphTool = serde_json::from_value(args).map_err(|e| e.to_string())?; + let req: GetSubgraphTool = serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let root = req.root_entity.ok_or_else(|| { crate::error::AppError::Internal("root_entity is required".to_string()) })?; @@ -1211,7 +1211,7 @@ impl McpTool for SweepGraphHealthHandler { } async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { - let req: SweepGraphHealthTool = serde_json::from_value(args).map_err(|e| e.to_string())?; + let req: SweepGraphHealthTool = serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let auto_prune = req.auto_prune_orphans.unwrap_or(false); let auto_prune_stale = req.auto_prune_stale_files.unwrap_or(false); @@ -1309,7 +1309,7 @@ impl McpTool for ResolveStaleSymbolsHandler { async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { let req: ResolveStaleSymbolsTool = - serde_json::from_value(args).map_err(|e| e.to_string())?; + serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let auto_heal = req.auto_heal.unwrap_or(true); let mut checked = 0; @@ -1367,7 +1367,7 @@ impl McpTool for SummarizeSubgraphHandler { } async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { - let req: SummarizeSubgraphTool = serde_json::from_value(args).map_err(|e| e.to_string())?; + let req: SummarizeSubgraphTool = serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let depth = req.depth.unwrap_or(2); let (sub_entities, sub_relations) = state.read_graph(|g| { diff --git a/server/src/handlers/logs.rs b/server/src/handlers/logs.rs index 8bc8db1..7ef2eff 100644 --- a/server/src/handlers/logs.rs +++ b/server/src/handlers/logs.rs @@ -23,7 +23,7 @@ impl McpTool for ProcessLogsHandler { } async fn execute(&self, args: Value, _state: Arc) -> crate::error::Result { - let tool_args: ProcessLogsTool = serde_json::from_value(args).map_err(|e| e.to_string())?; + let tool_args: ProcessLogsTool = serde_json::from_value(args).map_err(|e| crate::error::AppError::Internal(format!("Failed to seek file: {}", e)))?; let safe_path = crate::handlers::utils::validate_safe_path(&tool_args.file_path)?; match tool_args.action { @@ -43,14 +43,14 @@ impl McpTool for ProcessLogsHandler { let mut file = File::open(&safe_path).map_err(|e| { crate::error::AppError::Internal(format!("Failed to open file: {}", e)) })?; - let len = file.metadata().map_err(|e| e.to_string())?.len(); + let len = file.metadata().map_err(|e| crate::error::AppError::Internal(format!("Failed to read file metadata: {}", e)))?.len(); let read_size = std::cmp::min(16 * 1024, len); file.seek(SeekFrom::End(-(read_size as i64))) - .map_err(|e| e.to_string())?; + .map_err(|e| crate::error::AppError::Internal(format!("Failed to seek file: {}", e)))?; let mut vec_buf = Vec::new(); - file.read_to_end(&mut vec_buf).map_err(|e| e.to_string())?; + file.read_to_end(&mut vec_buf).map_err(|e| crate::error::AppError::Internal(format!("Failed to seek file: {}", e)))?; let buffer = String::from_utf8_lossy(&vec_buf).to_string(); let lines: Vec<&str> = buffer.lines().collect(); diff --git a/server/src/handlers/meta.rs b/server/src/handlers/meta.rs index af724ed..acb8e7b 100644 --- a/server/src/handlers/meta.rs +++ b/server/src/handlers/meta.rs @@ -22,7 +22,7 @@ impl McpTool for LogErrorFixHandler { } async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { - let req: LogErrorFixTool = serde_json::from_value(args).map_err(|e| e.to_string())?; + let req: LogErrorFixTool = serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let text_to_embed = format!("Signature: {}\nSolution: {}", req.signature, req.solution); let solution = req.solution; @@ -71,7 +71,7 @@ impl McpTool for SearchErrorFixesHandler { } async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { - let req: SearchErrorFixesTool = serde_json::from_value(args).map_err(|e| e.to_string())?; + let req: SearchErrorFixesTool = serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let limit = req.limit.unwrap_or(5); let include_body = req.include_body.unwrap_or(true); @@ -175,7 +175,7 @@ impl McpTool for LogCodeChangeHandler { } async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { - let req: LogCodeChangeTool = serde_json::from_value(args).map_err(|e| e.to_string())?; + let req: LogCodeChangeTool = serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let mut description = req.description; if let Some(range) = &req.line_range { @@ -353,7 +353,7 @@ impl McpTool for DecisionsHandler { } async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { - let req: DecisionsTool = serde_json::from_value(args).map_err(|e| e.to_string())?; + let req: DecisionsTool = serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; match req { DecisionsTool::Log { title, status, context, decision, consequences, namespace, repo_name, author, affected_components, alternatives_considered, supersedes, git_commit, git_branch, task_id } => { let ns = namespace.clone().unwrap_or_else(crate::models::default_namespace); @@ -607,7 +607,7 @@ impl McpTool for TechDebtHandler { } async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { - let req: TechDebtTool = serde_json::from_value(args).map_err(|e| e.to_string())?; + let req: TechDebtTool = serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; match req { TechDebtTool::Log { description, title: _, ideal_solution, git_commit, git_branch, symbol_references: _, line_range, namespace, severity, repo_name, file_path, workaround, effort_estimate } => { let ns = namespace.clone().unwrap_or_else(crate::models::default_namespace); @@ -733,7 +733,7 @@ impl McpTool for OmniSearchHandler { } async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { - let req: OmniSearchTool = serde_json::from_value(args).map_err(|e| e.to_string())?; + let req: OmniSearchTool = serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let limit = req.limit.unwrap_or(5); let include_body = req.include_body.unwrap_or(false); @@ -1106,7 +1106,7 @@ impl McpTool for GetProjectHealthHandler { } async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { - let req: GetProjectHealthTool = serde_json::from_value(args).map_err(|e| e.to_string())?; + let req: GetProjectHealthTool = serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let active_tasks = state.project.tasks.read_with(|tasks| { tasks .iter() @@ -1157,7 +1157,7 @@ impl McpTool for ManageCheckpointHandler { } async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { - let req: ManageCheckpointTool = serde_json::from_value(args).map_err(|e| e.to_string())?; + let req: ManageCheckpointTool = serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; match req { ManageCheckpointTool::Create { name_or_id, description, namespace } => { let name = name_or_id.ok_or_else(|| crate::error::AppError::Internal("name_or_id is required".to_string()))?; @@ -1297,7 +1297,7 @@ impl McpTool for QueryLineageHandler { } async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { - let req: QueryLineageTool = serde_json::from_value(args).map_err(|e| e.to_string())?; + let req: QueryLineageTool = serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let q = req.query.to_lowercase(); let mut timeline = Vec::new(); @@ -1400,7 +1400,7 @@ impl McpTool for GetNextActionableTasksHandler { async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { let req: GetNextActionableTasksTool = - serde_json::from_value(args).map_err(|e| e.to_string())?; + serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let limit = req.limit.unwrap_or(5); let tasks = state.project.tasks.read_with(|t| t.clone()); @@ -1459,7 +1459,7 @@ impl McpTool for HypothesesHandler { } async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { - let req: HypothesesTool = serde_json::from_value(args).map_err(|e| e.to_string())?; + let req: HypothesesTool = serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; match req { HypothesesTool::Log { hypothesis, task_id, status, evidence } => { let hyp_text = hypothesis; @@ -1527,7 +1527,7 @@ impl McpTool for GetPreflightContextHandler { async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { let req: GetPreflightContextTool = - serde_json::from_value(args).map_err(|e| e.to_string())?; + serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let tasks = state.project.tasks.read_with(|t| t.clone()); let tech_debts = state.code.tech_debts.read_with(|d| d.clone()); @@ -1603,7 +1603,7 @@ impl McpTool for AgentSignalsHandler { } async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { - let req: AgentSignalsTool = serde_json::from_value(args).map_err(|e| e.to_string())?; + let req: AgentSignalsTool = serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; match req { AgentSignalsTool::Broadcast { sender, signal_type, payload, ttl_seconds } => { let sender = sender; @@ -1705,7 +1705,7 @@ impl McpTool for AutoSessionCheckpointHandler { async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { let req: AutoSessionCheckpointTool = - serde_json::from_value(args).map_err(|e| e.to_string())?; + serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let timestamp = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) diff --git a/server/src/handlers/notes.rs b/server/src/handlers/notes.rs index af49f5e..afef914 100644 --- a/server/src/handlers/notes.rs +++ b/server/src/handlers/notes.rs @@ -23,7 +23,7 @@ impl McpTool for HandoffMemosHandler { } async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { - let req: HandoffMemosTool = serde_json::from_value(args).map_err(|e| e.to_string())?; + let req: HandoffMemosTool = serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; match req.action { HandoffMemoAction::Leave => { let content = req.content.ok_or_else(|| { @@ -95,7 +95,7 @@ impl McpTool for AddSessionSummaryHandler { } async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { - let req: AddSessionSummaryTool = serde_json::from_value(args).map_err(|e| e.to_string())?; + let req: AddSessionSummaryTool = serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; state.telemetry.session_summaries.modify(|summaries| { summaries.push(crate::models::SessionSummary { summary: req.summary, @@ -143,7 +143,7 @@ impl McpTool for GenerateStandupReportHandler { async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { let req: GenerateStandupReportTool = - serde_json::from_value(args).map_err(|e| e.to_string())?; + serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let cutoff = crate::handlers::utils::now_secs().saturating_sub(req.hours_lookback * 3600); let filtered_tasks = state.project.tasks.read_with(|items| { @@ -194,7 +194,7 @@ impl McpTool for PromoteToEntityHandler { } async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { - let req: PromoteToEntityTool = serde_json::from_value(args).map_err(|e| e.to_string())?; + let req: PromoteToEntityTool = serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let entity_name = req.entity_name.clone(); let obs = req.content.clone(); diff --git a/server/src/handlers/tasks.rs b/server/src/handlers/tasks.rs index b786b1a..939916f 100644 --- a/server/src/handlers/tasks.rs +++ b/server/src/handlers/tasks.rs @@ -22,7 +22,7 @@ impl McpTool for TasksHandler { } async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { - let req: TasksTool = serde_json::from_value(args).map_err(|e| e.to_string())?; + let req: TasksTool = serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; match req { TasksTool::Add { title, description, parent_id, dependencies, git_branch, namespace, repo_name, priority, assigned_agent, verification_command } => { let description = description.unwrap_or_default(); @@ -414,7 +414,7 @@ impl McpTool for MilestonesHandler { } async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { - let req: MilestonesTool = serde_json::from_value(args).map_err(|e| e.to_string())?; + let req: MilestonesTool = serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; match req { MilestonesTool::Add { title, namespace, target_date, description, deliverables, task_ids, repo_name } => { let ns = namespace.unwrap_or_else(crate::models::default_namespace); diff --git a/server/src/handlers/vision.rs b/server/src/handlers/vision.rs index 2785c07..1c70eb7 100644 --- a/server/src/handlers/vision.rs +++ b/server/src/handlers/vision.rs @@ -700,7 +700,7 @@ impl McpTool for ClipboardHandler { } async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { - let req: ClipboardTool = serde_json::from_value(args).map_err(|e| e.to_string())?; + let req: ClipboardTool = serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; match req.action { ClipboardAction::Image => { let cached_opt = { diff --git a/server/src/handlers/workspaces.rs b/server/src/handlers/workspaces.rs index 02a1097..a465585 100644 --- a/server/src/handlers/workspaces.rs +++ b/server/src/handlers/workspaces.rs @@ -22,7 +22,7 @@ impl McpTool for SnippetsHandler { } async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { - let req: SnippetsTool = serde_json::from_value(args).map_err(|e| e.to_string())?; + let req: SnippetsTool = serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; match req.action { SnippetAction::Store => { let name = req.name.or(req.query).or(req.id).ok_or_else(|| { @@ -231,7 +231,7 @@ impl McpTool for ReadDirectoryArchitectureHandler { async fn execute(&self, args: Value, _state: Arc) -> crate::error::Result { let tool_args: ReadDirectoryArchitectureTool = - serde_json::from_value(args).map_err(|e| e.to_string())?; + serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let dir = tool_args.directory.clone(); let result = tokio::task::spawn_blocking(move || -> crate::error::Result { @@ -301,7 +301,7 @@ impl McpTool for ReadDirectoryArchitectureHandler { } summary.push_str(&format!("Architecture of {}:\n", dir)); - visit_dirs(path, &mut summary, 0).map_err(|e| e.to_string())?; + visit_dirs(path, &mut summary, 0).map_err(|e| crate::error::AppError::Internal(format!("Failed to read directory: {}", e)))?; Ok(summary) }) @@ -330,7 +330,7 @@ impl McpTool for SemanticCodeSearchHandler { async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { let tool_args: SemanticCodeSearchTool = - serde_json::from_value(args).map_err(|e| e.to_string())?; + serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let results = state .search() @@ -388,7 +388,7 @@ impl McpTool for ManageSubagentNamespaceHandler { async fn execute(&self, args: Value, state: Arc) -> crate::error::Result { let req: ManageSubagentNamespaceTool = - serde_json::from_value(args).map_err(|e| e.to_string())?; + serde_json::from_value(args).map_err(|e| crate::error::AppError::BadRequest(format!("Schema validation failed. Your JSON arguments do not match the expected tool schema: {}", e)))?; let subagent_ns = format!("subagent-{}", req.subagent_id); match req.action {