generate_client_sdks.py•6.92 kB
#!/usr/bin/env python3
"""
Client SDK Generation Script for MCP Server for Splunk
This script generates client SDKs in multiple programming languages using the OpenAPI specification.
It supports Python, JavaScript/TypeScript, Go, Java, and C# client libraries.
"""
import json
import subprocess
import sys
from pathlib import Path
class ClientSDKGenerator:
"""
Generates client SDKs for the MCP Server for Splunk using OpenAPI Generator.
"""
def __init__(self, openapi_spec_path: str, output_dir: str):
self.openapi_spec_path = Path(openapi_spec_path)
self.output_dir = Path(output_dir)
self.output_dir.mkdir(parents=True, exist_ok=True)
# Supported languages and their configurations
self.language_configs = {
"python": {
"generator": "python",
"package_name": "splunk_mcp_client",
"project_name": "Python SDK",
"additional_properties": {
"packageName": "splunk_mcp_client",
"projectName": "splunk-mcp-client",
"packageVersion": "1.0.0",
},
},
"typescript": {
"generator": "typescript-fetch",
"package_name": "splunk-mcp-client",
"project_name": "TypeScript SDK",
"additional_properties": {
"npmName": "splunk-mcp-client",
"npmVersion": "1.0.0",
"supportsES6": "true",
"withInterfaces": "true",
},
},
}
def check_openapi_generator(self) -> bool:
"""Check if OpenAPI Generator is available."""
try:
result = subprocess.run(
["openapi-generator-cli", "version"], capture_output=True, text=True, check=True
)
print(f"✓ OpenAPI Generator found: {result.stdout.strip()}")
return True
except (subprocess.CalledProcessError, FileNotFoundError):
print("✗ OpenAPI Generator CLI not found")
print("Please install it using:")
print(" npm install @openapitools/openapi-generator-cli -g")
print(" or")
print(" brew install openapi-generator")
return False
def validate_openapi_spec(self) -> bool:
"""Validate the OpenAPI specification."""
try:
with open(self.openapi_spec_path) as f:
spec = json.load(f)
# Basic validation
required_fields = ["openapi", "info", "paths"]
for field in required_fields:
if field not in spec:
print(f"✗ OpenAPI spec missing required field: {field}")
return False
print("✓ OpenAPI specification is valid")
return True
except json.JSONDecodeError as e:
print(f"✗ Invalid JSON in OpenAPI spec: {e}")
return False
except FileNotFoundError:
print(f"✗ OpenAPI spec file not found: {self.openapi_spec_path}")
return False
def generate_sdk(self, language: str) -> bool:
"""Generate SDK for a specific language."""
if language not in self.language_configs:
print(f"✗ Unsupported language: {language}")
return False
config = self.language_configs[language]
output_path = self.output_dir / f"client-{language}"
print(f"\n🔧 Generating {config['project_name']} SDK...")
# Prepare command
cmd = [
"openapi-generator-cli",
"generate",
"-i",
str(self.openapi_spec_path),
"-g",
config["generator"],
"-o",
str(output_path),
]
# Add additional properties as a single comma-separated parameter
if config["additional_properties"]:
properties = ",".join(
[f"{key}={value}" for key, value in config["additional_properties"].items()]
)
cmd.extend(["--additional-properties", properties])
try:
# Create output directory
output_path.mkdir(parents=True, exist_ok=True)
# Run generation
subprocess.run(cmd, capture_output=True, text=True, check=True)
print(f"✓ {config['project_name']} SDK generated successfully")
print(f" Output: {output_path}")
return True
except subprocess.CalledProcessError as e:
print(f"✗ Failed to generate {config['project_name']} SDK")
print(f" Error: {e.stderr}")
return False
def generate_all_sdks(self, languages: list[str] | None = None) -> dict[str, bool]:
"""Generate SDKs for all or specified languages."""
if languages is None:
languages = list(self.language_configs.keys())
results = {}
print("🚀 Starting Client SDK Generation")
print(f"📁 Output directory: {self.output_dir}")
print(f"📄 OpenAPI spec: {self.openapi_spec_path}")
# Validate prerequisites
if not self.check_openapi_generator():
return {"error": "OpenAPI Generator not available"}
if not self.validate_openapi_spec():
return {"error": "Invalid OpenAPI specification"}
# Generate each SDK
for language in languages:
results[language] = self.generate_sdk(language)
# Summary
successful = [lang for lang, success in results.items() if success]
failed = [lang for lang, success in results.items() if not success]
print("\n📊 SDK Generation Summary:")
print(f"✓ Successful: {len(successful)} ({', '.join(successful)})")
if failed:
print(f"✗ Failed: {len(failed)} ({', '.join(failed)})")
return results
def main():
"""Main entry point for the SDK generator."""
import argparse
parser = argparse.ArgumentParser(description="Generate client SDKs for MCP Server for Splunk")
parser.add_argument(
"--spec", default="docs/api/openapi.json", help="Path to OpenAPI specification file"
)
parser.add_argument("--output", default="sdk", help="Output directory for generated SDKs")
parser.add_argument(
"--languages",
nargs="+",
choices=["python", "typescript"],
help="Languages to generate SDKs for (default: all)",
)
args = parser.parse_args()
# Create generator
generator = ClientSDKGenerator(args.spec, args.output)
# Generate SDKs
results = generator.generate_all_sdks(args.languages)
# Exit with error code if any generation failed
if "error" in results or any(not success for success in results.values()):
sys.exit(1)
if __name__ == "__main__":
main()