Files
mt5-quant/src/mcp_server.rs
T

144 lines
5.3 KiB
Rust
Raw Normal View History

2026-04-18 13:41:36 +07:00
use serde_json::{json, Value};
use std::sync::Arc;
use tokio::sync::Mutex;
use crate::{models::Config as ModelsConfig, tools::ToolHandler, McpError, McpRequest, McpResponse};
2026-04-18 13:41:36 +07:00
#[derive(Debug)]
pub struct McpServer {
initialized: Arc<Mutex<bool>>,
tool_handler: Arc<ToolHandler>,
2026-04-18 13:41:36 +07:00
}
impl McpServer {
pub fn new() -> Self {
let config = ModelsConfig::load().unwrap_or_default();
2026-04-18 13:41:36 +07:00
Self {
initialized: Arc::new(Mutex::new(false)),
tool_handler: Arc::new(ToolHandler::new(config)),
2026-04-18 13:41:36 +07:00
}
}
pub async fn handle_request(&self, request: McpRequest) -> McpResponse {
match request.method.as_str() {
"initialize" => {
*self.initialized.lock().await = true;
McpResponse {
jsonrpc: "2.0".to_string(),
id: request.id,
result: Some(json!(crate::InitializeResult {
protocol_version: "2024-11-05".to_string(),
capabilities: crate::ServerCapabilities {
experimental: json!({}),
tools: crate::ToolCapabilities {
list_changed: false,
},
},
server_info: crate::ServerInfo {
name: "MT5-Quant".to_string(),
version: "1.27.0".to_string(),
},
})),
error: None,
}
}
"tools/list" => {
let initialized = *self.initialized.lock().await;
if !initialized {
return McpResponse {
jsonrpc: "2.0".to_string(),
id: request.id,
result: None,
error: Some(McpError {
code: -32600,
message: "Received request before initialization was complete".to_string(),
data: None,
}),
};
}
McpResponse {
jsonrpc: "2.0".to_string(),
id: request.id,
result: Some(crate::tools::get_tools_list()),
2026-04-18 13:41:36 +07:00
error: None,
}
}
"tools/call" => {
let initialized = *self.initialized.lock().await;
if !initialized {
return McpResponse {
jsonrpc: "2.0".to_string(),
id: request.id,
result: None,
error: Some(McpError {
code: -32600,
message: "Received request before initialization was complete".to_string(),
data: None,
}),
};
}
if let Some(params) = request.params {
if let (Some(tool_name), Some(arguments)) = (
params.get("name").and_then(|v| v.as_str()),
params.get("arguments")
) {
let result = self.handle_tool_call(tool_name, arguments).await;
McpResponse {
jsonrpc: "2.0".to_string(),
id: request.id,
result: Some(result),
error: None,
}
} else {
McpResponse {
jsonrpc: "2.0".to_string(),
id: request.id,
result: None,
error: Some(McpError {
code: -32602,
message: "Invalid request parameters".to_string(),
data: None,
}),
}
}
} else {
McpResponse {
jsonrpc: "2.0".to_string(),
id: request.id,
result: None,
error: Some(McpError {
code: -32602,
message: "Invalid request parameters".to_string(),
data: None,
}),
}
}
}
_ => {
McpResponse {
jsonrpc: "2.0".to_string(),
id: request.id,
result: None,
error: Some(McpError {
code: -32601,
message: format!("Method not found: {}", request.method),
data: None,
}),
}
}
}
}
async fn handle_tool_call(&self, tool_name: &str, arguments: &Value) -> Value {
self.tool_handler.handle(tool_name, arguments).await.unwrap_or_else(|e| json!({
"content": [{
"type": "text",
"text": format!("Tool execution failed: {}", e)
}],
"isError": true
}))
2026-04-18 13:41:36 +07:00
}
}