
- Production-ready MCP server for Name Cheap API integration - Domain management (registration, renewal, availability checking) - DNS management (records, nameserver configuration) - SSL certificate management and monitoring - Account information and balance checking - Smart identifier resolution for improved UX - Comprehensive error handling with specific exception types - 80%+ test coverage with unit, integration, and MCP tests - CLI and MCP server interfaces - FastMCP 2.10.5+ implementation with full MCP spec compliance 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
146 lines
4.3 KiB
Python
Executable File
146 lines
4.3 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
Script to help with publishing to TestPyPI and PyPI.
|
|
This script provides an interactive way to build and publish the package.
|
|
"""
|
|
|
|
import subprocess
|
|
import sys
|
|
import argparse
|
|
from pathlib import Path
|
|
|
|
|
|
def run_command(cmd: list[str], description: str) -> bool:
|
|
"""Run a command and return success status."""
|
|
print(f"\n🔄 {description}")
|
|
print(f"Command: {' '.join(cmd)}")
|
|
|
|
try:
|
|
result = subprocess.run(cmd, check=True, cwd=Path(__file__).parent.parent)
|
|
print(f"✅ {description} - Success")
|
|
return True
|
|
except subprocess.CalledProcessError as e:
|
|
print(f"❌ {description} - Failed with exit code {e.returncode}")
|
|
return False
|
|
|
|
|
|
def main():
|
|
"""Main publishing script."""
|
|
parser = argparse.ArgumentParser(description="Publish MCP Name Cheap package")
|
|
parser.add_argument(
|
|
"--target",
|
|
choices=["testpypi", "pypi"],
|
|
default="testpypi",
|
|
help="Publishing target (default: testpypi)"
|
|
)
|
|
parser.add_argument(
|
|
"--skip-tests",
|
|
action="store_true",
|
|
help="Skip running tests before publishing"
|
|
)
|
|
parser.add_argument(
|
|
"--skip-build",
|
|
action="store_true",
|
|
help="Skip building (use existing dist/)"
|
|
)
|
|
|
|
args = parser.parse_args()
|
|
|
|
print("🚀 MCP Name Cheap Publishing Script")
|
|
print(f"Target: {args.target}")
|
|
|
|
success = True
|
|
|
|
# Run tests unless skipped
|
|
if not args.skip_tests:
|
|
print("\n" + "="*60)
|
|
print("📋 Running tests...")
|
|
success &= run_command(
|
|
["python", "run_tests.py", "--all"],
|
|
"Running all tests and quality checks"
|
|
)
|
|
|
|
if not success:
|
|
print("\n❌ Tests failed. Fix issues before publishing.")
|
|
return 1
|
|
|
|
# Clean and build
|
|
if not args.skip_build:
|
|
print("\n" + "="*60)
|
|
print("🏗️ Building package...")
|
|
|
|
# Clean old builds
|
|
success &= run_command(
|
|
["rm", "-rf", "dist/", "build/"],
|
|
"Cleaning old build artifacts"
|
|
)
|
|
|
|
# Build package
|
|
success &= run_command(
|
|
["python", "-m", "build"],
|
|
"Building source and wheel distributions"
|
|
)
|
|
|
|
if not success:
|
|
print("\n❌ Build failed.")
|
|
return 1
|
|
|
|
# Check package
|
|
print("\n" + "="*60)
|
|
print("🔍 Checking package...")
|
|
success &= run_command(
|
|
["python", "-m", "twine", "check", "dist/*"],
|
|
"Checking package with twine"
|
|
)
|
|
|
|
if not success:
|
|
print("\n❌ Package check failed.")
|
|
return 1
|
|
|
|
# Publish
|
|
print("\n" + "="*60)
|
|
print(f"📦 Publishing to {args.target}...")
|
|
|
|
if args.target == "testpypi":
|
|
repository_url = "https://test.pypi.org/legacy/"
|
|
print("\n⚠️ Publishing to TestPyPI")
|
|
print("You can install the test package with:")
|
|
print("pip install -i https://test.pypi.org/simple/ mcp-namecheap")
|
|
else:
|
|
repository_url = "https://upload.pypi.org/legacy/"
|
|
print("\n🚨 Publishing to PRODUCTION PyPI")
|
|
|
|
confirm = input("Are you sure you want to publish to production PyPI? (yes/no): ")
|
|
if confirm.lower() != "yes":
|
|
print("❌ Publishing cancelled.")
|
|
return 1
|
|
|
|
# Build twine command
|
|
twine_cmd = ["python", "-m", "twine", "upload"]
|
|
if args.target == "testpypi":
|
|
twine_cmd.extend(["--repository-url", repository_url])
|
|
twine_cmd.append("dist/*")
|
|
|
|
success &= run_command(
|
|
twine_cmd,
|
|
f"Publishing to {args.target}"
|
|
)
|
|
|
|
if success:
|
|
print(f"\n🎉 Successfully published to {args.target}!")
|
|
if args.target == "testpypi":
|
|
print("\n📋 Next steps:")
|
|
print("1. Test the package: pip install -i https://test.pypi.org/simple/ mcp-namecheap")
|
|
print("2. If everything works, publish to PyPI: python scripts/publish.py --target pypi")
|
|
else:
|
|
print("\n🌟 Package is now live on PyPI!")
|
|
print("Users can install with: pip install mcp-namecheap")
|
|
else:
|
|
print(f"\n❌ Publishing to {args.target} failed.")
|
|
return 1
|
|
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main()) |