Skip to main content

agentic_memory_mcp/tools/
memory_quality.rs

1//! Tool: memory_quality — Graph quality and reliability summary.
2
3use 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}