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:
1 parent
ee4157d07b
commit
0e29b12ac8
33 files changed
+71
-1981
No files matched your search
+70
-481
@@ -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
|
||||
|
||||
Reference in new issue
Block a user