agentic_memory_mcp/tools/
memory_quality.rs1use std::sync::Arc;
4use tokio::sync::Mutex;
5
6use serde::Deserialize;
7use serde_json::{json, Value};
8
9use agentic_memory::{MemoryQualityParams, QueryEngine};
10
11use crate::session::SessionManager;
12use crate::types::{McpError, McpResult, ToolCallResult, ToolDefinition};
13
14#[derive(Debug, Deserialize)]
15struct QualityParams {
16 #[serde(default = "default_low_conf")]
17 low_confidence_threshold: f32,
18 #[serde(default = "default_stale_decay")]
19 stale_decay_threshold: f32,
20 #[serde(default = "default_max_examples")]
21 max_examples: usize,
22}
23
24fn default_low_conf() -> f32 {
25 0.45
26}
27fn default_stale_decay() -> f32 {
28 0.20
29}
30fn default_max_examples() -> usize {
31 20
32}
33
34pub fn definition() -> ToolDefinition {
35 ToolDefinition {
36 name: "memory_quality".to_string(),
37 description: Some(
38 "Evaluate memory reliability: confidence, staleness, orphan nodes, and unsupported decisions"
39 .to_string(),
40 ),
41 input_schema: json!({
42 "type": "object",
43 "properties": {
44 "low_confidence_threshold": { "type": "number", "default": 0.45 },
45 "stale_decay_threshold": { "type": "number", "default": 0.20 },
46 "max_examples": { "type": "integer", "default": 20 }
47 }
48 }),
49 }
50}
51
52pub async fn execute(
53 args: Value,
54 session: &Arc<Mutex<SessionManager>>,
55) -> McpResult<ToolCallResult> {
56 let params: QualityParams = serde_json::from_value(args)
57 .map_err(|e| McpError::InvalidParams(format!("invalid params: {e}")))?;
58
59 let session = session.lock().await;
60 let graph = session.graph();
61 let qe = QueryEngine::new();
62 let report = qe
63 .memory_quality(
64 graph,
65 MemoryQualityParams {
66 low_confidence_threshold: params.low_confidence_threshold.clamp(0.0, 1.0),
67 stale_decay_threshold: params.stale_decay_threshold.clamp(0.0, 1.0),
68 max_examples: params.max_examples.max(1),
69 },
70 )
71 .map_err(|e| McpError::AgenticMemory(format!("memory quality failed: {e}")))?;
72
73 Ok(ToolCallResult::json(&json!({
74 "status": report.status,
75 "summary": {
76 "nodes": report.node_count,
77 "edges": report.edge_count,
78 "low_confidence_count": report.low_confidence_count,
79 "stale_count": report.stale_count,
80 "orphan_count": report.orphan_count,
81 "decisions_without_support_count": report.decisions_without_support_count,
82 "contradiction_edges": report.contradiction_edges,
83 "supersedes_edges": report.supersedes_edges
84 },
85 "examples": {
86 "low_confidence": report.low_confidence_examples,
87 "stale": report.stale_examples,
88 "orphan": report.orphan_examples,
89 "unsupported_decisions": report.unsupported_decision_examples
90 }
91 })))
92}