use enki_runtime::mcp::{McpClient, McpTransport};
use serde_json::json;
use std::path::PathBuf;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
println!("=== MCP Client Example ===\n");
println!("Connecting to Enki Calculator MCP Server...\n");
let server_path = find_mcp_server_binary();
println!("Using server binary: {}\n", server_path.display());
let transport = McpTransport::stdio(server_path.to_string_lossy().to_string(), vec![]);
match McpClient::connect(transport).await {
Ok(client) => {
println!("✓ Connected to Enki MCP Server!\n");
let tools = client.tools();
println!("Available tools ({}):", tools.len());
for tool in tools {
println!(
" - {}: {}",
tool.name,
tool.description.as_deref().unwrap_or("No description")
);
}
println!("\n--- Testing Calculator Tools ---\n");
println!("Calling add(10, 5)...");
match client.call_tool("add", json!({"a": 10, "b": 5})).await {
Ok(result) => println!(" Result: {}\n", result),
Err(e) => println!(" Error: {}\n", e),
}
println!("Calling subtract(20, 8)...");
match client.call_tool("subtract", json!({"a": 20, "b": 8})).await {
Ok(result) => println!(" Result: {}\n", result),
Err(e) => println!(" Error: {}\n", e),
}
println!("Calling multiply(7, 6)...");
match client.call_tool("multiply", json!({"a": 7, "b": 6})).await {
Ok(result) => println!(" Result: {}\n", result),
Err(e) => println!(" Error: {}\n", e),
}
println!("--- All tests complete! ---\n");
println!("Disconnecting...");
if let Err(e) = client.disconnect().await {
println!("Disconnect warning: {}", e);
}
}
Err(e) => {
println!("✗ Failed to connect to MCP server: {}\n", e);
println!("Make sure you have built the mcp_server example first:");
println!(" cargo build --example mcp_server --features mcp");
println!("\nExpected binary at: {}", server_path.display());
}
}
println!("\n=== Example Complete ===");
Ok(())
}
fn find_mcp_server_binary() -> PathBuf {
let exe_name = if cfg!(windows) {
"mcp_server.exe"
} else {
"mcp_server"
};
let candidates = vec![
PathBuf::from("target/debug/examples").join(exe_name),
PathBuf::from("../target/debug/examples").join(exe_name),
PathBuf::from("../../target/debug/examples").join(exe_name),
std::env::var("CARGO_MANIFEST_DIR")
.map(|dir| {
PathBuf::from(dir)
.join("../target/debug/examples")
.join(exe_name)
})
.unwrap_or_default(),
];
for path in candidates {
if path.exists() {
return path.canonicalize().unwrap_or(path);
}
}
PathBuf::from("target/debug/examples").join(exe_name)
}