|
6 | 6 | useful for validating that Lightspeed Core Stack correctly sends auth headers |
7 | 7 | to MCP servers. |
8 | 8 |
|
9 | | -The server runs both HTTP and HTTPS simultaneously on consecutive ports. |
| 9 | +The server runs HTTP and optionally HTTPS on consecutive ports. |
| 10 | +Set MCP_HTTP_ONLY=true to disable HTTPS (useful when openssl is unavailable). |
10 | 11 |
|
11 | 12 | Usage: |
12 | 13 | python server.py [http_port] |
13 | 14 |
|
14 | 15 | Example: |
15 | 16 | python server.py 3000 # HTTP on 3000, HTTPS on 3001 |
| 17 | + MCP_HTTP_ONLY=true python server.py 3000 # HTTP only on 3000 |
16 | 18 | """ |
17 | 19 |
|
18 | 20 | import json |
| 21 | +import os |
19 | 22 | import ssl |
20 | 23 | import subprocess |
21 | 24 | import sys |
@@ -268,61 +271,79 @@ def run_https_server(port: int, httpd: HTTPServer) -> None: |
268 | 271 |
|
269 | 272 |
|
270 | 273 | def main() -> None: |
271 | | - """Start the mock MCP server with both HTTP and HTTPS.""" |
| 274 | + """Start the mock MCP server with HTTP and optionally HTTPS.""" |
272 | 275 | http_port = int(sys.argv[1]) if len(sys.argv) > 1 else 3000 |
273 | | - https_port = http_port + 1 |
| 276 | + http_only = os.environ.get("MCP_HTTP_ONLY", "").lower() in ("true", "1", "yes") |
274 | 277 |
|
275 | 278 | # Create HTTP server |
276 | 279 | http_server = HTTPServer(("", http_port), MCPMockHandler) |
277 | 280 |
|
278 | | - # Create HTTPS server with self-signed certificate |
279 | | - https_server = HTTPServer(("", https_port), MCPMockHandler) |
280 | | - |
281 | | - # Generate or load self-signed certificate |
282 | | - script_dir = Path(__file__).parent |
283 | | - cert_dir = script_dir / ".certs" |
284 | | - cert_file, key_file = generate_self_signed_cert(cert_dir) |
285 | | - |
286 | | - # Wrap socket with SSL |
287 | | - context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) |
288 | | - context.load_cert_chain(cert_file, key_file) |
289 | | - https_server.socket = context.wrap_socket(https_server.socket, server_side=True) |
| 281 | + https_server = None |
| 282 | + if not http_only: |
| 283 | + try: |
| 284 | + https_port = http_port + 1 |
| 285 | + https_server = HTTPServer(("", https_port), MCPMockHandler) |
| 286 | + |
| 287 | + # Generate or load self-signed certificate |
| 288 | + script_dir = Path(__file__).parent |
| 289 | + cert_dir = script_dir / ".certs" |
| 290 | + cert_file, key_file = generate_self_signed_cert(cert_dir) |
| 291 | + |
| 292 | + # Wrap socket with SSL |
| 293 | + context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) |
| 294 | + context.load_cert_chain(cert_file, key_file) |
| 295 | + https_server.socket = context.wrap_socket( |
| 296 | + https_server.socket, server_side=True |
| 297 | + ) |
| 298 | + except (subprocess.CalledProcessError, FileNotFoundError, OSError) as e: |
| 299 | + print(f"HTTPS setup failed ({e}), running HTTP only") |
| 300 | + https_server = None |
290 | 301 |
|
291 | 302 | print("=" * 70) |
292 | | - print("MCP Mock Server starting with HTTP and HTTPS") |
| 303 | + if https_server: |
| 304 | + print("MCP Mock Server starting with HTTP and HTTPS") |
| 305 | + else: |
| 306 | + print("MCP Mock Server starting (HTTP only)") |
293 | 307 | print("=" * 70) |
294 | 308 | print(f"HTTP: http://localhost:{http_port}") |
295 | | - print(f"HTTPS: https://localhost:{https_port}") |
| 309 | + if https_server: |
| 310 | + print(f"HTTPS: https://localhost:{https_port}") |
296 | 311 | print("=" * 70) |
297 | 312 | print("Debug endpoints:") |
298 | 313 | print(" • /debug/headers - View captured headers") |
299 | 314 | print(" • /debug/requests - View request log") |
300 | 315 | print("MCP endpoint:") |
301 | 316 | print(" • POST to any path (e.g., / or /mcp/v1/list_tools)") |
302 | 317 | print("=" * 70) |
303 | | - print("Note: HTTPS uses a self-signed certificate (for testing only)") |
| 318 | + if https_server: |
| 319 | + print("Note: HTTPS uses a self-signed certificate (for testing only)") |
304 | 320 | print("Press Ctrl+C to stop") |
305 | 321 | print() |
306 | 322 |
|
307 | | - # Start servers in separate threads |
| 323 | + # Start HTTP server in a thread |
308 | 324 | http_thread = threading.Thread( |
309 | 325 | target=run_http_server, args=(http_port, http_server), daemon=True |
310 | 326 | ) |
311 | | - https_thread = threading.Thread( |
312 | | - target=run_https_server, args=(https_port, https_server), daemon=True |
313 | | - ) |
314 | | - |
315 | 327 | http_thread.start() |
316 | | - https_thread.start() |
| 328 | + |
| 329 | + # Start HTTPS server if available |
| 330 | + https_thread = None |
| 331 | + if https_server: |
| 332 | + https_thread = threading.Thread( |
| 333 | + target=run_https_server, args=(https_port, https_server), daemon=True |
| 334 | + ) |
| 335 | + https_thread.start() |
317 | 336 |
|
318 | 337 | try: |
319 | 338 | # Keep main thread alive |
320 | 339 | http_thread.join() |
321 | | - https_thread.join() |
| 340 | + if https_thread: |
| 341 | + https_thread.join() |
322 | 342 | except KeyboardInterrupt: |
323 | 343 | print("\nShutting down mock servers...") |
324 | 344 | http_server.shutdown() |
325 | | - https_server.shutdown() |
| 345 | + if https_server: |
| 346 | + https_server.shutdown() |
326 | 347 |
|
327 | 348 |
|
328 | 349 | if __name__ == "__main__": |
|
0 commit comments