refactor: deduplicate arg parsing in handlers and remove redundant python scripts

Created a parse_tool! macro that eliminated ~450 lines of repetitive error-handling boilerplate across 54 MCP tool definitions in server/src/handlers.rs.

Purged 30+ stale, redundant python patching scripts and legacy mcp_client.py test runners that were polluting the workspace root and server/src directories.
This commit is contained in:
Riz Ashraf committed 2026-09-14 04:57:31 +01:00
1 parent ee4157d07b
commit 0e29b12ac8
33 files changed
+71 -1981

No files matched your search

+70 -481
View File
@@ -2,6 +2,22 @@ use crate::models::*;
use crate::state::MemoryState;
use crate::tools::*;
macro_rules! parse_tool {
($args:expr, $id:expr, $type:ty) => {
match parse_args::<$type>($args) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
$id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": format!("Invalid args: {}", e)}] }),
));
}
}
};
}
use serde::de::DeserializeOwned;
use std::collections::HashSet;
use std::sync::Arc;
@@ -124,10 +140,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
let result: Result<String, String> = match name {
"query_graph_path" => {
let req: crate::tools::QueryGraphPathTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => return Some(crate::mcp::success(id.clone(), serde_json::json!({"isError": true, "content": [{"type": "text", "text": format!("Invalid args: {}", e)}] })))
};
let req = parse_tool!(args.clone(), id, crate::tools::QueryGraphPathTool);
let graph = self.state.get_full_graph();
let max_depth = req.max_depth.unwrap_or(5);
let mut queue = std::collections::VecDeque::new();
@@ -185,15 +198,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
}
}
"create_entities" => {
let req: CreateEntitiesTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, CreateEntitiesTool);
self.state.write_to_local_delta(|g| {
for entity in req.entities {
if !entity.name.is_empty() {
@@ -207,15 +212,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec!["Entities created".to_string()][0].clone())
}
"create_relations" => {
let req: CreateRelationsTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, CreateRelationsTool);
self.state.write_to_local_delta(|g| {
for relation in req.relations {
if !relation.from.is_empty() && !relation.to.is_empty() {
@@ -226,15 +223,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec!["Relations created".to_string()][0].clone())
}
"add_observations" => {
let req: AddObservationsTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, AddObservationsTool);
let full = self.state.get_full_graph();
self.state.write_to_local_delta(|g| {
for o in req.observations {
@@ -258,15 +247,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec!["Observations added".to_string()][0].clone())
}
"delete_entities" => {
let req: DeleteEntitiesTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, DeleteEntitiesTool);
let to_delete: HashSet<_> = req.entity_names.into_iter().collect();
self.state.apply_sync_write(|master| {
for name in &to_delete {
@@ -279,15 +260,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec!["Entities deleted".to_string()][0].clone())
}
"delete_observations" => {
let req: DeleteObservationsTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, DeleteObservationsTool);
self.state.apply_sync_write(|master| {
for d in req.deletions {
if let Some(e) = master.entities.get_mut(&d.entity_name)
@@ -300,15 +273,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec!["Observations deleted".to_string()][0].clone())
}
"delete_relations" => {
let req: DeleteRelationsTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, DeleteRelationsTool);
self.state.apply_sync_write(|master| {
let mut to_rem = HashSet::new();
for r in req.relations {
@@ -327,15 +292,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec!["Relations deleted".to_string()][0].clone())
}
"read_graph" => {
let req: ReadGraphTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, ReadGraphTool);
let mut full = self.state.get_full_graph();
if let Some(ns) = req.namespace {
full.entities.retain(|_, e| e.namespace == ns);
@@ -345,15 +302,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec![data.to_string()][0].clone())
}
"search_nodes" => {
let req: SearchNodesTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, SearchNodesTool);
let matches = if let Ok(idx) = self.state.search_index.read() {
idx.search(&req.query, req.namespace.as_deref())
.unwrap_or_default()
@@ -373,15 +322,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec![data.to_string()][0].clone())
}
"open_nodes" => {
let req: OpenNodesTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, OpenNodesTool);
let targets: HashSet<_> = req.names.into_iter().collect();
let full = self.state.get_full_graph();
let mut result = KnowledgeGraph::default();
@@ -404,15 +345,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec![data.to_string()][0].clone())
}
"log_code_change" => {
let req: LogCodeChangeTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, LogCodeChangeTool);
self.state.ledger.modify(|ledger| {
ledger.push(CodeChange {
timestamp: SystemTime::now()
@@ -433,15 +366,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec![data.to_string()][0].clone())
}
"visualize_graph" => {
let req: VisualizeGraphTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, VisualizeGraphTool);
let query = req.query.unwrap_or_default().to_lowercase();
let full = self.state.get_full_graph();
let mut included = HashSet::new();
@@ -511,15 +436,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec![output.to_string()][0].clone())
}
"add_sticky_note" => {
let req: AddStickyNoteTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, AddStickyNoteTool);
self.state.sticky.modify(|notes| {
notes.push(StickyNote {
timestamp: SystemTime::now()
@@ -537,15 +454,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec![data.to_string()][0].clone())
}
"condense_entity" => {
let req: CondenseEntityTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, CondenseEntityTool);
self.state.apply_sync_write(|master| {
if let Some(e) = master.entities.get_mut(&req.entity_name) {
e.observations = req.summarized_observations;
@@ -554,15 +463,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec!["Entity condensed".to_string()][0].clone())
}
"add_task" => {
let req: AddTaskTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, AddTaskTool);
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
@@ -586,15 +487,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec![format!("Task added with ID: {}", id).to_string()][0].clone())
}
"update_task_status" => {
let req: UpdateTaskStatusTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, UpdateTaskStatusTool);
let mut found = false;
self.state.tasks.modify(|tasks| {
for t in tasks.iter_mut() {
@@ -616,15 +509,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
}
}
"list_active_tasks" => {
let req: ListActiveTasksTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, ListActiveTasksTool);
let mut tasks = self.state.tasks.read();
tasks.retain(|t| t.status != "done");
if let Some(branch) = req.git_branch {
@@ -637,15 +522,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec![data.to_string()][0].clone())
}
"store_snippet" => {
let req: StoreSnippetTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, StoreSnippetTool);
self.state.snippets.modify(|snippets| {
snippets.retain(|s| s.name != req.name);
snippets.push(Snippet {
@@ -662,15 +539,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec![format!("Snippet '{}' stored.", req.name).to_string()][0].clone())
}
"search_snippets" => {
let req: SearchSnippetsTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, SearchSnippetsTool);
let query = req.query.to_lowercase();
let snippets = self.state.snippets.read();
let mut results = Vec::new();
@@ -686,15 +555,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec![data.to_string()][0].clone())
}
"delete_snippet" => {
let req: DeleteSnippetTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, DeleteSnippetTool);
let mut deleted = false;
self.state.snippets.modify(|snippets| {
let orig = snippets.len();
@@ -708,15 +569,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
}
}
"log_decision" => {
let req: LogDecisionTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, LogDecisionTool);
let mut id = String::new();
self.state.adrs.modify(|adrs| {
id = format!("ADR-{:04}", adrs.len() + 1);
@@ -735,15 +588,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec![format!("Decision logged as {}", id).to_string()][0].clone())
}
"query_decisions" => {
let req: QueryDecisionsTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, QueryDecisionsTool);
let mut adrs = self.state.adrs.read();
if let Some(q) = req.query {
let q = q.to_lowercase();
@@ -757,15 +602,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec![data.to_string()][0].clone())
}
"merge_entities" => {
let req: MergeEntitiesTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, MergeEntitiesTool);
self.state.apply_sync_write(|master| {
if let Some(src) = master.entities.remove(&req.source_entity) {
if let Some(tgt) = master.entities.get_mut(&req.target_entity) {
@@ -807,15 +644,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec![data.to_string()][0].clone())
}
"learn_preference" => {
let req: LearnPreferenceTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, LearnPreferenceTool);
self.state.prefs.modify(|prefs| {
prefs.insert(
req.key.clone(),
@@ -837,15 +666,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec![data.to_string()][0].clone())
}
"log_error_fix" => {
let req: LogErrorFixTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, LogErrorFixTool);
self.state.error_fixes.modify(|fixes| {
fixes.push(crate::models::ErrorFix {
signature: req.signature,
@@ -861,15 +682,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec!["Error fix logged".to_string()][0].clone())
}
"search_error_fixes" => {
let req: SearchErrorFixesTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, SearchErrorFixesTool);
let q = req.query.to_lowercase();
let mut fixes = self.state.error_fixes.read();
fixes.retain(|f| {
@@ -880,15 +693,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec![data.to_string()][0].clone())
}
"pin_file" => {
let req: PinFileTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, PinFileTool);
self.state.pinned_files.modify(|pinned| {
pinned.retain(|p| {
!(p.namespace == req.namespace && p.file_path == req.file_path)
@@ -906,15 +711,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec!["File pinned".to_string()][0].clone())
}
"unpin_file" => {
let req: UnpinFileTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, UnpinFileTool);
self.state.pinned_files.modify(|pinned| {
pinned.retain(|p| {
!(p.namespace == req.namespace && p.file_path == req.file_path)
@@ -923,15 +720,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec!["File unpinned".to_string()][0].clone())
}
"list_pinned_files" => {
let req: ListPinnedFilesTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, ListPinnedFilesTool);
let mut pinned = self.state.pinned_files.read();
if let Some(ns) = req.namespace {
pinned.retain(|p| p.namespace == ns);
@@ -946,15 +735,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec![data.to_string()][0].clone())
}
"add_session_summary" => {
let req: AddSessionSummaryTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, AddSessionSummaryTool);
self.state.session_summaries.modify(|summaries| {
summaries.push(crate::models::SessionSummary {
summary: req.summary,
@@ -968,15 +749,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec!["Session summary added".to_string()][0].clone())
}
"get_project_timeline" => {
let req: GetProjectTimelineTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, GetProjectTimelineTool);
let mut summaries = self.state.session_summaries.read();
if let Some(ns) = req.namespace {
summaries.retain(|s| s.namespace == ns);
@@ -986,15 +759,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec![data.to_string()][0].clone())
}
"leave_handoff_memo" => {
let req: LeaveHandoffMemoTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, LeaveHandoffMemoTool);
self.state.handoff_memos.modify(|memos| {
memos.push(crate::models::HandoffMemo {
id: uuid::Uuid::new_v4().to_string(),
@@ -1010,15 +775,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec!["Handoff memo left".to_string()][0].clone())
}
"read_handoff_memos" => {
let req: ReadHandoffMemosTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, ReadHandoffMemosTool);
let mut memos = self.state.handoff_memos.read();
if let Some(ns) = req.namespace {
memos.retain(|m| m.namespace == ns);
@@ -1027,15 +784,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec![data.to_string()][0].clone())
}
"clear_handoff_memos" => {
let req: ClearHandoffMemosTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, ClearHandoffMemosTool);
let ids: HashSet<_> = req.ids.into_iter().collect();
self.state
.handoff_memos
@@ -1043,15 +792,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec!["Handoff memos cleared".to_string()][0].clone())
}
"update_env_fingerprint" => {
let req: UpdateEnvFingerprintTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, UpdateEnvFingerprintTool);
self.state.env_fingerprints.modify(|fps| {
fps.insert(
req.namespace.clone(),
@@ -1071,15 +812,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec!["Env fingerprint updated".to_string()][0].clone())
}
"read_env_fingerprint" => {
let req: ReadEnvFingerprintTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, ReadEnvFingerprintTool);
let fps = self.state.env_fingerprints.read();
if let Some(fp) = fps.get(&req.namespace) {
let data = serde_json::to_string(fp).unwrap_or_default();
@@ -1089,15 +822,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
}
}
"log_env_requirement" => {
let req: LogEnvRequirementTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, LogEnvRequirementTool);
self.state.env_requirements.modify(|reqs| {
reqs.retain(|r| !(r.namespace == req.namespace && r.key == req.key));
reqs.push(crate::models::EnvRequirement {
@@ -1110,15 +835,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec!["Env requirement logged".to_string()][0].clone())
}
"add_milestone" => {
let req: AddMilestoneTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, AddMilestoneTool);
self.state.milestones.modify(|ms| {
ms.push(crate::models::Milestone {
id: uuid::Uuid::new_v4().to_string(),
@@ -1131,15 +848,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec!["Milestone added".to_string()][0].clone())
}
"update_milestone" => {
let req: UpdateMilestoneTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, UpdateMilestoneTool);
let mut found = false;
self.state.milestones.modify(|ms| {
for m in ms.iter_mut() {
@@ -1157,15 +866,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
}
}
"list_milestones" => {
let req: ListMilestonesTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, ListMilestonesTool);
let mut ms = self.state.milestones.read();
if let Some(ns) = req.namespace {
ms.retain(|m| m.namespace == ns);
@@ -1174,15 +875,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec![data.to_string()][0].clone())
}
"generate_standup_report" => {
let req: GenerateStandupReportTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, GenerateStandupReportTool);
let cutoff = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
@@ -1213,15 +906,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec![report.to_string().to_string()][0].clone())
}
"register_environment" => {
let req: RegisterEnvironmentTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, RegisterEnvironmentTool);
self.state.environments.modify(|envs| {
envs.retain(|e| !(e.namespace == req.namespace && e.name == req.name));
envs.push(crate::models::EnvironmentDetail {
@@ -1239,30 +924,14 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec!["Environment registered".to_string()][0].clone())
}
"get_environment_details" => {
let req: GetEnvironmentDetailsTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, GetEnvironmentDetailsTool);
let mut envs = self.state.environments.read();
envs.retain(|e| e.namespace == req.namespace);
let data = serde_json::to_string(&envs).unwrap_or_default();
Ok(vec![data.to_string()][0].clone())
}
"add_pr_checklist_item" => {
let req: AddPrChecklistItemTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, AddPrChecklistItemTool);
self.state.pr_checklists.modify(|items| {
items.push(crate::models::PrChecklistItem {
namespace: req.namespace,
@@ -1273,45 +942,21 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec!["PR checklist item added".to_string()][0].clone())
}
"get_pr_checklist" => {
let req: GetPrChecklistTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, GetPrChecklistTool);
let mut items = self.state.pr_checklists.read();
items.retain(|i| i.namespace == req.namespace);
let data = serde_json::to_string(&items).unwrap_or_default();
Ok(vec![data.to_string()][0].clone())
}
"clear_pr_checklist" => {
let req: ClearPrChecklistTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, ClearPrChecklistTool);
self.state
.pr_checklists
.modify(|items| items.retain(|i| i.namespace != req.namespace));
Ok(vec!["PR checklist cleared".to_string()][0].clone())
}
"log_tech_debt" => {
let req: LogTechDebtTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, LogTechDebtTool);
self.state.tech_debts.modify(|debts| {
debts.push(crate::models::TechDebt {
id: uuid::Uuid::new_v4().to_string(),
@@ -1330,15 +975,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec!["Tech debt logged".to_string()][0].clone())
}
"resolve_tech_debt" => {
let req: ResolveTechDebtTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, ResolveTechDebtTool);
let mut found = false;
self.state.tech_debts.modify(|debts| {
for d in debts.iter_mut() {
@@ -1356,15 +993,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
}
}
"list_tech_debt" => {
let req: ListTechDebtTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, ListTechDebtTool);
let mut debts = self.state.tech_debts.read();
debts.retain(|d| {
d.namespace == req.namespace && (req.include_resolved || !d.is_resolved)
@@ -1373,15 +1002,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec![data.to_string()][0].clone())
}
"save_context_workspace" => {
let req: SaveContextWorkspaceTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, SaveContextWorkspaceTool);
self.state.context_workspaces.modify(|ws| {
ws.retain(|w| !(w.namespace == req.namespace && w.name == req.name));
ws.push(crate::models::ContextWorkspace {
@@ -1398,45 +1019,21 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec!["Context workspace saved".to_string()][0].clone())
}
"load_context_workspace" => {
let req: LoadContextWorkspaceTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, LoadContextWorkspaceTool);
let mut ws = self.state.context_workspaces.read();
ws.retain(|w| w.namespace == req.namespace && w.name == req.name);
let data = serde_json::to_string(&ws.first()).unwrap_or_default();
Ok(vec![data.to_string()][0].clone())
}
"list_context_workspaces" => {
let req: ListContextWorkspacesTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, ListContextWorkspacesTool);
let mut ws = self.state.context_workspaces.read();
ws.retain(|w| w.namespace == req.namespace);
let data = serde_json::to_string(&ws).unwrap_or_default();
Ok(vec![data.to_string()][0].clone())
}
"omni_search" => {
let req: OmniSearchTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, OmniSearchTool);
let matches = if let Ok(idx) = self.state.search_index.read() {
idx.search(&req.query, req.namespace.as_deref())
.unwrap_or_default()
@@ -1522,15 +1119,7 @@ crate::mcp::tool_def::<CreateEntitiesTool>("create_entities", "Create new entiti
Ok(vec![report.to_string().to_string()][0].clone())
}
"get_project_health" => {
let req: GetProjectHealthTool = match parse_args(args.clone()) {
Ok(r) => r,
Err(e) => {
return Some(crate::mcp::success(
id.clone(),
serde_json::json!({"isError": true, "content": [{"type": "text", "text": e}] }),
));
}
};
let req = parse_tool!(args.clone(), id, GetProjectHealthTool);
let active_tasks = self
.state
.tasks