run_dual_server.py•4.11 kB
#!/usr/bin/env python3
"""
Dual Server Runner - MCP 서버와 WebSocket 서버를 동시에 실행
"""
import asyncio
import subprocess
import threading
import sys
import os
import signal
import time
# 현재 디렉토리를 Python 경로에 추가
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
import websockets
import json
from connection_manager import connection_manager
class WebSocketWrapper:
"""websockets 라이브러리의 WebSocket을 Starlette WebSocket처럼 사용하기 위한 래퍼"""
def __init__(self, websocket):
self.websocket = websocket
async def send_text(self, text: str):
await self.websocket.send(text)
async def close(self):
await self.websocket.close()
async def websocket_handler(websocket, path):
"""WebSocket 핸들러"""
print(f"[WebSocket] Client connected from {websocket.remote_address}")
wrapped_websocket = WebSocketWrapper(websocket)
try:
await connection_manager.connect(wrapped_websocket)
async for message_str in websocket:
try:
print(f"[WebSocket] Received: {message_str}")
message = json.loads(message_str)
await connection_manager.handle_unreal_response(message)
except json.JSONDecodeError as e:
print(f"[WebSocket] JSON decode error: {e}")
except websockets.exceptions.ConnectionClosed:
print("[WebSocket] Client disconnected")
except Exception as e:
print(f"[WebSocket] Error: {e}")
finally:
await connection_manager.disconnect()
async def start_websocket_server():
"""WebSocket 서버 시작"""
print("[WebSocket] Starting WebSocket server on ws://localhost:6277...")
# websockets 라이브러리의 최신 버전에 맞는 핸들러
async def handler_wrapper(websocket):
await websocket_handler(websocket, "/")
server = await websockets.serve(
handler_wrapper,
"localhost",
6277
)
print("[WebSocket] WebSocket server started successfully on port 6277")
await server.wait_closed()
def start_mcp_server():
"""MCP 서버 시작 (별도 프로세스)"""
print("[MCP] Starting FastMCP server...")
cmd = [
sys.executable, "-m", "fastmcp", "run",
"unreal_blueprint_mcp_server.py"
]
process = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
cwd=os.path.dirname(os.path.abspath(__file__))
)
print(f"[MCP] FastMCP server started (PID: {process.pid})")
return process
def signal_handler(signum, frame):
"""시그널 핸들러"""
print("\n[SYSTEM] Shutting down servers...")
sys.exit(0)
async def main():
"""메인 함수"""
print("=" * 60)
print(" Unreal Blueprint MCP Server - Dual Server Mode")
print("=" * 60)
# 시그널 핸들러 등록
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
try:
# MCP 서버 시작 (별도 프로세스)
mcp_process = start_mcp_server()
# 잠시 대기
await asyncio.sleep(2)
print("\n[SYSTEM] Servers started successfully!")
print("[MCP] MCP tools available via STDIO")
print("[WebSocket] WebSocket server available at ws://localhost:6277")
print("[INFO] Press Ctrl+C to stop both servers")
print()
# WebSocket 서버 시작 (현재 프로세스)
await start_websocket_server()
except KeyboardInterrupt:
print("\n[SYSTEM] Keyboard interrupt received")
except Exception as e:
print(f"\n[ERROR] Server error: {e}")
finally:
# MCP 서버 종료
if 'mcp_process' in locals():
print("[MCP] Terminating FastMCP server...")
mcp_process.terminate()
mcp_process.wait()
print("[SYSTEM] All servers stopped")
if __name__ == "__main__":
try:
asyncio.run(main())
except KeyboardInterrupt:
print("\n[SYSTEM] Shutdown complete")