use std::sync::Arc;
use cloudllm::clients::openai::{Model, OpenAIClient};
use cloudllm::tool_protocol::ToolRegistry;
use cloudllm::tool_protocols::McpClientProtocol;
use cloudllm::Agent;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
cloudllm::init_logger();
println!("=== Multi-MCP Agent Example ===\n");
println!("Step 1: Creating OpenAI client...");
let api_key = std::env::var("OPEN_AI_SECRET")?;
let client = Arc::new(OpenAIClient::new_with_model_enum(
&api_key,
Model::GPT41Nano,
));
println!("\nStep 2: Creating multi-protocol ToolRegistry...");
let mut registry = ToolRegistry::empty();
println!("Step 3: Registering MCP server protocols...\n");
println!(" - Adding local MCP server (http://localhost:8080)");
println!(" Expected tools: memory, bash");
let local_protocol = Arc::new(McpClientProtocol::new("http://localhost:8080".to_string()));
match registry.add_protocol("local", local_protocol).await {
Ok(_) => println!(" ✓ Local server connected"),
Err(e) => println!(" ⚠ Could not connect to local server: {}", e),
}
println!("\n - Adding remote YouTube MCP server (http://youtube-mcp.example.com:8081)");
println!(" Expected tools: youtube_search, youtube_get_transcript");
let youtube_protocol = Arc::new(McpClientProtocol::new(
"http://youtube-mcp.example.com:8081".to_string(),
));
match registry.add_protocol("youtube", youtube_protocol).await {
Ok(_) => println!(" ✓ YouTube server connected"),
Err(e) => println!(" ⚠ Could not connect to YouTube server: {}", e),
}
println!("\n - Adding remote GitHub MCP server (http://github-mcp.example.com:8082)");
println!(" Expected tools: github_search_repos, github_get_issues");
let github_protocol = Arc::new(McpClientProtocol::new(
"http://github-mcp.example.com:8082".to_string(),
));
match registry.add_protocol("github", github_protocol).await {
Ok(_) => println!(" ✓ GitHub server connected"),
Err(e) => println!(" ⚠ Could not connect to GitHub server: {}", e),
}
println!("\nStep 4: Listing available tools from all protocols...");
let tools = registry.list_tools();
if tools.is_empty() {
println!(" No tools available (MCP servers may not be running)");
println!("\n To test this example, you would need to:");
println!(" 1. Start the local MCP server: cargo run --example mcp_server_local");
println!(" 2. Update the YouTube and GitHub server URLs to valid endpoints");
} else {
println!(" Available tools:");
for tool_meta in tools {
println!(" - {} ({})", tool_meta.name, tool_meta.description);
if let Some(protocol) = registry.get_tool_protocol(&tool_meta.name) {
println!(" [from: {}]", protocol);
}
}
}
println!("\nStep 5: Registered protocols:");
for protocol_name in registry.list_protocols() {
println!(" - {}", protocol_name);
}
println!("\nStep 6: Creating agent with access to all tools...");
let _agent = Agent::new("research-agent", "Research Agent", client)
.with_expertise("Finding information using multiple sources")
.with_personality("Curious and methodical")
.with_tools(Arc::new(registry));
println!("\n=== Agent Capabilities ===\n");
println!("The agent now has access to tools from multiple MCP servers:");
println!();
println!("From 'local' MCP server:");
println!(" - Use 'memory' to store/retrieve research notes");
println!(" - Use 'bash' to process data locally");
println!();
println!("From 'youtube' MCP server:");
println!(" - Use 'youtube_search' to find videos");
println!(" - Use 'youtube_get_transcript' to get video transcripts");
println!();
println!("From 'github' MCP server:");
println!(" - Use 'github_search_repos' to find repositories");
println!(" - Use 'github_get_issues' to retrieve issues");
println!("\n=== Example Workflow ===\n");
println!("Agent instruction: \"Search GitHub for Rust projects and summarize top issues\"\n");
println!("The agent would then:");
println!(" 1. Call 'github_search_repos' (routed to 'github' server)");
println!(" 2. Retrieve repo details and call 'github_get_issues'");
println!(" 3. Process results and store summary in 'memory' tool (routed to 'local' server)");
println!(" 4. Return findings to the user");
println!("\n=== How Tool Routing Works ===\n");
println!("When the agent calls a tool:");
println!(" 1. Agent calls registry.execute_tool(tool_name, params)");
println!(" 2. Registry looks up which protocol owns this tool");
println!(" 3. Registry forwards execute() to the correct MCP server");
println!(" 4. Result is returned to agent transparently");
println!("\nThis allows agents to seamlessly orchestrate across multiple sources!");
Ok(())
}