Skip to main content
Glama

Google Calendar and Meet MCP Server

by INSIDE-HAIR
docker-deploy.sh•13.7 kB
#!/bin/bash # Google Meet MCP Server v3.0 - Docker Deployment Script # Production-ready deployment automation with environment validation set -euo pipefail # Exit on error, undefined vars, pipe failures # ============================================================================ # Configuration and Constants # ============================================================================ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" DOCKER_COMPOSE_DEV="$PROJECT_ROOT/docker-compose.yml" DOCKER_COMPOSE_PROD="$PROJECT_ROOT/docker-compose.prod.yml" # Color codes for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Default values ENVIRONMENT="development" BUILD_FRESH=false VERBOSE=false HEALTHCHECK_TIMEOUT=60 BACKUP_DATA=false # ============================================================================ # Utility Functions # ============================================================================ print_banner() { echo -e "${BLUE}" echo "================================================" echo " Google Meet MCP Server v3.0 - Docker Deploy" echo "================================================" echo -e "${NC}" } log_info() { echo -e "${GREEN}[INFO]${NC} $1" } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } log_debug() { if [[ "$VERBOSE" == "true" ]]; then echo -e "${BLUE}[DEBUG]${NC} $1" fi } show_usage() { cat << EOF Usage: $0 [OPTIONS] COMMAND COMMANDS: dev Deploy in development mode with hot reload prod Deploy in production mode with optimizations stop Stop all services restart Restart services (preserves data) logs Show service logs status Show service status cleanup Clean up containers and networks backup Backup persistent data OPTIONS: -f, --fresh Force rebuild of Docker images -v, --verbose Enable verbose logging -t, --timeout N Health check timeout in seconds (default: 60) -b, --backup Backup data before deployment -h, --help Show this help message EXAMPLES: $0 dev # Start development environment $0 prod --fresh --backup # Fresh production deployment with backup $0 logs google-meet-mcp # Show application logs $0 stop # Stop all services $0 cleanup # Clean up everything EOF } # ============================================================================ # Pre-flight Checks # ============================================================================ check_dependencies() { log_info "Checking dependencies..." # Check Docker if ! command -v docker &> /dev/null; then log_error "Docker is not installed or not in PATH" exit 1 fi # Check Docker Compose if ! command -v docker-compose &> /dev/null && ! docker compose version &> /dev/null; then log_error "Docker Compose is not installed" exit 1 fi # Check Docker daemon if ! docker info &> /dev/null; then log_error "Docker daemon is not running" exit 1 fi log_debug "Docker version: $(docker --version)" log_debug "Docker Compose version: $(docker-compose --version 2>/dev/null || docker compose version)" } check_files() { log_info "Checking required files..." local required_files=("$PROJECT_ROOT/Dockerfile") if [[ "$ENVIRONMENT" == "development" ]]; then required_files+=("$DOCKER_COMPOSE_DEV") else required_files+=("$DOCKER_COMPOSE_PROD") fi for file in "${required_files[@]}"; do if [[ ! -f "$file" ]]; then log_error "Required file not found: $file" exit 1 fi log_debug "Found: $file" done } check_credentials() { log_info "Checking Google credentials..." local credentials_path="" # Check environment variables if [[ -n "${G_OAUTH_CREDENTIALS:-}" ]]; then credentials_path="$G_OAUTH_CREDENTIALS" elif [[ -n "${GOOGLE_MEET_CREDENTIALS_PATH:-}" ]]; then credentials_path="$GOOGLE_MEET_CREDENTIALS_PATH" else credentials_path="$PROJECT_ROOT/credentials.json" fi if [[ ! -f "$credentials_path" ]]; then log_warn "Credentials file not found: $credentials_path" log_warn "Make sure to set up Google OAuth credentials before deployment" log_warn "Run 'npm run setup' to create credentials" else log_debug "Credentials found: $credentials_path" fi } # ============================================================================ # Deployment Functions # ============================================================================ backup_data() { if [[ "$BACKUP_DATA" != "true" ]]; then return 0 fi log_info "Creating data backup..." local backup_dir="$PROJECT_ROOT/backups/$(date +%Y%m%d_%H%M%S)" mkdir -p "$backup_dir" # Backup Docker volumes local volumes=() if [[ "$ENVIRONMENT" == "development" ]]; then volumes=("google_meet_mcp_logs_dev" "google_meet_mcp_data_dev") else volumes=("google_meet_mcp_logs_prod" "google_meet_mcp_data_prod") fi for volume in "${volumes[@]}"; do if docker volume inspect "$volume" &> /dev/null; then log_debug "Backing up volume: $volume" docker run --rm -v "$volume:/data" -v "$backup_dir:/backup" alpine:latest \ tar czf "/backup/${volume}.tar.gz" -C /data . fi done log_info "Backup completed: $backup_dir" } build_images() { log_info "Building Docker images..." local compose_file="" if [[ "$ENVIRONMENT" == "development" ]]; then compose_file="$DOCKER_COMPOSE_DEV" else compose_file="$DOCKER_COMPOSE_PROD" fi local build_args=() if [[ "$BUILD_FRESH" == "true" ]]; then build_args+=("--no-cache" "--pull") log_info "Performing fresh build (no cache)" fi if [[ "$VERBOSE" == "true" ]]; then build_args+=("--progress=plain") fi docker-compose -f "$compose_file" build "${build_args[@]}" } deploy_services() { log_info "Deploying services in $ENVIRONMENT mode..." local compose_file="" if [[ "$ENVIRONMENT" == "development" ]]; then compose_file="$DOCKER_COMPOSE_DEV" else compose_file="$DOCKER_COMPOSE_PROD" fi # Start services docker-compose -f "$compose_file" up -d # Wait for services to be healthy wait_for_health } wait_for_health() { log_info "Waiting for services to be healthy (timeout: ${HEALTHCHECK_TIMEOUT}s)..." local compose_file="" if [[ "$ENVIRONMENT" == "development" ]]; then compose_file="$DOCKER_COMPOSE_DEV" # Development mode may not have health checks enabled log_info "Development mode - skipping health check wait" return 0 else compose_file="$DOCKER_COMPOSE_PROD" fi local timeout=$HEALTHCHECK_TIMEOUT local interval=5 local elapsed=0 while [[ $elapsed -lt $timeout ]]; do local healthy=true # Check main service health if ! docker-compose -f "$compose_file" ps google-meet-mcp | grep -q "healthy\|Up"; then healthy=false fi if [[ "$healthy" == "true" ]]; then log_info "All services are healthy!" return 0 fi log_debug "Waiting for services... (${elapsed}s/${timeout}s)" sleep $interval elapsed=$((elapsed + interval)) done log_error "Services failed to become healthy within ${timeout}s" show_service_status exit 1 } show_service_status() { log_info "Service status:" local compose_file="" if [[ "$ENVIRONMENT" == "development" ]]; then compose_file="$DOCKER_COMPOSE_DEV" else compose_file="$DOCKER_COMPOSE_PROD" fi docker-compose -f "$compose_file" ps } show_logs() { local service_name="${1:-}" local compose_file="" if [[ "$ENVIRONMENT" == "development" ]]; then compose_file="$DOCKER_COMPOSE_DEV" else compose_file="$DOCKER_COMPOSE_PROD" fi if [[ -n "$service_name" ]]; then docker-compose -f "$compose_file" logs -f "$service_name" else docker-compose -f "$compose_file" logs -f fi } stop_services() { log_info "Stopping services..." local compose_files=("$DOCKER_COMPOSE_DEV" "$DOCKER_COMPOSE_PROD") for compose_file in "${compose_files[@]}"; do if [[ -f "$compose_file" ]]; then log_debug "Stopping services from: $compose_file" docker-compose -f "$compose_file" down || true fi done } restart_services() { log_info "Restarting services..." local compose_file="" if [[ "$ENVIRONMENT" == "development" ]]; then compose_file="$DOCKER_COMPOSE_DEV" else compose_file="$DOCKER_COMPOSE_PROD" fi docker-compose -f "$compose_file" restart wait_for_health } cleanup_docker() { log_info "Cleaning up Docker resources..." # Stop all services stop_services # Remove unused networks docker network prune -f # Remove unused images (if requested) if [[ "$BUILD_FRESH" == "true" ]]; then log_info "Removing unused Docker images..." docker image prune -f fi # Remove dangling volumes (with confirmation) log_warn "This will remove unused Docker volumes. Continue? (y/N)" read -r response if [[ "$response" =~ ^[Yy]$ ]]; then docker volume prune -f fi } # ============================================================================ # Command Handlers # ============================================================================ cmd_dev() { ENVIRONMENT="development" check_dependencies check_files check_credentials backup_data build_images deploy_services log_info "Development environment deployed successfully!" log_info "Services available:" log_info " - MCP Server: stdio transport (main)" log_info " - HTTP API: http://localhost:3000 (if enabled)" log_info " - MongoDB: localhost:27017" log_info " - Mongo Express: http://localhost:8081 (run with --profile debug)" log_info "" log_info "View logs: $0 logs" log_info "Stop services: $0 stop" } cmd_prod() { ENVIRONMENT="production" # Production requires stricter checks if [[ ! -f "$PROJECT_ROOT/credentials.json" ]]; then log_error "Production requires credentials.json file" exit 1 fi check_dependencies check_files check_credentials backup_data build_images deploy_services log_info "Production environment deployed successfully!" log_info "Services available:" log_info " - MCP Server: stdio transport (main)" log_info " - HTTP API: http://localhost:3000" log_info " - Health Check: http://localhost:3000/health" log_info " - Metrics: http://localhost:9090 (if enabled)" log_info "" log_info "Monitor logs: $0 logs" log_info "Check status: $0 status" } cmd_stop() { stop_services log_info "All services stopped" } cmd_restart() { restart_services log_info "Services restarted successfully" } cmd_logs() { local service_name="${1:-}" show_logs "$service_name" } cmd_status() { show_service_status } cmd_cleanup() { cleanup_docker log_info "Cleanup completed" } cmd_backup() { BACKUP_DATA=true backup_data } # ============================================================================ # Main Script Logic # ============================================================================ main() { print_banner # Parse command line arguments while [[ $# -gt 0 ]]; do case $1 in -f|--fresh) BUILD_FRESH=true shift ;; -v|--verbose) VERBOSE=true shift ;; -t|--timeout) HEALTHCHECK_TIMEOUT="$2" shift 2 ;; -b|--backup) BACKUP_DATA=true shift ;; -h|--help) show_usage exit 0 ;; dev|prod|stop|restart|logs|status|cleanup|backup) COMMAND="$1" shift break ;; *) log_error "Unknown option: $1" show_usage exit 1 ;; esac done # Check for command if [[ -z "${COMMAND:-}" ]]; then log_error "No command specified" show_usage exit 1 fi # Execute command case "$COMMAND" in dev) cmd_dev ;; prod) cmd_prod ;; stop) cmd_stop ;; restart) cmd_restart ;; logs) cmd_logs "$@" ;; status) cmd_status ;; cleanup) cmd_cleanup ;; backup) cmd_backup ;; *) log_error "Unknown command: $COMMAND" show_usage exit 1 ;; esac } # Run main function with all arguments main "$@"

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/INSIDE-HAIR/mcp-google-calendar-and-meet'

If you have feedback or need assistance with the MCP directory API, please join our Discord server