Files
AI-Trader/agent_tools/start_mcp_services.py
Bill 1bdfefae35 refactor: remove duplicate MCP service log files
Remove redundant log file creation for MCP services since output is
already captured by Docker logs. This simplifies deployment by removing
unnecessary volume mounts and file management.

Changes:
- Remove logs/ directory creation from Dockerfile
- Remove logs/ volume mount from docker-compose.yml
- Update start_mcp_services.py to send output to DEVNULL
- Update documentation to reflect changes (DOCKER.md, docs/DOCKER.md)
- Update .env.example to remove logs/ from volume description

Users can still view MCP service output via 'docker logs' or
'docker-compose logs -f'. Trading session logs in data/agent_data/
remain unchanged.
2025-11-02 19:57:17 -05:00

235 lines
7.9 KiB
Python
Executable File

#!/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()