#![expect(
clippy::doc_markdown,
reason = "AgentCat is the name of the product, not code"
)]
#![expect(
clippy::unused_async_trait_impl,
reason = "the methods #[tool_handler] generates are async without an await"
)]
use agentcat_sdk::{AgentCat, Options};
use rmcp::handler::server::wrapper::Parameters;
use rmcp::model::{Implementation, InitializeResult, ServerCapabilities};
use rmcp::transport::stdio;
use rmcp::{ServerHandler, ServiceExt, tool, tool_handler, tool_router};
use schemars::JsonSchema;
use serde::Deserialize;
#[derive(Deserialize, JsonSchema)]
struct AddArgs {
a: f64,
b: f64,
}
#[derive(Deserialize, JsonSchema)]
struct EchoArgs {
text: String,
}
#[derive(Clone)]
struct Demo;
#[tool_router]
impl Demo {
#[tool(description = "Adds two numbers")]
async fn add(&self, Parameters(args): Parameters<AddArgs>) -> String {
(args.a + args.b).to_string()
}
#[tool(description = "Sends the text back")]
async fn echo(&self, Parameters(args): Parameters<EchoArgs>) -> String {
args.text
}
}
#[tool_handler]
impl ServerHandler for Demo {
fn get_info(&self) -> InitializeResult {
InitializeResult::new(ServerCapabilities::builder().enable_tools().build())
.with_server_info(Implementation::new("agentcat-example-stdio", "1.0.0"))
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let server = AgentCat::from_env(Options::default()).track(Demo);
let running = server.serve(stdio()).await?;
running.waiting().await?;
Ok(())
}