Skip to main content

pmcp_server/tools/
test_generate.rs

1//! Test scenario generation tool.
2//!
3//! Wraps `mcp_tester::ScenarioGenerator::create_scenario_struct()` to let
4//! users generate test scenarios from a live MCP server's capabilities.
5
6use async_trait::async_trait;
7use mcp_tester::ScenarioGenerator;
8use pmcp::types::ToolInfo;
9use pmcp::ToolHandler;
10use serde::Deserialize;
11use serde_json::{json, Value};
12
13use super::{create_tester, default_timeout, internal_err};
14
15/// Input parameters for the `test_generate` tool.
16#[derive(Deserialize)]
17struct TestGenerateInput {
18    /// MCP server URL to discover capabilities from.
19    url: String,
20    /// Timeout in seconds (default: 30).
21    #[serde(default = "default_timeout")]
22    timeout: u64,
23    /// Include all discovered tools in the scenario.
24    #[serde(default = "default_true")]
25    all_tools: bool,
26    /// Include resource testing in the scenario.
27    #[serde(default)]
28    with_resources: bool,
29    /// Include prompt testing in the scenario.
30    #[serde(default)]
31    with_prompts: bool,
32}
33
34const fn default_true() -> bool {
35    true
36}
37
38/// Test scenario generation tool.
39///
40/// Connects to a remote MCP server, discovers its tools, resources, and
41/// prompts, then generates a structured test scenario as JSON.
42pub struct TestGenerateTool;
43
44#[async_trait]
45impl ToolHandler for TestGenerateTool {
46    async fn handle(&self, args: Value, _extra: pmcp::RequestHandlerExtra) -> pmcp::Result<Value> {
47        let params: TestGenerateInput = serde_json::from_value(args)
48            .map_err(|e| pmcp::Error::validation(format!("Invalid arguments: {e}")))?;
49
50        let mut tester = create_tester(&params.url, params.timeout)?;
51
52        let generator = ScenarioGenerator::new(
53            params.url,
54            params.all_tools,
55            params.with_resources,
56            params.with_prompts,
57        );
58
59        let scenario = generator
60            .create_scenario_struct(&mut tester)
61            .await
62            .map_err(internal_err)?;
63
64        serde_json::to_value(&scenario).map_err(internal_err)
65    }
66
67    fn metadata(&self) -> Option<ToolInfo> {
68        Some(ToolInfo::new(
69            "test_generate",
70            Some("Generate test scenarios from a remote MCP server's capabilities".to_string()),
71            json!({
72                "type": "object",
73                "properties": {
74                    "url": {
75                        "type": "string",
76                        "description": "MCP server URL to discover capabilities from"
77                    },
78                    "timeout": {
79                        "type": "integer",
80                        "description": "Timeout in seconds",
81                        "default": 30
82                    },
83                    "all_tools": {
84                        "type": "boolean",
85                        "description": "Include all discovered tools in the scenario",
86                        "default": true
87                    },
88                    "with_resources": {
89                        "type": "boolean",
90                        "description": "Include resource testing in the scenario",
91                        "default": false
92                    },
93                    "with_prompts": {
94                        "type": "boolean",
95                        "description": "Include prompt testing in the scenario",
96                        "default": false
97                    }
98                },
99                "required": ["url"]
100            }),
101        ))
102    }
103}