#!/usr/bin/env python3 """ MCP Service Startup Script (Python Version) Start all four MCP services: Math, Search, TradeTools, LocalPrices """ import os import sys import time import signal import subprocess import threading from pathlib import Path from dotenv import load_dotenv load_dotenv() class MCPServiceManager: def __init__(self): self.services = {} self.running = True # Set default ports self.ports = { 'math': int(os.getenv('MATH_HTTP_PORT', '8000')), 'search': int(os.getenv('SEARCH_HTTP_PORT', '8001')), 'trade': int(os.getenv('TRADE_HTTP_PORT', '8002')), 'price': int(os.getenv('GETPRICE_HTTP_PORT', '8003')) } # Service configurations (paths relative to /app) self.agent_tools_dir = Path(__file__).parent.resolve() self.service_configs = { 'math': { 'script': self.agent_tools_dir / 'tool_math.py', 'name': 'Math', 'port': self.ports['math'] }, 'search': { 'script': self.agent_tools_dir / 'tool_jina_search.py', 'name': 'Search', 'port': self.ports['search'] }, 'trade': { 'script': self.agent_tools_dir / 'tool_trade.py', 'name': 'TradeTools', 'port': self.ports['trade'] }, 'price': { 'script': self.agent_tools_dir / 'tool_get_price_local.py', 'name': 'LocalPrices', 'port': self.ports['price'] } } # Set signal handlers signal.signal(signal.SIGINT, self.signal_handler) signal.signal(signal.SIGTERM, self.signal_handler) def signal_handler(self, signum, frame): """Handle interrupt signals""" print("\nšŸ›‘ Received stop signal, shutting down all services...") self.stop_all_services() sys.exit(0) def start_service(self, service_id, config): """Start a single service""" script_path = config['script'] service_name = config['name'] port = config['port'] if not script_path.exists(): print(f"āŒ Script file not found: {script_path}") return False try: # Set PYTHONPATH to /app so services can import from tools module env = os.environ.copy() env['PYTHONPATH'] = str(Path.cwd()) # Start service process (output goes to Docker logs) process = subprocess.Popen( [sys.executable, str(script_path)], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, cwd=Path.cwd(), # Use current working directory (/app) env=env # Pass environment with PYTHONPATH ) self.services[service_id] = { 'process': process, 'name': service_name, 'port': port } print(f"āœ… {service_name} service started (PID: {process.pid}, Port: {port})") return True except Exception as e: print(f"āŒ Failed to start {service_name} service: {e}") return False def check_service_health(self, service_id): """Check service health status""" if service_id not in self.services: return False service = self.services[service_id] process = service['process'] port = service['port'] # Check if process is still running if process.poll() is not None: return False # Check if port is responding (simple check) try: import socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(1) result = sock.connect_ex(('localhost', port)) sock.close() return result == 0 except: return False def start_all_services(self): """Start all services""" print("šŸš€ Starting MCP services...") print("=" * 50) print(f"šŸ“Š Port configuration:") for service_id, config in self.service_configs.items(): print(f" - {config['name']}: {config['port']}") print("\nšŸ”„ Starting services...") # Start all services for service_id, config in self.service_configs.items(): self.start_service(service_id, config) # Wait for services to start print("\nā³ Waiting for services to start...") time.sleep(3) # Check service status print("\nšŸ” Checking service status...") self.check_all_services() print("\nšŸŽ‰ All MCP services started!") self.print_service_info() # Keep running self.keep_alive() def check_all_services(self): """Check all service status""" for service_id, service in self.services.items(): if self.check_service_health(service_id): print(f"āœ… {service['name']} service running normally") else: print(f"āŒ {service['name']} service failed to start") print(f" Check Docker logs for details: docker logs ai-trader-server") def print_service_info(self): """Print service information""" print("\nšŸ“‹ Service information:") for service_id, service in self.services.items(): print(f" - {service['name']}: http://localhost:{service['port']} (PID: {service['process'].pid})") print("\nšŸ›‘ Press Ctrl+C to stop all services") def keep_alive(self): """Keep services running""" try: while self.running: time.sleep(1) # Check service status for service_id, service in self.services.items(): if service['process'].poll() is not None: print(f"\nāš ļø {service['name']} service stopped unexpectedly") self.running = False break except KeyboardInterrupt: pass finally: self.stop_all_services() def stop_all_services(self): """Stop all services""" print("\nšŸ›‘ Stopping all services...") for service_id, service in self.services.items(): try: service['process'].terminate() service['process'].wait(timeout=5) print(f"āœ… {service['name']} service stopped") except subprocess.TimeoutExpired: service['process'].kill() print(f"šŸ”Ø {service['name']} service force stopped") except Exception as e: print(f"āŒ Error stopping {service['name']} service: {e}") print("āœ… All services stopped") def status(self): """Display service status""" print("šŸ“Š MCP Service Status Check") print("=" * 30) for service_id, config in self.service_configs.items(): if service_id in self.services: service = self.services[service_id] if self.check_service_health(service_id): print(f"āœ… {config['name']} service running normally (Port: {config['port']})") else: print(f"āŒ {config['name']} service abnormal (Port: {config['port']})") else: print(f"āŒ {config['name']} service not started (Port: {config['port']})") def main(): """Main function""" if len(sys.argv) > 1 and sys.argv[1] == 'status': # Status check mode manager = MCPServiceManager() manager.status() else: # Startup mode manager = MCPServiceManager() manager.start_all_services() if __name__ == "__main__": main()