"""
CanRun Game Compatibility Checker - Simple MCP Server Implementation
"""
import gradio as gr
import logging
import os
import signal
import sys
import time
import asyncio
import base64
import platform
# Platform detection
IS_WINDOWS = platform.system() == "Windows"
from src.canrun_engine import CanRunEngine
from plugin import CanRunGAssistPlugin
# Configure logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s",
handlers=[logging.StreamHandler(sys.stdout)]
)
logger = logging.getLogger(__name__)
def signal_handler(signum, frame):
"""Handle shutdown signals gracefully."""
logger.info(f"Received signal {signum}, shutting down gracefully...")
sys.exit(0)
async def analyze_game(game_name):
"""Analyze game compatibility using the CanRun engine"""
if not game_name:
return "Please enter a game name to begin the analysis."
try:
plugin = CanRunGAssistPlugin()
params = {"game_name": game_name, "force_refresh": True}
# Properly await the async method
response = await plugin.check_game_compatibility(params)
if response.get("success", False):
return response.get("message", "Analysis completed successfully.")
else:
return response.get("message", "Could not analyze the game. Please check the game name and try again.")
except Exception as e:
logger.error(f"Error analyzing game: {e}")
return f"An error occurred during analysis: {e}"
def detect_hardware():
"""Detect hardware specifications"""
try:
plugin = CanRunGAssistPlugin()
response = plugin.detect_hardware({})
if response.get("success", False):
return response.get("message", "Hardware detection successful.")
else:
return response.get("message", "Could not detect hardware specifications.")
except Exception as e:
logger.error(f"Error detecting hardware: {e}")
return f"An error occurred during hardware detection: {e}"
def get_logo_html():
"""Get HTML that displays the logo"""
logo_path = os.path.join(os.path.dirname(__file__), "logo.png")
if os.path.exists(logo_path):
# Read the logo file and encode it as base64
with open(logo_path, "rb") as image_file:
encoded_image = base64.b64encode(image_file.read()).decode("utf-8")
# Return HTML that displays the logo
return f"""
CanRun Game Compatibility Checker
Check if your PC can run any game with an advanced tier system and Steam API integration
"""
else:
logger.warning(f"Logo file not found at {logo_path}")
return """
CanRun Game Compatibility Checker
Check if your PC can run any game with an advanced tier system and Steam API integration
"""
def create_gradio_interface():
"""Create a simple Gradio interface with logo and favicon"""
# Set custom theme with brand color matching the logo
theme = gr.themes.Default(
primary_hue="green",
secondary_hue="gray",
)
# Define file paths
favicon_path = os.path.join(os.path.dirname(__file__), "logo.png")
with gr.Blocks(theme=theme, title="CanRun - Game Compatibility Checker", css="") as demo:
# Header with logo
gr.HTML(get_logo_html())
# Main content
with gr.Row():
with gr.Column():
game_input = gr.Textbox(label="Game Name", placeholder="Enter game name (e.g., Diablo 4)")
check_btn = gr.Button("Check Compatibility", variant="primary")
hw_btn = gr.Button("Detect Hardware", variant="secondary")
with gr.Column():
result_output = gr.Textbox(label="Results", lines=20)
# Footer
gr.HTML("""
CanRun - Advanced Game Compatibility Checker with MCP Server Support
Powered by G-Assist Integration
""")
# For async functions, we need to use .click(fn=..., inputs=..., outputs=...)
check_btn.click(fn=analyze_game, inputs=game_input, outputs=result_output)
hw_btn.click(fn=detect_hardware, inputs=None, outputs=result_output)
return demo
def is_mcp_available():
"""Check if the MCP package is available"""
try:
import mcp
return True
except ImportError:
return False
def main():
"""Main application entry point"""
# Set up signal handlers
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
logger.info("Starting CanRun Game Compatibility Checker")
# Create Gradio interface
demo = create_gradio_interface()
# Check if MCP support is available
mcp_enabled = is_mcp_available()
if mcp_enabled:
logger.info("MCP server functionality is enabled")
else:
logger.info("MCP server functionality is disabled. Install with 'pip install \"gradio[mcp]\"' to enable")
# Launch with auto port discovery
launch_kwargs = {
"server_name": "0.0.0.0",
"share": False,
"favicon_path": os.path.join(os.path.dirname(__file__), "logo.png"),
}
# Only enable MCP server if the package is available
if mcp_enabled:
launch_kwargs["mcp_server"] = True
# Launch the server
demo.queue().launch(**launch_kwargs)
# Keep the main thread alive - Platform-independent approach
logger.info("Press Ctrl+C to stop the server")
try:
# This works on most systems and is more reliable than signal.pause()
while True:
time.sleep(1)
except KeyboardInterrupt:
logger.info("Keyboard interrupt received, shutting down...")
sys.exit(0)
if __name__ == "__main__":
main()