MCP-LOGO-GEN

#!/usr/bin/env python """ Server runner script with clean shutdown handling and auto-reload. This script runs the server in a subprocess, handles Ctrl+C properly, and automatically restarts the server when files change. """ import os import signal import subprocess import sys import time import threading from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler # Flag to indicate if we should restart the server restart_server = False # Flag to indicate if we're shutting down shutting_down = False class FileChangeHandler(FileSystemEventHandler): def on_any_event(self, event): global restart_server # Skip temporary files and __pycache__ directories if (event.src_path.endswith('.pyc') or '__pycache__' in event.src_path or '.git' in event.src_path or event.is_directory): return # Only restart for Python files if event.src_path.endswith('.py'): print(f"\n[RELOAD] Detected change in {event.src_path}") restart_server = True def start_file_watcher(directory): """Start watching for file changes in the specified directory.""" event_handler = FileChangeHandler() observer = Observer() observer.schedule(event_handler, directory, recursive=True) observer.start() return observer def run_server(): """Run the server process and handle its lifecycle.""" global restart_server, shutting_down # Start the server as a subprocess server_process = subprocess.Popen( [sys.executable, "server.py"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, bufsize=1 # Line buffered ) # Print server output in real-time def print_output(): for line in server_process.stdout: if not shutting_down: # Only print if we're not shutting down print(line, end='') # Start a thread to print output output_thread = threading.Thread(target=print_output) output_thread.daemon = True output_thread.start() # Monitor the server process while server_process.poll() is None: if restart_server: print("\n[RELOAD] Restarting server due to file changes...") server_process.terminate() try: server_process.wait(timeout=2) except subprocess.TimeoutExpired: server_process.kill() server_process.wait() restart_server = False return True # Signal to restart time.sleep(0.1) # If we get here, the server exited on its own return_code = server_process.poll() print(f"\nServer exited with code {return_code}") return False # Signal not to restart def main(): global restart_server, shutting_down print("Starting MCP Tool Server with clean shutdown handling and auto-reload...") # Start file watcher observer = start_file_watcher("mcp_tool_server") # Function to handle Ctrl+C def signal_handler(sig, frame): global shutting_down print("\nReceived shutdown signal. Terminating server...") shutting_down = True observer.stop() sys.exit(0) # Register signal handlers signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) # Run the server, restarting as needed try: while True: should_restart = run_server() if not should_restart: break time.sleep(0.5) # Small delay before restart except KeyboardInterrupt: signal_handler(signal.SIGINT, None) finally: observer.stop() observer.join() return 0 if __name__ == "__main__": sys.exit(main())