#![allow(
clippy::expect_used,
clippy::panic,
clippy::indexing_slicing,
clippy::missing_errors_doc,
clippy::missing_panics_doc,
dead_code
)]
use loopctl::mcp::{McpClient, McpToolProvider};
use loopctl::tool::{ToolContext, ToolRegistry};
use rmcp::handler::server::ServerHandler;
use rmcp::handler::server::router::tool::ToolRouter;
use rmcp::{tool, tool_handler, tool_router};
use serde_json::json;
#[derive(Clone)]
struct GreetServer {
router: ToolRouter<Self>,
}
#[tool_router]
impl GreetServer {
fn new() -> Self {
Self {
router: Self::tool_router(),
}
}
#[tool(description = "Return a friendly greeting")]
async fn greet(&self) -> String {
"hello, world!".to_string()
}
}
#[allow(clippy::unused_async_trait_impl)] #[tool_handler]
impl ServerHandler for GreetServer {}
#[tokio::main]
async fn main() {
let client = McpClient::in_process(GreetServer::new())
.await
.expect("client initialize");
let provider = McpToolProvider::connect(client, None)
.await
.expect("connect + list_tools");
let mut registry = ToolRegistry::new();
provider.register_into(&mut registry);
println!("discovered {} tool(s):", registry.len());
for schema in registry.all_schemas() {
println!(" - {} : {}", schema.tool, schema.description);
}
let greet = registry.get("greet").expect("greet registered");
let ctx = ToolContext::default();
let out = greet.call(json!({}), &ctx).await.expect("greet call");
println!("greet -> {}", out.text_content());
assert!(!out.is_error);
assert_eq!(out.text_content(), "hello, world!");
println!("OK");
}