Skip to main content
Glama

MCP Trader Server

by Af7007
main.py12.6 kB
#!/usr/bin/env python3 """Main entry point for the Trading Chatbot System""" import asyncio import argparse import logging import os import sys from typing import Optional import subprocess # Configure logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) logger = logging.getLogger(__name__) class TradingChatbotSystem: """Manages the entire trading chatbot system""" def __init__(self, ollama_host: str = "127.0.0.1", ollama_port: int = 8001, mt5_host: str = "127.0.0.1", mt5_port: int = 8000, web_host: str = "127.0.0.1", web_port: int = 3000): self.ollama_host = ollama_host self.ollama_port = ollama_port self.mt5_host = mt5_host self.mt5_port = mt5_port self.web_host = web_host self.web_port = web_port self.mt5_process: Optional[subprocess.Popen] = None self.ollama_process: Optional[subprocess.Popen] = None self.web_process: Optional[subprocess.Popen] = None # Environment variables for servers self.env_mt5 = os.environ.copy() self.env_mt5.update({ "MT5_MCP_TRANSPORT": "stdio" }) self.env_ollama = os.environ.copy() self.env_ollama.update({ "OLLAMA_MCP_TRANSPORT": "stdio" }) async def start_mt5_server(self) -> bool: """Start the MT5 MCP server""" try: logger.info(f"Starting MT5 MCP server on {self.mt5_host}:{self.mt5_port}") # Start server directly with Python cmd = [sys.executable, "src/mcp_mt5/main.py"] self.mt5_process = subprocess.Popen( cmd, cwd=os.getcwd(), env=self.env_mt5, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True ) # Wait a bit for server to start await asyncio.sleep(3) # Check if process is still alive if self.mt5_process.poll() is None: logger.info("MT5 MCP server started successfully") return True else: stdout, stderr = self.mt5_process.communicate() logger.error(f"MT5 server failed to start: {stderr}") return False except Exception as e: logger.error(f"Failed to start MT5 server: {e}") return False async def start_ollama_server(self) -> bool: """Start the Ollama MCP server in HTTP mode""" try: logger.info(f"Starting Ollama MCP server on {self.ollama_host}:{self.ollama_port}") # Start server in HTTP mode instead of STDIO env_http = self.env_ollama.copy() env_http["OLLAMA_MCP_MODE"] = "http" cmd = [sys.executable, "src/mcp_ollama/main.py"] self.ollama_process = subprocess.Popen( cmd, cwd=os.getcwd(), env=env_http, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True ) # Wait for server to start (longer for HTTP server) await asyncio.sleep(5) if self.ollama_process.poll() is None: logger.info("Ollama MCP HTTP server started successfully") return True else: stdout, stderr = self.ollama_process.communicate() logger.error(f"Ollama HTTP server failed to start: {stderr}") return False except Exception as e: logger.error(f"Failed to start Ollama server: {e}") return False async def start_web_server(self) -> bool: """Start the web interface server""" try: logger.info(f"Starting web server on {self.web_host}:{self.web_port}") cmd = [sys.executable, "src/web/app.py"] self.web_process = subprocess.Popen( cmd, cwd=os.getcwd(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True ) # Wait for server to start await asyncio.sleep(5) if self.web_process.poll() is None: logger.info("Web server started successfully") return True else: stdout, stderr = self.web_process.communicate() logger.error(f"Web server failed to start: {stderr}") return False except Exception as e: logger.error(f"Failed to start web server: {e}") return False async def check_ollama_running(self) -> bool: """Check if Ollama service is running locally""" try: import aiohttp async with aiohttp.ClientSession() as session: async with session.get("http://localhost:11434/api/version", timeout=aiohttp.ClientTimeout(total=5)) as response: if response.status == 200: logger.info("Ollama service is running") return True except Exception as e: logger.error(f"Ollama service not available: {e}") # Try to start Ollama if not running logger.info("Attempting to start Ollama service...") try: # On Windows, try to start Ollama service os.system("ollama serve") await asyncio.sleep(5) # Wait for startup return True except Exception: logger.error("Could not start Ollama service automatically") return False async def start_system(self) -> bool: """Start the entire trading chatbot system""" logger.info("🚀 Starting Trading Chatbot System...") logger.info("=" * 50) # Check Ollama availability ollama_ok = await self.check_ollama_running() if not ollama_ok: logger.warning("⚠️ WARNING: Ollama service may not be available") logger.info(" Please ensure Ollama is installed and running: https://ollama.ai") # Start MT5 MCP server logger.info("🔄 Starting MT5 MCP server...") mt5_ok = await self.start_mt5_server() if not mt5_ok: logger.error("❌ Failed to start MT5 MCP server") return False # Start Ollama MCP server logger.info("🔄 Starting Ollama MCP server...") ollama_server_ok = await self.start_ollama_server() if not ollama_server_ok: logger.error("❌ Failed to start Ollama MCP server") return False # Start web interface logger.info("🔄 Starting web interface...") web_ok = await self.start_web_server() if not web_ok: logger.error("❌ Failed to start web server") return False logger.info("=" * 50) logger.info("✅ ALL SYSTEMS STARTED SUCCESSFULLY!") logger.info("") logger.info("🌐 Access the Trading Chatbot at:") logger.info(f" http://{self.web_host}:{self.web_port}") logger.info("") logger.info("📋 System Status:") logger.info(f" • MT5 MCP Server: http://{self.mt5_host}:{self.mt5_port}") logger.info(f" • Ollama MCP Server: http://{self.ollama_host}:{self.ollama_port}") logger.info(f" • Web Interface: http://{self.web_host}:{self.web_port}") logger.info(f" • Ollama AI Service: http://localhost:11434") logger.info("") logger.info("🔧 Troubleshooting:") logger.info(" • Check MT5 terminal is running and logged in") logger.info(" • Ensure Python dependencies are installed") logger.info(" • Pull models: ollama pull qwen2.5-coder llama3.1") logger.info("") logger.info("🎯 Ready for natural language trading commands!") logger.info("=" * 50) return True def stop_system(self): """Stop all running servers""" logger.info("🛑 Stopping Trading Chatbot System...") processes = [ ("MT5 MCP", self.mt5_process), ("Ollama MCP", self.ollama_process), ("Web server", self.web_process) ] for name, process in processes: if process and process.poll() is None: logger.info(f"Stopping {name}...") try: process.terminate() # Wait up to 5 seconds for graceful shutdown for _ in range(10): if process.poll() is not None: break asyncio.run(asyncio.sleep(0.5)) else: # Force kill if still running process.kill() except Exception as e: logger.error(f"Error stopping {name}: {e}") logger.info("✅ All servers stopped") async def monitor_system(self): """Monitor running servers and restart if necessary""" while True: processes = [ ("MT5 MCP", self.mt5_process, self.start_mt5_server), ("Ollama MCP", self.ollama_process, self.start_ollama_server), ("Web server", self.web_process, self.start_web_server) ] restart_count = 0 for name, process, start_func in processes: if process and process.poll() is not None: logger.warning(f"{name} server crashed, restarting...") try: success = await start_func() if success: logger.info(f"✅ {name} server restarted") restart_count += 1 else: logger.error(f"❌ Failed to restart {name} server") except Exception as e: logger.error(f"Error restarting {name}: {e}") if restart_count > 0: logger.info(f"Restarted {restart_count} servers") await asyncio.sleep(30) # Check every 30 seconds async def main(): """Main function""" parser = argparse.ArgumentParser(description="Trading Chatbot System") parser.add_argument("--mt5-host", default="127.0.0.1", help="MT5 MCP server host") parser.add_argument("--mt5-port", type=int, default=8000, help="MT5 MCP server port") parser.add_argument("--ollama-host", default="127.0.0.1", help="Ollama MCP server host") parser.add_argument("--ollama-port", type=int, default=8001, help="Ollama MCP server port") parser.add_argument("--web-host", default="127.0.0.1", help="Web interface host") parser.add_argument("--web-port", type=int, default=3000, help="Web interface port") parser.add_argument("--command", choices=["start", "stop"], default="start", help="Command to execute") args = parser.parse_args() system = TradingChatbotSystem( mt5_host=args.mt5_host, mt5_port=args.mt5_port, ollama_host=args.ollama_host, ollama_port=args.ollama_port, web_host=args.web_host, web_port=args.web_port ) if args.command == "start": try: # Start the system success = await system.start_system() if not success: logger.error("Failed to start system") return 1 # Keep running and monitor logger.info("System is running. Press Ctrl+C to stop.") # Start monitoring task monitor_task = asyncio.create_task(system.monitor_system()) # Wait for keyboard interrupt def signal_handler(signum, frame): logger.info("Received shutdown signal") import signal signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) try: await monitor_task except KeyboardInterrupt: logger.info("Keyboard interrupt received") except Exception as e: logger.error(f"System error: {e}") return 1 finally: # Cleanup system.stop_system() elif args.command == "stop": # Stop the system system.stop_system() return 0 if __name__ == "__main__": sys.exit(asyncio.run(main()))

Latest Blog Posts

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/Af7007/mcp-trader'

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