File size: 5,737 Bytes
8372659
1af10cc
8372659
 
 
 
12c95f8
1af10cc
12c95f8
 
1af10cc
 
8372659
bd84a4f
1af10cc
12c95f8
1af10cc
 
 
 
12c95f8
1af10cc
 
def69a7
1af10cc
def69a7
 
12c95f8
 
def69a7
1af10cc
12c95f8
 
 
 
 
 
1af10cc
12c95f8
 
 
1af10cc
12c95f8
 
 
 
 
 
1af10cc
12c95f8
 
 
 
 
 
 
 
 
 
 
1af10cc
 
12c95f8
 
8372659
 
1af10cc
 
 
8372659
1af10cc
 
 
 
 
 
12c95f8
 
1af10cc
 
 
 
 
 
 
 
 
 
 
 
 
 
8372659
 
def69a7
1af10cc
 
 
 
 
 
 
 
 
 
 
def69a7
8372659
1af10cc
 
 
 
 
8372659
 
1af10cc
8372659
bbd9cd6
1af10cc
8372659
 
 
1af10cc
bbd9cd6
1af10cc
8372659
 
1af10cc
 
bd84a4f
 
bbd9cd6
 
 
1af10cc
bbd9cd6
1af10cc
def69a7
8372659
12c95f8
 
 
 
 
 
8372659
 
1af10cc
 
 
 
8372659
1af10cc
 
 
 
12c95f8
 
1af10cc
 
12c95f8
 
 
 
 
 
1af10cc
 
 
 
12c95f8
 
8372659
1af10cc
 
12c95f8
1af10cc
 
 
 
 
 
 
 
12c95f8
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
"""
Script to run either the MCP server or the Gradio interface for TutorX
"""

import os
import sys
import time
import argparse
import subprocess
import multiprocessing
from pathlib import Path
import socket

def run_mcp_server(host="0.0.0.0", port=8000, debug=False):
    """
    Run the MCP server using uv
    
    Args:
        host: Host to bind the server to
        port: Port to run the server on
        debug: Whether to run in debug mode
    """
    print(f"Starting TutorX MCP Server on {host}:{port}...")
    
    # Set environment variables
    os.environ["MCP_HOST"] = host
    os.environ["MCP_PORT"] = str(port)
    if debug:
        os.environ["DEBUG"] = "1"
    
    try:
        # Build the command to run the server using uv
        cmd = [
            "uv", "run", "-m", "mcp_server.server",
            "--host", host,
            "--port", str(port)
        ]
        
        # Add debug flag if needed
        if debug:
            cmd.append("--debug")
        
        # Execute the command
        server_process = subprocess.Popen(
            cmd,
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,
            universal_newlines=True
        )
        
        # Print the first few lines of output to confirm server started
        for _ in range(5):
            line = server_process.stdout.readline()
            if not line:
                break
            print(line.strip())
        
        # Return the process so it can be managed by the caller
        return server_process
        
    except Exception as e:
        print(f"Error starting MCP server: {e}")
        print("Make sure you have installed all required dependencies:")
        print("  pip install uv")
        sys.exit(1)

def run_gradio_interface(port=7860):
    """
    Run the Gradio interface
    
    Args:
        port: Port to run the Gradio interface on
    """
    print(f"Starting TutorX Gradio Interface on port {port}...")
    
    try:
        # Make sure the mcp_server directory is in the path
        mcp_server_dir = str(Path(__file__).parent / "mcp_server")
        if mcp_server_dir not in sys.path:
            sys.path.insert(0, mcp_server_dir)
            
        # Import and run the Gradio app
        from app import demo
        
        # Launch the Gradio interface
        demo.launch(
            server_name="0.0.0.0",
            server_port=port,
            share=False
        )
    except Exception as e:
        print(f"Failed to start Gradio interface: {e}")
        sys.exit(1)

def check_port_available(port):
    """
    Check if a port is available
    
    Args:
        port: Port number to check
        
    Returns:
        bool: True if port is available, False otherwise
    """
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        return s.connect_ex(('localhost', port)) != 0

if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        description="TutorX - Run MCP Server and/or Gradio Interface"
    )
    
    # Add command line arguments
    parser.add_argument(
        "--mode", 
        type=str, 
        choices=["mcp", "gradio", "both"], 
        default="both",
        help="Run mode: 'mcp' for MCP server, 'gradio' for Gradio interface, 'both' for both (default)"
    )
    parser.add_argument(
        "--host", 
        type=str, 
        default="0.0.0.0",
        help="Host to bind the server to (default: 0.0.0.0)"
    )
    parser.add_argument(
        "--mcp-port", 
        type=int, 
        default=8000,
        help="Port for MCP server (default: 8000)"
    )
    parser.add_argument(
        "--gradio-port", 
        type=int, 
        default=7860,
        help="Port for Gradio interface (default: 7860)"
    )
    
    parser.add_argument(
        "--debug", 
        action="store_true",
        help="Run with debug mode for more verbose output"
    )
    
    args = parser.parse_args()
    
    # Check if ports are available
    if args.mode in ["mcp", "both"] and not check_port_available(args.mcp_port):
        print(f"Error: Port {args.mcp_port} is already in use (MCP server)")
        sys.exit(1)
        
    if args.mode in ["gradio", "both"] and not check_port_available(args.gradio_port):
        print(f"Error: Port {args.gradio_port} is already in use (Gradio interface)")
        sys.exit(1)
    
    server_process = None
    
    try:
        if args.mode in ["mcp", "both"]:
            # Start MCP server using uv run
            print("Starting MCP server...")
            server_process = run_mcp_server(
                host=args.host,
                port=args.mcp_port,
                debug=args.debug
            )
            
            # Give the server a moment to start
            time.sleep(2)
            print(f"MCP server running at http://{args.host}:{args.mcp_port}")
            print(f"MCP SSE endpoint available at http://{args.host}:{args.mcp_port}/sse")
        
        if args.mode in ["gradio", "both"]:
            # Run Gradio in the main process
            print(f"Starting Gradio interface on port {args.gradio_port}...")
            run_gradio_interface(port=args.gradio_port)
            
    except KeyboardInterrupt:
        print("\nShutting down...")
    except Exception as e:
        print(f"Error: {e}")
        sys.exit(1)
    finally:
        # Clean up the server process if it's running
        if server_process is not None:
            print("Terminating MCP server...")
            server_process.terminate()
            try:
                server_process.wait(timeout=5)
            except subprocess.TimeoutExpired:
                server_process.kill()
                print("Server process killed after timeout")