use rust_agent::{McpServer, Tool};
use std::sync::Arc;
use anyhow::Error;
use std::pin::Pin;
pub struct WeatherTool {
name: String,
description: String,
}
impl WeatherTool {
pub fn new() -> Self {
Self {
name: "get_weather".to_string(),
description: "Get the weather information for a specified city. For example: 'What's the weather like in Beijing?'".to_string(),
}
}
}
impl Tool for WeatherTool {
fn name(&self) -> &str {
&self.name
}
fn description(&self) -> &str {
&self.description
}
fn invoke(&self, input: &str) -> Pin<Box<dyn std::future::Future<Output = Result<String, Error>> + Send + '_>> {
let city = match serde_json::from_str::<serde_json::Value>(input) {
Ok(json_value) => {
if let Some(city_value) = json_value.get("city") {
city_value.as_str().unwrap_or(input).to_string()
} else {
input.to_string()
}
},
Err(_) => {
input.to_string()
}
};
Box::pin(async move {
let weather_data = match city.to_lowercase().as_str() {
"beijing" => "Sunny, 25°C",
"shanghai" => "Cloudy, 22°C",
"guangzhou" => "Rainy, 28°C",
_ => "Weather data not available",
};
Ok(format!("Weather in {}: {}", city, weather_data))
})
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
pub struct CalculatorTool {
name: String,
description: String,
}
impl CalculatorTool {
pub fn new() -> Self {
Self {
name: "simple_calculate".to_string(),
description: "Perform simple mathematical calculations. Input should be a mathematical expression with numbers and operators (+, -, *, /). For example: '15.5 + 24.3'".to_string(),
}
}
}
impl Tool for CalculatorTool {
fn name(&self) -> &str {
&self.name
}
fn description(&self) -> &str {
&self.description
}
fn invoke(&self, input: &str) -> Pin<Box<dyn std::future::Future<Output = Result<String, Error>> + Send + '_>> {
let expression = match serde_json::from_str::<serde_json::Value>(input) {
Ok(json_value) => {
if let Some(expr_value) = json_value.get("expression") {
expr_value.as_str().unwrap_or(input).to_string()
} else {
input.to_string()
}
},
Err(_) => {
input.to_string()
}
};
Box::pin(async move {
let expression = expression.replace(" ", "");
for op_char in ["+", "-", "*", "/"].iter() {
if let Some(pos) = expression.find(op_char) {
if *op_char == "-" && pos == 0 {
if let Some(next_pos) = expression[1..].find("-") {
let actual_pos = next_pos + 1;
let left_str = &expression[0..actual_pos];
let right_str = &expression[actual_pos + 1..];
if let (Ok(left), Ok(right)) = (left_str.parse::<f64>(), right_str.parse::<f64>()) {
let result = left - right;
return Ok(format!("Result: {} (from {} - {})", result, left, right));
} else {
return Ok(format!("Calculation error: Invalid numbers for subtraction"));
}
} else {
if let Ok(num) = expression.parse::<f64>() {
return Ok(format!("Result: {}", num));
} else {
return Ok(format!("Calculation error: Invalid number"));
}
}
}
let left_str = &expression[0..pos];
let right_str = &expression[pos + 1..];
let left_result = left_str.parse::<f64>();
let right_result = right_str.parse::<f64>();
match (left_result, right_result) {
(Ok(left), Ok(right)) => {
let result = match *op_char {
"+" => left + right,
"-" => left - right,
"*" => left * right,
"/" => {
if right == 0.0 {
return Ok(format!("Calculation error: Division by zero"));
}
left / right
},
_ => unreachable!()
};
return Ok(format!("Result: {} (from {} {} {})", result, left, op_char, right));
},
_ => {
continue;
}
}
}
}
if let Ok(number) = expression.parse::<f64>() {
return Ok(format!("Result: {}", number));
}
Ok(format!("Calculation error: Failed to parse expression: {}", expression))
})
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== Rust Agent Complete MCP Server Example ===");
let server = rust_agent::SimpleMcpServer::new().with_address("127.0.0.1:6000".to_string());
let weather_tool = WeatherTool::new();
let calculator_tool = CalculatorTool::new();
server.register_tool(Arc::new(weather_tool))?;
server.register_tool(Arc::new(calculator_tool))?;
server.start("127.0.0.1:6000").await?;
println!("MCP服务器已启动,地址: 127.0.0.1:6000");
println!("MCP Server端工具:");
println!(" 1. get_weather: Get the weather information for a specified city. For example: 'What's the weather like in Beijing?'");
println!(" 2. simple_calculate: Perform simple mathematical calculations. Input should be a mathematical expression with numbers and operators (+, -, *, /). For example: '15.5 + 24.3'");
println!("服务器正在运行中,按 Ctrl+C 停止服务器");
#[cfg(unix)]
let terminate = async {
tokio::signal::unix::signal(tokio::signal::unix::SignalKind::terminate())
.unwrap()
.recv()
.await;
};
#[cfg(not(unix))]
let terminate = std::future::pending::<()>();
tokio::select! {
_ = tokio::signal::ctrl_c() => {
println!("收到 Ctrl+C 信号,正在停止服务器...");
},
_ = terminate => {
println!("收到终止信号,正在停止服务器...");
},
}
println!("MCP服务器已停止");
Ok(())
}