From 397f893bfc50e6fffe6943f8f8f2aca6a2bea841 Mon Sep 17 00:00:00 2001 From: Devid HW Date: Sun, 19 Apr 2026 05:58:16 +0700 Subject: [PATCH] feat: Auto-verify setup on first initialization - Add auto_verify_result field to McpServer - Run verify_setup automatically during initialize - Include setup status in serverInfo response: - verified: bool - hint: string message - Users immediately see if environment is ready --- src/mcp_server.rs | 84 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 74 insertions(+), 10 deletions(-) diff --git a/src/mcp_server.rs b/src/mcp_server.rs index c26f5cb..dd5df72 100644 --- a/src/mcp_server.rs +++ b/src/mcp_server.rs @@ -4,10 +4,19 @@ use tokio::sync::Mutex; use crate::{models::Config as ModelsConfig, tools::ToolHandler, McpError, McpRequest, McpResponse}; +/// Auto-verify result stored after first initialization +#[derive(Debug, Clone)] +struct AutoVerifyResult { + all_ok: bool, + hint: String, + config_path: String, +} + #[derive(Debug)] pub struct McpServer { initialized: Arc>, tool_handler: Arc, + auto_verify_result: Arc>>, } impl McpServer { @@ -16,6 +25,45 @@ impl McpServer { Self { initialized: Arc::new(Mutex::new(false)), tool_handler: Arc::new(ToolHandler::new(config)), + auto_verify_result: Arc::new(Mutex::new(None)), + } + } + + /// Run verify_setup on initialization and return summary + async fn run_auto_verify(&self) -> AutoVerifyResult { + // Get config from tool_handler + let config = ModelsConfig::load().unwrap_or_default(); + + // Check if config exists + let config_path = ModelsConfig::writable_config_path(); + let config_exists = config_path.exists(); + + // Check wine and terminal + let wine_ok = config.wine_executable.as_ref() + .map(|p| std::path::Path::new(p).exists()) + .unwrap_or(false); + let term_ok = config.terminal_dir.as_ref() + .map(|p| std::path::Path::new(p).is_dir()) + .unwrap_or(false); + + let all_ok = config_exists && wine_ok && term_ok; + + let hint = if all_ok { + "Environment fully configured and ready".to_string() + } else if !config_exists { + format!("Auto-discovery will run on first request. Config will be written to {}", config_path.display()) + } else if !wine_ok { + "Wine/CrossOver not found - required for MT5 execution".to_string() + } else if !term_ok { + "MT5 directory not found - check installation".to_string() + } else { + "Fix missing paths in config".to_string() + }; + + AutoVerifyResult { + all_ok, + hint, + config_path: config_path.to_string_lossy().to_string(), } } @@ -35,22 +83,38 @@ impl McpServer { "2024-11-05" }; + // Run auto-verify on first initialization + let verify_result = self.run_auto_verify().await; + let all_ok = verify_result.all_ok; + let hint = verify_result.hint.clone(); + + // Store the result + *self.auto_verify_result.lock().await = Some(verify_result); + *self.initialized.lock().await = true; + + // Include verify status in server info + let server_info = json!({ + "name": "MT5-Quant", + "version": "1.27.0", + "setup": { + "verified": all_ok, + "hint": hint, + } + }); + McpResponse { jsonrpc: "2.0".to_string(), id: request.id, - result: Some(json!(crate::InitializeResult { - protocol_version: negotiated_version.to_string(), - capabilities: crate::ServerCapabilities { - experimental: json!({}), - tools: crate::ToolCapabilities { - list_changed: false, + result: Some(json!({ + "protocolVersion": negotiated_version, + "capabilities": { + "experimental": {}, + "tools": { + "listChanged": false, }, }, - server_info: crate::ServerInfo { - name: "MT5-Quant".to_string(), - version: "1.27.0".to_string(), - }, + "serverInfo": server_info, })), error: None, }