mcp-mailu/scripts/publish.py
Ryan Malloy 66d1c0732a Initial commit: FastMCP server for Mailu email API integration
- 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.
2025-07-16 11:55:44 -06:00

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()