- Complete FastMCP server with OpenAPI integration and fallback tools - Automatic tool generation from Mailu REST API endpoints - Bearer token authentication support - Comprehensive test suite and documentation - PyPI-ready package configuration with proper metadata - Environment-based configuration support - Production-ready error handling and logging - Examples and publishing scripts included Features: - User management (list, create, update, delete) - Domain management (list, create, update, delete) - Alias management and email forwarding - DKIM key generation - Manager assignment for domains - Graceful fallback when OpenAPI validation fails Ready for Claude Desktop integration and PyPI distribution.
126 lines
3.4 KiB
Python
126 lines
3.4 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Build and publish script for mcp-mailu package.
|
|
|
|
Usage:
|
|
python scripts/publish.py --build # Build package
|
|
python scripts/publish.py --test # Upload to TestPyPI
|
|
python scripts/publish.py --prod # Upload to PyPI
|
|
python scripts/publish.py --check # Check package
|
|
"""
|
|
|
|
import argparse
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
|
|
def run_command(cmd: str, check: bool = True) -> subprocess.CompletedProcess:
|
|
"""Run a shell command and return the result."""
|
|
print(f"🔧 Running: {cmd}")
|
|
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
|
|
|
|
if check and result.returncode != 0:
|
|
print(f"❌ Command failed: {cmd}")
|
|
print(f"stdout: {result.stdout}")
|
|
print(f"stderr: {result.stderr}")
|
|
sys.exit(1)
|
|
|
|
return result
|
|
|
|
|
|
def build_package():
|
|
"""Build the package for distribution."""
|
|
print("📦 Building package...")
|
|
|
|
# Clean previous builds
|
|
run_command("rm -rf dist/ build/ *.egg-info")
|
|
|
|
# Build package
|
|
run_command("uv build")
|
|
|
|
print("✅ Package built successfully!")
|
|
|
|
|
|
def check_package():
|
|
"""Check the package for common issues."""
|
|
print("🔍 Checking package...")
|
|
|
|
# Check with twine
|
|
run_command("uv run twine check dist/*")
|
|
|
|
print("✅ Package check passed!")
|
|
|
|
|
|
def upload_test():
|
|
"""Upload to TestPyPI for testing."""
|
|
print("🧪 Uploading to TestPyPI...")
|
|
|
|
run_command("uv run twine upload --repository testpypi dist/*")
|
|
|
|
print("✅ Uploaded to TestPyPI!")
|
|
print("📋 Test installation:")
|
|
print(" pip install -i https://test.pypi.org/simple/ mcp-mailu")
|
|
|
|
|
|
def upload_prod():
|
|
"""Upload to production PyPI."""
|
|
print("🚀 Uploading to PyPI...")
|
|
|
|
# Double check first
|
|
response = input("⚠️ This will upload to production PyPI. Continue? (y/N): ")
|
|
if response.lower() != 'y':
|
|
print("❌ Upload cancelled.")
|
|
return
|
|
|
|
run_command("uv run twine upload dist/*")
|
|
|
|
print("✅ Uploaded to PyPI!")
|
|
print("📋 Installation:")
|
|
print(" pip install mcp-mailu")
|
|
|
|
|
|
def main():
|
|
"""Main script entry point."""
|
|
parser = argparse.ArgumentParser(description="Build and publish mcp-mailu package")
|
|
parser.add_argument("--build", action="store_true", help="Build the package")
|
|
parser.add_argument("--check", action="store_true", help="Check the package")
|
|
parser.add_argument("--test", action="store_true", help="Upload to TestPyPI")
|
|
parser.add_argument("--prod", action="store_true", help="Upload to PyPI")
|
|
|
|
args = parser.parse_args()
|
|
|
|
if not any([args.build, args.check, args.test, args.prod]):
|
|
parser.print_help()
|
|
return
|
|
|
|
# Ensure we're in the right directory
|
|
if not Path("pyproject.toml").exists():
|
|
print("❌ Run this script from the project root directory")
|
|
sys.exit(1)
|
|
|
|
try:
|
|
if args.build:
|
|
build_package()
|
|
|
|
if args.check:
|
|
check_package()
|
|
|
|
if args.test:
|
|
build_package()
|
|
check_package()
|
|
upload_test()
|
|
|
|
if args.prod:
|
|
build_package()
|
|
check_package()
|
|
upload_prod()
|
|
|
|
except KeyboardInterrupt:
|
|
print("\n❌ Operation cancelled by user")
|
|
sys.exit(1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|