use rmcp::model::Tool;
use std::sync::Arc;
use super::AnyToolFactory;
pub fn meta_tool_name(trait_name: &str) -> String {
let snake = trait_name
.replace("::", "__")
.chars()
.enumerate()
.flat_map(|(i, c)| {
if c.is_uppercase() {
let lower = c.to_lowercase().next().unwrap_or(c);
if i == 0 {
vec![lower]
} else {
vec!['_', lower]
}
} else {
vec![c]
}
})
.collect::<String>();
format!("instantiate_{snake}")
}
pub fn make_meta_tool(factory: &dyn AnyToolFactory) -> Tool {
let trait_name = factory.trait_name();
let name = meta_tool_name(trait_name);
let methods = factory.method_names().join(", ");
let description = format!(
"{desc} Call with {{\"prefix\": \"<registered_prefix>\"}} to instantiate tools: {methods}. \
Register a type first with register_type::<T>(prefix) at server startup.",
desc = factory.factory_description(),
);
let schema = serde_json::json!({
"type": "object",
"properties": {
"prefix": {
"type": "string",
"description": "The prefix used in register_type::<T>(prefix) at startup"
}
},
"required": ["prefix"]
});
let schema_obj = match schema {
serde_json::Value::Object(m) => Arc::new(m),
_ => Arc::new(Default::default()),
};
Tool::new(name, description, schema_obj)
}