Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 94eb8927fd | |||
| 2104fabe50 | |||
| 51f19640c3 | |||
| 1ec0adb6e6 | |||
| 397f893bfc |
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"json.schemas": [
|
||||
{
|
||||
"fileMatch": ["server.json"],
|
||||
"url": "https://raw.githubusercontent.com/modelcontextprotocol/specification/main/schema/2024-11-05/schema.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -10,7 +10,7 @@ PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
VERSION=$(grep -E '^version = ' Cargo.toml | head -1 | sed 's/version = "\(.*\)"/\1/')
|
||||
echo "=== Building MT5-Quant v${VERSION} ==="
|
||||
echo "=== Building MCP-MT5-Quant v${VERSION} ==="
|
||||
echo ""
|
||||
|
||||
# Clean previous builds
|
||||
@@ -19,7 +19,7 @@ mkdir -p "$PROJECT_ROOT/dist"
|
||||
|
||||
# Build current platform
|
||||
echo "Building for current platform..."
|
||||
cargo build --release
|
||||
RUSTFLAGS="-D warnings" cargo build --release
|
||||
|
||||
# Detect platform
|
||||
UNAME=$(uname -s)
|
||||
@@ -33,7 +33,7 @@ else
|
||||
PLATFORM="unknown"
|
||||
fi
|
||||
|
||||
PACKAGE_NAME="mt5-quant-${PLATFORM}"
|
||||
PACKAGE_NAME="mcp-mt5-quant-${PLATFORM}"
|
||||
PACKAGE_DIR="$PROJECT_ROOT/dist/${PACKAGE_NAME}"
|
||||
|
||||
echo "Packaging for ${PLATFORM}..."
|
||||
@@ -48,7 +48,7 @@ cp "$PROJECT_ROOT/config/mt5-quant.example.yaml" "$PACKAGE_DIR/config/"
|
||||
|
||||
# Copy docs
|
||||
cp "$PROJECT_ROOT/README.md" "$PACKAGE_DIR/"
|
||||
cp "$PROJECT_ROOT/WINDSURF_SETUP.md" "$PACKAGE_DIR/"
|
||||
cp "$PROJECT_ROOT/docs/WINDSURF.md" "$PACKAGE_DIR/WINDSURF_SETUP.md"
|
||||
cp "$PROJECT_ROOT/CLAUDE.md" "$PACKAGE_DIR/"
|
||||
|
||||
# Create tarball
|
||||
@@ -59,6 +59,7 @@ echo ""
|
||||
echo "=== Build Complete ==="
|
||||
echo ""
|
||||
echo "Package: dist/${PACKAGE_NAME}.tar.gz"
|
||||
echo "Binary: mt5-quant"
|
||||
echo "Size: $(du -h "${PACKAGE_NAME}.tar.gz" | cut -f1)"
|
||||
echo ""
|
||||
echo "Contents:"
|
||||
@@ -67,4 +68,5 @@ echo ""
|
||||
echo "To install:"
|
||||
echo " tar -xzf ${PACKAGE_NAME}.tar.gz"
|
||||
echo " cd ${PACKAGE_NAME}"
|
||||
echo " ./mt5-quant --help"
|
||||
echo " sudo cp mt5-quant /usr/local/bin/"
|
||||
echo " mt5-quant --help"
|
||||
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
||||
"$schema": "https://raw.githubusercontent.com/modelcontextprotocol/specification/main/schema/2024-11-05/schema.json",
|
||||
"name": "io.github.masdevid/mt5-quant",
|
||||
"title": "MT5-Quant",
|
||||
"description": "MCP server for MetaTrader 5 strategy development on macOS/Linux. 43 tools to compile MQL5 Expert Advisors, run backtests, analyze deals, and optimize parameters — no Windows required.",
|
||||
"description": "MCP server for MT5 strategy development. Compile, backtest, analyze MQL5 EAs on macOS/Linux.",
|
||||
"repository": {
|
||||
"url": "https://github.com/masdevid/mt5-quant",
|
||||
"source": "github"
|
||||
@@ -11,7 +11,7 @@
|
||||
"packages": [
|
||||
{
|
||||
"registryType": "mcpb",
|
||||
"identifier": "https://github.com/masdevid/mt5-quant/releases/download/v1.0.0/mt5-quant-macos-arm64.tar.gz",
|
||||
"identifier": "https://github.com/masdevid/mt5-quant/releases/download/v1.0.0/mcp-mt5-quant-macos-arm64.tar.gz",
|
||||
"fileSha256": "5d647e44efa32ab9a1b8e16139a3a0e4a58408ce5993cc0bf14d551184124fbb",
|
||||
"transport": {
|
||||
"type": "stdio"
|
||||
|
||||
+101
-10
@@ -4,10 +4,20 @@ 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)]
|
||||
#[allow(dead_code)]
|
||||
struct AutoVerifyResult {
|
||||
all_ok: bool,
|
||||
hint: String,
|
||||
config_path: String,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct McpServer {
|
||||
initialized: Arc<Mutex<bool>>,
|
||||
tool_handler: Arc<ToolHandler>,
|
||||
auto_verify_result: Arc<Mutex<Option<AutoVerifyResult>>>,
|
||||
}
|
||||
|
||||
impl McpServer {
|
||||
@@ -16,6 +26,76 @@ 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 in background - non blocking
|
||||
fn spawn_auto_verify(&self) {
|
||||
let result_arc = self.auto_verify_result.clone();
|
||||
|
||||
tokio::spawn(async move {
|
||||
// Get config
|
||||
let config = ModelsConfig::load().unwrap_or_default();
|
||||
let config_path = ModelsConfig::writable_config_path();
|
||||
|
||||
// Quick async file checks
|
||||
let config_exists = tokio::task::spawn_blocking({
|
||||
let path = config_path.clone();
|
||||
move || path.exists()
|
||||
}).await.unwrap_or(false);
|
||||
|
||||
let wine_ok = if let Some(wine) = &config.wine_executable {
|
||||
let wine = wine.clone();
|
||||
tokio::task::spawn_blocking(move || {
|
||||
std::path::Path::new(&wine).exists()
|
||||
}).await.unwrap_or(false)
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
let term_ok = if let Some(term) = &config.terminal_dir {
|
||||
let term = term.clone();
|
||||
tokio::task::spawn_blocking(move || {
|
||||
std::path::Path::new(&term).is_dir()
|
||||
}).await.unwrap_or(false)
|
||||
} else {
|
||||
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()
|
||||
};
|
||||
|
||||
let result = AutoVerifyResult {
|
||||
all_ok,
|
||||
hint,
|
||||
config_path: config_path.to_string_lossy().to_string(),
|
||||
};
|
||||
|
||||
// Store result
|
||||
let mut guard = result_arc.lock().await;
|
||||
*guard = Some(result);
|
||||
});
|
||||
}
|
||||
|
||||
/// Get current verify status (may be loading if called immediately after init)
|
||||
#[allow(dead_code)]
|
||||
async fn get_verify_status(&self) -> (Option<bool>, String) {
|
||||
let guard = self.auto_verify_result.lock().await;
|
||||
match guard.as_ref() {
|
||||
Some(result) => (Some(result.all_ok), result.hint.clone()),
|
||||
None => (None, "Checking environment...".to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,22 +115,33 @@ impl McpServer {
|
||||
"2024-11-05"
|
||||
};
|
||||
|
||||
// Start background verify (non-blocking)
|
||||
self.spawn_auto_verify();
|
||||
|
||||
*self.initialized.lock().await = true;
|
||||
|
||||
// Return immediately with fast status
|
||||
let server_info = json!({
|
||||
"name": "MT5-Quant",
|
||||
"version": "1.27.0",
|
||||
"setup": {
|
||||
"verified": null, // null = checking
|
||||
"hint": "Auto-verification running... Use verify_setup tool for detailed status",
|
||||
}
|
||||
});
|
||||
|
||||
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,
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use anyhow::Result;
|
||||
use serde_json::{json, Value};
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use crate::compile::MqlCompiler;
|
||||
use crate::models::Config;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use anyhow::Result;
|
||||
use serde_json::{json, Value};
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use crate::models::Config;
|
||||
|
||||
pub async fn handle_read_set_file(args: &Value) -> Result<Value> {
|
||||
|
||||
Reference in New Issue
Block a user