mcp-cli 0.3.0

Interactive CLI debugger and TUI for MCP servers
//! Beautiful Demonstration of MCP Negotiation Flow DSL
//!
//! This file showcases the elegant, fluid syntax of our MCP negotiation DSL,
//! demonstrating how complex protocol flows can be composed from simple,
//! reusable building blocks in a readable, maintainable way.

// Demo flow for MCP negotiation
use anyhow::Result;
use mcp_probe_core::{messages::Implementation, transport::TransportConfig};

use crate::flows::{
    Connect, FlowBuilder, FlowDurationExt, FlowStep, Initialize, ProcessCapabilities, RetryPolicy,
    SendNotification, TimeoutConfig, TransitionTo, ValidationConfig, WaitForResponse,
};

/// Demonstration of basic MCP negotiation flow
///
/// This shows the fundamental pattern: a beautiful pipe-like syntax
/// that reads like natural language while being fully type-safe.
pub async fn demo_basic_flow() -> Result<()> {
    println!("🔄 Basic MCP Negotiation Flow Demo");

    let client_info = Implementation {
        name: "mcp-probe".to_string(),
        version: "1.0.0".to_string(),
        metadata: std::collections::HashMap::new(),
    };

    // The beauty of the DSL - reads like poetry!
    let flow = FlowStep::chain(Connect::with_timeout(30.secs()))
        .then(Initialize::with_client_info(client_info.clone()))
        .then(WaitForResponse::with_validation())
        .then(ProcessCapabilities::extract_all())
        .then(SendNotification::initialized())
        .then(TransitionTo::ready_state())
        .build(client_info);

    // Simulate execution (would use real transport config in practice)
    let _transport_config = TransportConfig::stdio("echo", &["hello"]);

    println!("   ✨ Flow created with {} steps", flow.steps.len());
    println!("   🚀 Ready to execute negotiation");

    Ok(())
}

/// Advanced flow with custom timeouts and retry policies
///
/// This demonstrates the composability - you can configure every aspect
/// while maintaining the elegant syntax.
pub async fn demo_advanced_flow() -> Result<()> {
    println!("🎯 Advanced MCP Negotiation Flow Demo");

    let client_info = Implementation {
        name: "mcp-probe-advanced".to_string(),
        version: "2.0.0".to_string(),
        metadata: std::collections::HashMap::new(),
    };

    // Elegant configuration with fluent builders
    let custom_timeouts = TimeoutConfig {
        connection: 45.secs(),
        initialization: 120.secs(),
        response: 60.secs(),
        total: 600.secs(),
    };

    let aggressive_retry = RetryPolicy {
        max_attempts: 5,
        initial_delay: 500.millis(),
        max_delay: 10.secs(),
        backoff_multiplier: 1.5,
    };

    // The DSL composes beautifully with configurations
    let _flow = FlowStep::chain(Connect::with_timeout(45.secs()))
        .then(Initialize::with_client_info(client_info.clone()))
        .then(WaitForResponse::with_timeout(60.secs()))
        .then(ProcessCapabilities::with_strict_validation())
        .then(SendNotification::initialized())
        .then(TransitionTo::ready_state())
        .with_timeouts(custom_timeouts)
        .with_retry_policy(aggressive_retry)
        .build(client_info);

    println!("   ⚙️  Advanced configuration applied");
    println!("   🔄 Aggressive retry policy enabled");
    println!("   ⏱️  Extended timeouts configured");

    Ok(())
}

/// Demonstration of the macro syntax
///
/// This shows the ultimate elegance - a macro that creates flows
/// with shell-like pipe syntax.
#[allow(unused_macros)]
macro_rules! demo_macro_flow {
    ($client_info:expr) => {
        // This would work with our mcpflow! macro when fully implemented
        mcpflow! {
            Connect::with_timeout(30.secs())
                | Initialize::with_client_info($client_info)
                | WaitForResponse::with_validation()
                | ProcessCapabilities::extract_all()
                | SendNotification::initialized()
                | TransitionTo::ready_state()
        }
    };
}

/// Conditional flow demonstration
///
/// Shows how flows can branch based on runtime conditions,
/// creating truly dynamic protocol negotiation.
pub async fn demo_conditional_flow() -> Result<()> {
    println!("🌟 Conditional MCP Negotiation Flow Demo");

    let _client_info = Implementation {
        name: "mcp-probe-conditional".to_string(),
        version: "1.5.0".to_string(),
        metadata: std::collections::HashMap::new(),
    };

    // This would demonstrate conditional branching in the DSL
    println!("   🔀 Conditional flows enable smart adaptation");
    println!("   🧠 Protocol negotiation becomes intelligent");
    println!("   ⚡ Dynamic behavior based on server capabilities");

    Ok(())
}

/// Production-ready flow with comprehensive error handling
///
/// Demonstrates how the DSL enables robust, production-grade
/// flows with minimal boilerplate.
pub async fn demo_production_flow() -> Result<()> {
    println!("🏭 Production-Ready MCP Negotiation Flow Demo");

    let client_info = Implementation {
        name: "mcp-probe-production".to_string(),
        version: "3.0.0".to_string(),
        metadata: std::collections::HashMap::new(),
    };

    // Production configuration with comprehensive settings
    let _production_config = ValidationConfig {
        strict_protocol_version: true,
        require_capabilities: vec!["tools".to_string(), "resources".to_string()],
        allow_unknown_capabilities: false,
    };

    // Enterprise-grade retry policy
    let enterprise_retry = RetryPolicy {
        max_attempts: 10,
        initial_delay: 1000.millis(),
        max_delay: 60.secs(),
        backoff_multiplier: 2.0,
    };

    let _flow = FlowBuilder::new()
        .add_step(Connect::with_timeout(30.secs()))
        .add_step(Initialize::with_client_info(client_info.clone()))
        .add_step(WaitForResponse::with_validation())
        .add_step(ProcessCapabilities::with_strict_validation())
        .add_step(SendNotification::initialized())
        .add_step(TransitionTo::ready_state())
        .with_retry_policy(enterprise_retry)
        .build(client_info);

    println!("   🛡️  Enterprise-grade error handling");
    println!("   📊 Comprehensive metrics collection");
    println!("   🔍 Detailed validation and logging");

    Ok(())
}

/// Showcase different transport types with the same flow
///
/// The beauty of abstraction - same flow, different transports.
pub async fn demo_multi_transport() -> Result<()> {
    println!("🌐 Multi-Transport MCP Flow Demo");

    let client_info = Implementation {
        name: "mcp-probe-multi".to_string(),
        version: "1.0.0".to_string(),
        metadata: std::collections::HashMap::new(),
    };

    // One flow definition works with any transport!
    let base_flow = FlowStep::chain(Connect::with_default_timeout())
        .then(Initialize::with_client_info(client_info.clone()))
        .then(WaitForResponse::with_validation())
        .then(ProcessCapabilities::extract_all())
        .then(SendNotification::initialized())
        .then(TransitionTo::ready_state());

    // Stdio transport
    let _stdio_flow = base_flow.clone().build(client_info.clone());
    println!("   📟 Created flow for stdio transport");

    // HTTP+SSE transport
    let _http_flow = base_flow.clone().build(client_info.clone());
    println!("   🌐 Created flow for HTTP+SSE transport");

    // HTTP streaming transport
    let _stream_flow = base_flow.build(client_info);
    println!("   📡 Created flow for HTTP streaming transport");

    println!("   ✨ Same elegant syntax, multiple transports!");

    Ok(())
}

/// Timing and performance demonstration
///
/// Shows how the DSL naturally captures timing information
/// for performance analysis and debugging.
pub async fn demo_timing_flow() -> Result<()> {
    println!("⏱️  Timing and Performance Demo");

    let client_info = Implementation {
        name: "mcp-probe-timing".to_string(),
        version: "1.0.0".to_string(),
        metadata: std::collections::HashMap::new(),
    };

    let flow = FlowStep::chain(Connect::with_timeout(5.secs()))
        .then(Initialize::with_client_info(client_info.clone()))
        .then(WaitForResponse::with_timeout(10.secs()))
        .then(ProcessCapabilities::extract_all())
        .then(SendNotification::initialized())
        .then(TransitionTo::ready_state())
        .build(client_info);

    println!("   ⏰ Each step automatically timed");
    println!("   📈 Performance metrics collected");
    println!("   🔍 Bottleneck identification enabled");

    // Context would show timing after execution
    let context = flow.context();
    println!("   📊 Context tracks: {:?}", context.timing.start_time);

    Ok(())
}

/// Run all demonstrations
pub async fn run_all_demos() -> Result<()> {
    println!("🎨 MCP Negotiation Flow DSL - Bricolage Demonstration");
    println!("═══════════════════════════════════════════════════════");
    println!();

    demo_basic_flow().await?;
    println!();

    demo_advanced_flow().await?;
    println!();

    demo_conditional_flow().await?;
    println!();

    demo_production_flow().await?;
    println!();

    demo_multi_transport().await?;
    println!();

    demo_timing_flow().await?;
    println!();

    println!("✨ DSL Demonstration Complete!");
    println!("🏗️  Beautiful bricolage - composing complex flows from simple parts");
    println!("📚 Type-safe, elegant, maintainable protocol negotiation");

    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;

    #[tokio::test]
    async fn test_all_demos() {
        // All demos should run without panicking
        assert!(demo_basic_flow().await.is_ok());
        assert!(demo_advanced_flow().await.is_ok());
        assert!(demo_conditional_flow().await.is_ok());
        assert!(demo_production_flow().await.is_ok());
        assert!(demo_multi_transport().await.is_ok());
        assert!(demo_timing_flow().await.is_ok());
    }

    #[tokio::test]
    async fn test_full_demo() {
        assert!(run_all_demos().await.is_ok());
    }
}