use async_trait::async_trait;
use mcp_tester::ScenarioGenerator;
use pmcp::types::ToolInfo;
use pmcp::ToolHandler;
use serde::Deserialize;
use serde_json::{json, Value};
use super::{create_tester, default_timeout, internal_err};
#[derive(Deserialize)]
struct TestGenerateInput {
url: String,
#[serde(default = "default_timeout")]
timeout: u64,
#[serde(default = "default_true")]
all_tools: bool,
#[serde(default)]
with_resources: bool,
#[serde(default)]
with_prompts: bool,
}
const fn default_true() -> bool {
true
}
pub struct TestGenerateTool;
#[async_trait]
impl ToolHandler for TestGenerateTool {
async fn handle(&self, args: Value, _extra: pmcp::RequestHandlerExtra) -> pmcp::Result<Value> {
let params: TestGenerateInput = serde_json::from_value(args)
.map_err(|e| pmcp::Error::validation(format!("Invalid arguments: {e}")))?;
let mut tester = create_tester(¶ms.url, params.timeout)?;
let generator = ScenarioGenerator::new(
params.url,
params.all_tools,
params.with_resources,
params.with_prompts,
);
let scenario = generator
.create_scenario_struct(&mut tester)
.await
.map_err(internal_err)?;
serde_json::to_value(&scenario).map_err(internal_err)
}
fn metadata(&self) -> Option<ToolInfo> {
Some(ToolInfo::new(
"test_generate",
Some("Generate test scenarios from a remote MCP server's capabilities".to_string()),
json!({
"type": "object",
"properties": {
"url": {
"type": "string",
"description": "MCP server URL to discover capabilities from"
},
"timeout": {
"type": "integer",
"description": "Timeout in seconds",
"default": 30
},
"all_tools": {
"type": "boolean",
"description": "Include all discovered tools in the scenario",
"default": true
},
"with_resources": {
"type": "boolean",
"description": "Include resource testing in the scenario",
"default": false
},
"with_prompts": {
"type": "boolean",
"description": "Include prompt testing in the scenario",
"default": false
}
},
"required": ["url"]
}),
))
}
}