Skip to content

Commit 186ffbc

Browse files
committed
fix doc
Signed-off-by: Yuchen Zhang <[email protected]>
1 parent 499a0a9 commit 186ffbc

File tree

4 files changed

+20
-93
lines changed

4 files changed

+20
-93
lines changed

src/nat/front_ends/mcp/load_test_utils/cli.py

Lines changed: 2 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,6 @@
1616
"""MCP Load Test Entry Point Script.
1717
1818
Run load tests against MCP servers using YAML configuration files.
19-
20-
Usage:
21-
python cli.py --config_file=./configs/config.yml
22-
python cli.py -c configs/config.yml --verbose
2319
"""
2420

2521
import argparse
@@ -43,35 +39,14 @@ def parse_args():
4339
parser = argparse.ArgumentParser(
4440
description="Run MCP server load tests using YAML configuration",
4541
formatter_class=argparse.RawDescriptionHelpFormatter,
46-
epilog="""
47-
Examples:
48-
# Run with config file
49-
python cli.py --config_file=configs/config.yml
50-
51-
# With verbose logging
52-
python cli.py --config_file=configs/config.yml --verbose
53-
54-
# Short form
55-
python cli.py -c configs/config.yml
56-
57-
Configuration File Format:
58-
The YAML config file should contain:
59-
- config_file: Path to NAT workflow config
60-
- server: Server configuration (host, port, transport)
61-
- load_test: Test parameters (num_concurrent_users, duration_seconds, etc.)
62-
- output: Output directory configuration
63-
- tool_calls: List of tool calls to execute
64-
65-
See configs/config.yml for a complete example.
66-
""",
6742
)
6843

6944
parser.add_argument(
7045
"-c",
7146
"--config_file",
7247
type=str,
7348
required=True,
74-
help="Path to YAML configuration file (e.g., configs/config.yml)",
49+
help="Path to YAML configuration file",
7550
)
7651

7752
parser.add_argument(
@@ -94,7 +69,6 @@ def print_summary(results: dict):
9469
logger.info("LOAD TEST RESULTS SUMMARY")
9570
logger.info("=" * 70)
9671

97-
# Summary metrics
9872
summary = results.get("summary", {})
9973
logger.info("\nSummary Metrics:")
10074
logger.info(" Total Requests: %d", summary.get("total_requests", 0))
@@ -104,7 +78,6 @@ def print_summary(results: dict):
10478
logger.info(" Test Duration: %.2f seconds", summary.get("test_duration_seconds", 0))
10579
logger.info(" Requests/Second: %.2f", summary.get("requests_per_second", 0))
10680

107-
# Latency statistics
10881
latency = results.get("latency_statistics", {})
10982
logger.info("\nLatency Statistics:")
11083
logger.info(" Mean: %.2f ms", latency.get("mean_ms", 0))
@@ -114,7 +87,6 @@ def print_summary(results: dict):
11487
logger.info(" Min: %.2f ms", latency.get("min_ms", 0))
11588
logger.info(" Max: %.2f ms", latency.get("max_ms", 0))
11689

117-
# Memory statistics
11890
memory = results.get("memory_statistics", {})
11991
if memory:
12092
logger.info("\nMemory Statistics:")
@@ -125,7 +97,6 @@ def print_summary(results: dict):
12597
logger.info(" Mean Memory Usage: %.2f%%", memory.get("percent_mean", 0))
12698
logger.info(" Max Memory Usage: %.2f%%", memory.get("percent_max", 0))
12799

128-
# Per-tool statistics
129100
tool_stats = results.get("per_tool_statistics", {})
130101
if tool_stats:
131102
logger.info("\nPer-Tool Statistics:")
@@ -135,14 +106,12 @@ def print_summary(results: dict):
135106
logger.info(" Success Rate: %.2f%%", stats.get("success_rate", 0))
136107
logger.info(" Mean Latency: %.2f ms", stats.get("mean_latency_ms", 0))
137108

138-
# Errors
139109
errors = results.get("errors", {})
140110
if errors:
141111
logger.info("\nErrors:")
142112
for error_msg, count in sorted(errors.items(), key=lambda x: x[1], reverse=True)[:5]:
143113
logger.info(" [%d] %s", count, error_msg[:80])
144114

145-
# Output location
146115
test_config = results.get("test_configuration", {})
147116
output_dir = test_config.get("output_dir", "load_test_results")
148117
logger.info("\n" + "=" * 70)
@@ -154,18 +123,14 @@ def main():
154123
"""Main entry point."""
155124
args = parse_args()
156125

157-
# Set logging level
158126
if args.verbose:
159127
logging.getLogger().setLevel(logging.DEBUG)
160128
logger.debug("Verbose logging enabled")
161129

162-
# Validate config file path
163130
config_path = Path(args.config_file)
164131

165132
if not config_path.exists():
166133
logger.error("Configuration file not found: %s", config_path)
167-
168-
# Try to find it relative to script directory
169134
script_dir = Path(__file__).parent
170135
alternative_path = script_dir / args.config_file
171136

@@ -179,18 +144,15 @@ def main():
179144
logger.info("Configuration file: %s", config_path.absolute())
180145

181146
try:
182-
# Run the load test
183147
results = run_load_test_from_yaml(str(config_path))
184148

185-
# Print summary
186149
print_summary(results)
187150

188-
# Return success
189151
return 0
190152

191153
except KeyboardInterrupt:
192154
logger.warning("\nLoad test interrupted by user")
193-
return 130 # Standard exit code for SIGINT
155+
return 130
194156

195157
except Exception as e:
196158
logger.error("Load test failed: %s", e, exc_info=args.verbose)

src/nat/front_ends/mcp/load_test_utils/config_loader.py

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,31 +51,26 @@ def load_config_from_yaml(config_path: str | Path) -> LoadTestConfig:
5151
if not config_data:
5252
raise ValueError("Config file is empty")
5353

54-
# Extract required field
5554
config_file = config_data.get("config_file")
5655
if not config_file:
57-
raise ValueError("'config_file' is required in the config")
56+
raise ValueError("config_file is required in the config")
5857

59-
# Extract server configuration
6058
server_config = config_data.get("server", {})
6159
server_host = server_config.get("host", "localhost")
6260
server_port = server_config.get("port", 9901)
6361
transport = server_config.get("transport", "streamable-http")
6462

65-
# Extract load test parameters
6663
load_test_config = config_data.get("load_test", {})
6764
num_concurrent_users = load_test_config.get("num_concurrent_users", 10)
6865
duration_seconds = load_test_config.get("duration_seconds", 60)
6966
warmup_seconds = load_test_config.get("warmup_seconds", 5)
7067

71-
# Extract output configuration
7268
output_config = config_data.get("output", {})
7369
output_dir = output_config.get("directory", None)
7470

75-
# Extract tool calls
7671
tool_calls_data = config_data.get("tool_calls", [])
7772
if not tool_calls_data:
78-
raise ValueError("At least one tool call must be specified in 'tool_calls'")
73+
raise ValueError("At least one tool call must be specified in tool_calls")
7974

8075
tool_calls = []
8176
for tc in tool_calls_data:
@@ -130,7 +125,7 @@ def validate_config(config: LoadTestConfig) -> None:
130125
raise ValueError("At least one tool call must be specified")
131126

132127
if config.transport not in ["streamable-http", "sse"]:
133-
raise ValueError("transport must be 'streamable-http' or 'sse'")
128+
raise ValueError("transport must be streamable-http or sse")
134129

135130
if config.server_port < 1 or config.server_port > 65535:
136131
raise ValueError("server_port must be between 1 and 65535")

0 commit comments

Comments
 (0)