use elicitation::Elicit;
use elicitation_macros::elicit_tools;
use rmcp::handler::server::wrapper::Json;
use rmcp::model::{ServerCapabilities, ServerInfo};
use rmcp::service::{Peer, RoleServer};
use rmcp::{ErrorData, ServerHandler, tool, tool_router};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
struct RegularResponse {
message: String,
}
struct RegularOnlyServer;
#[tool_router]
impl RegularOnlyServer {
#[tool(description = "Regular tool")]
pub async fn regular(_peer: Peer<RoleServer>) -> Result<Json<RegularResponse>, ErrorData> {
Ok(Json(RegularResponse {
message: "ok".to_string(),
}))
}
}
impl ServerHandler for RegularOnlyServer {
fn get_info(&self) -> ServerInfo {
ServerInfo {
capabilities: ServerCapabilities::builder().enable_tools().build(),
..Default::default()
}
}
}
#[test]
fn test_1_regular_only_baseline() {
let router = RegularOnlyServer::tool_router();
let tools = router.list_all();
println!("Test 1 - Regular only: {} tools", tools.len());
for tool in &tools {
println!(" - {}", tool.name);
}
assert_eq!(tools.len(), 1, "Should have 1 regular tool");
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Elicit)]
struct TestData {
value: String,
}
struct ElicitOnlyServer;
#[elicit_tools(TestData)]
#[tool_router]
impl ElicitOnlyServer {}
impl ServerHandler for ElicitOnlyServer {
fn get_info(&self) -> ServerInfo {
ServerInfo {
capabilities: ServerCapabilities::builder().enable_tools().build(),
..Default::default()
}
}
}
#[test]
fn test_2_elicit_only_works() {
let router = ElicitOnlyServer::tool_router();
let tools = router.list_all();
println!("Test 2 - Elicit only: {} tools", tools.len());
for tool in &tools {
println!(" - {}", tool.name);
}
assert_eq!(tools.len(), 1, "Should have 1 elicit tool");
}
#[test]
fn test_3_tool_attr_functions_exist() {
let data_tool = ElicitOnlyServer::elicit_test_data_tool_attr();
println!("Test 3 - Tool attr functions:");
println!(" - {}", data_tool.name);
assert_eq!(data_tool.name, "elicit_test_data");
}
struct ComposedServer;
#[elicit_tools(TestData)]
#[tool_router]
impl ComposedServer {
#[tool(description = "Regular tool")]
pub async fn regular(_peer: Peer<RoleServer>) -> Result<Json<RegularResponse>, ErrorData> {
Ok(Json(RegularResponse {
message: "ok".to_string(),
}))
}
}
impl ServerHandler for ComposedServer {
fn get_info(&self) -> ServerInfo {
ServerInfo {
capabilities: ServerCapabilities::builder().enable_tools().build(),
..Default::default()
}
}
}
#[test]
fn test_4_composition() {
let router = ComposedServer::tool_router();
let tools = router.list_all();
println!("Test 4 - Composed: {} tools", tools.len());
for tool in &tools {
println!(" - {}", tool.name);
}
assert_eq!(tools.len(), 2, "Should have 1 regular + 1 elicit = 2 tools");
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Elicit)]
struct Config {
name: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Elicit)]
struct User {
username: String,
}
struct MultiToolServer;
#[elicit_tools(Config, User, TestData)]
#[tool_router]
impl MultiToolServer {
#[tool(description = "Get status")]
pub async fn status(_peer: Peer<RoleServer>) -> Result<Json<RegularResponse>, ErrorData> {
Ok(Json(RegularResponse {
message: "running".to_string(),
}))
}
#[tool(description = "Get version")]
pub async fn version(_peer: Peer<RoleServer>) -> Result<Json<RegularResponse>, ErrorData> {
Ok(Json(RegularResponse {
message: "1.0.0".to_string(),
}))
}
}
impl ServerHandler for MultiToolServer {
fn get_info(&self) -> ServerInfo {
ServerInfo {
capabilities: ServerCapabilities::builder().enable_tools().build(),
..Default::default()
}
}
}
#[test]
fn test_5_multiple_tools_each_kind() {
let router = MultiToolServer::tool_router();
let tools = router.list_all();
println!("Test 5 - Multiple of each: {} tools", tools.len());
for tool in &tools {
println!(" - {}", tool.name);
}
assert_eq!(tools.len(), 5, "Should have 2 regular + 3 elicit = 5 tools");
let names: Vec<String> = tools.iter().map(|t| t.name.to_string()).collect();
assert!(names.contains(&"status".to_string()));
assert!(names.contains(&"version".to_string()));
assert!(names.contains(&"elicit_config".to_string()));
assert!(names.contains(&"elicit_user".to_string()));
assert!(names.contains(&"elicit_test_data".to_string()));
}