do-memory-mcp 0.1.31

Model Context Protocol (MCP) server for AI agents
Documentation
//! # Memory MCP Integration Sample
//!
//! This example demonstrates the complete integration between the self-learning memory system
//! and the MCP (Model Context Protocol) server. It shows how to:
//!
//! 1. Create and manage episodes in the memory system
//! 2. Use the MCP server to query memory and analyze patterns
//! 3. Verify database entries and memory integration
//! 4. Test pattern extraction and analysis
//!
//! ## Usage
//!
//! Run this example to see the full memory-MCP integration in action:
//!
//! ```bash
//! cargo run --example memory_mcp_integration
//! ```

use do_memory_core::{
    ComplexityLevel, ExecutionStep, SelfLearningMemory, TaskContext, TaskOutcome, TaskType,
};
use do_memory_mcp::{MemoryMCPServer, SandboxConfig};
use serde_json::json;
use std::sync::Arc;
use tokio::time::{Duration, sleep};

#[tokio::main]
#[allow(clippy::unwrap_used)]
async fn main() -> anyhow::Result<()> {
    println!("🚀 Memory MCP Integration Sample");
    println!("================================\n");

    // Initialize the memory system
    println!("1. Initializing Memory System...");
    let memory = Arc::new(SelfLearningMemory::new());
    println!("   ✅ Memory system initialized\n");

    // Create the MCP server
    println!("2. Creating MCP Server...");
    let sandbox_config = SandboxConfig::restrictive();
    let mcp_server = Arc::new(MemoryMCPServer::new(sandbox_config, memory.clone()).await?);
    println!(
        "   ✅ MCP server created with {} tools\n",
        mcp_server.list_tools().await.len()
    );

    // Demonstrate episode lifecycle
    println!("3. Episode Lifecycle Demonstration");
    println!("   -------------------------------");

    // Start an episode
    println!("   3.1 Starting episode...");
    let episode_id = memory
        .start_episode(
            "Implement user authentication API".to_string(),
            TaskContext {
                domain: "web-api".to_string(),
                language: Some("rust".to_string()),
                framework: Some("axum".to_string()),
                complexity: ComplexityLevel::Moderate,
                tags: vec!["authentication".to_string(), "api".to_string()],
            },
            TaskType::CodeGeneration,
        )
        .await;
    println!("       ✅ Episode started\n");

    // Log some execution steps
    println!("   3.2 Logging execution steps...");
    let steps = vec![
        ExecutionStep::new(1, "cargo".to_string(), "create_project".to_string()),
        ExecutionStep::new(
            2,
            "rust_analyzer".to_string(),
            "implement_auth_struct".to_string(),
        ),
        ExecutionStep::new(3, "cargo".to_string(), "add_dependencies".to_string()),
    ];

    for (i, mut step) in steps.into_iter().enumerate() {
        // Set additional step properties
        step.parameters = json!({
            "command": match i {
                0 => "cargo new auth-api --bin",
                1 => "implement user and token structs",
                2 => "cargo add jsonwebtoken bcrypt",
                _ => "unknown"
            }
        });
        step.result = Some(do_memory_core::ExecutionResult::Success {
            output: match i {
                0 => "Created binary (application) `auth-api` package".to_string(),
                1 => "Implemented User and AuthToken structs with validation".to_string(),
                2 => "Added dependencies: jsonwebtoken, bcrypt".to_string(),
                _ => "Completed".to_string(),
            },
        });
        step.latency_ms = match i {
            0 => 150,
            1 => 320,
            2 => 200,
            _ => 100,
        };
        step.tokens_used = Some(match i {
            0 => 50,
            1 => 120,
            2 => 30,
            _ => 25,
        });

        memory.log_step(episode_id, step).await;
        println!(
            "       ✅ Step {} logged: {}",
            i + 1,
            match i {
                0 => "create_project",
                1 => "implement_auth_struct",
                2 => "add_dependencies",
                _ => "unknown",
            }
        );
    }
    println!();

    // Complete the episode
    println!("   3.3 Completing episode...");
    let outcome = TaskOutcome::Success {
        verdict: "Successfully implemented JWT-based authentication API with proper error handling"
            .to_string(),
        artifacts: vec![
            "src/auth.rs".to_string(),
            "src/models.rs".to_string(),
            "/api/auth/login".to_string(),
            "/api/auth/register".to_string(),
        ],
    };

    memory.complete_episode(episode_id, outcome).await.unwrap();
    println!("       ✅ Episode completed successfully\n");

    // Wait a moment for pattern extraction
    println!("   3.4 Waiting for pattern extraction...");
    sleep(Duration::from_millis(100)).await;
    println!("       ✅ Pattern extraction completed\n");

    // Demonstrate MCP server functionality
    println!("4. MCP Server Functionality Tests");
    println!("   -------------------------------");

    // Test memory querying
    println!("   4.1 Testing memory queries...");
    let memory_result = mcp_server
        .query_memory(
            "authentication API implementation".to_string(),
            "web-api".to_string(),
            Some("code_generation".to_string()),
            10,
            "relevance".to_string(),
            None,
        )
        .await?;
    println!(
        "       ✅ Memory query returned {} episodes and {} patterns",
        memory_result["episodes"].as_array().unwrap().len(),
        memory_result["patterns"].as_array().unwrap().len()
    );

    // Test pattern analysis
    println!("   4.2 Testing pattern analysis...");
    let pattern_result = mcp_server
        .analyze_patterns("code_generation".to_string(), 0.7, 10, None)
        .await
        .unwrap();
    println!(
        "       ✅ Pattern analysis returned {} patterns",
        pattern_result["patterns"].as_array().unwrap().len()
    );
    println!(
        "       📊 Statistics: {} total patterns, avg success rate: {:.2}",
        pattern_result["statistics"]["total_patterns"],
        pattern_result["statistics"]["avg_success_rate"]
    );
    println!();

    // Database verification tests
    println!("5. Database Verification Tests");
    println!("   ---------------------------");

    // Test episode storage
    println!("   5.1 Verifying episode storage...");
    let episodes = memory
        .retrieve_relevant_context(
            "authentication".to_string(),
            TaskContext {
                domain: "web-api".to_string(),
                language: None,
                framework: None,
                complexity: ComplexityLevel::Moderate,
                tags: vec![],
            },
            10,
        )
        .await;
    assert!(!episodes.is_empty(), "No episodes found in database");
    println!("       ✅ Found {} episodes in database", episodes.len());

    // Verify episode content
    let episode = &episodes[0];
    assert_eq!(
        episode.task_description,
        "Implement user authentication API"
    );
    assert!(episode.outcome.is_some());
    assert!(episode.steps.len() == 3);
    println!("       ✅ Episode content verified (description, outcome, steps)");

    // Test pattern extraction
    println!("   5.2 Verifying pattern extraction...");
    let patterns = memory
        .retrieve_relevant_patterns(
            &TaskContext {
                domain: "web-api".to_string(),
                language: None,
                framework: None,
                complexity: ComplexityLevel::Moderate,
                tags: vec!["authentication".to_string()],
            },
            10,
        )
        .await;
    // Note: patterns might be empty initially as pattern extraction is async
    println!(
        "       ✅ Pattern retrieval completed (found {} patterns)",
        patterns.len()
    );

    // Test tool usage tracking
    println!("   5.3 Verifying tool usage tracking...");
    let usage = mcp_server.get_tool_usage().await;
    assert!(usage.contains_key("query_memory"));
    assert!(usage.contains_key("analyze_patterns"));
    println!(
        "       ✅ Tool usage tracking verified ({} tools tracked)",
        usage.len()
    );

    // Test execution statistics
    println!("   5.4 Verifying execution statistics...");
    let stats = mcp_server.get_stats().await;
    // Note: Code execution may fail if Node.js is not available, so we just verify stats are tracked
    println!(
        "       ✅ Execution statistics verified ({} total executions, {} successful, {} failed, {} violations)",
        stats.total_executions,
        stats.successful_executions,
        stats.failed_executions,
        stats.security_violations
    );

    println!();
    println!("🎉 Memory MCP Integration Sample Completed Successfully!");
    println!("======================================================");
    println!("✅ Episode lifecycle: Create → Log steps → Complete → Extract patterns");
    println!("✅ MCP server: Query memory → Analyze patterns");
    println!("✅ Database verification: Episodes, patterns, and statistics stored correctly");
    println!("✅ Integration: Memory system and MCP server fully integrated");

    Ok(())
}