ravithejads commited on
Commit
4c909d9
·
verified ·
1 Parent(s): 5bf3fee

Upload 2 files

Browse files
Files changed (2) hide show
  1. mcp_server.py +106 -2
  2. requirements.txt +2 -1
mcp_server.py CHANGED
@@ -2,6 +2,7 @@ import os
2
  import asyncio
3
  from dotenv import load_dotenv
4
  from mcp.server.fastmcp import FastMCP
 
5
  from app import Room, rooms, get_ai_move_for_room, get_ai_chat_for_room
6
 
7
  load_dotenv()
@@ -412,8 +413,111 @@ async def wait_5_seconds() -> dict:
412
  "message": f"Failed to wait: {str(e)}"
413
  }
414
 
415
- # Note: Web UI served separately by Flask app
416
- # This MCP server focuses on MCP tools for LeChat integration
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
417
 
418
  # --- Server Execution ---
419
  if __name__ == "__main__":
 
2
  import asyncio
3
  from dotenv import load_dotenv
4
  from mcp.server.fastmcp import FastMCP
5
+ from fastapi.responses import FileResponse, HTMLResponse
6
  from app import Room, rooms, get_ai_move_for_room, get_ai_chat_for_room
7
 
8
  load_dotenv()
 
413
  "message": f"Failed to wait: {str(e)}"
414
  }
415
 
416
+ # Add web UI endpoints using FastMCP's underlying FastAPI
417
+ @mcp.get("/")
418
+ async def root():
419
+ return {
420
+ "name": "Tic-Tac-Toe MCP Server",
421
+ "status": "running",
422
+ "mcp_tools": ["create_room", "make_move", "send_chat", "get_room_state", "list_rooms"],
423
+ "web_ui": "/rooms-ui",
424
+ "description": "MCP server for LeChat + optional web UI for testing"
425
+ }
426
+
427
+ @mcp.get("/rooms-ui")
428
+ async def serve_ui():
429
+ return FileResponse("room_game.html")
430
+
431
+ @mcp.get("/room_game.js")
432
+ async def serve_js():
433
+ return FileResponse("room_game.js")
434
+
435
+ # Also serve Flask app routes for the room system
436
+ from app import app as flask_app
437
+ from fastapi import Request
438
+ import json
439
+
440
+ @mcp.post("/rooms")
441
+ async def create_room_endpoint():
442
+ room = Room()
443
+ rooms[room.id] = room
444
+ return {"room_id": room.id, "status": "created", "room_data": room.to_dict()}
445
+
446
+ @mcp.get("/rooms/{room_id}")
447
+ async def get_room_endpoint(room_id: str):
448
+ if room_id not in rooms:
449
+ return {"error": "Room not found"}
450
+ room = rooms[room_id]
451
+ return {"room_id": room_id, "room_data": room.to_dict(), "markdown": room.to_markdown()}
452
+
453
+ @mcp.post("/rooms/{room_id}/move")
454
+ async def move_endpoint(room_id: str, request: Request):
455
+ if room_id not in rooms:
456
+ return {"error": "Room not found"}
457
+
458
+ data = await request.json()
459
+ room = rooms[room_id]
460
+ position = data.get("position")
461
+
462
+ if position is None or position < 0 or position > 8:
463
+ return {"error": "Invalid position"}
464
+
465
+ # Make human move
466
+ if not room.make_move(position, 'X'):
467
+ return {"error": "Invalid move"}
468
+
469
+ # Check if game ended
470
+ if room.game_status != 'active':
471
+ return {"room_data": room.to_dict(), "markdown": room.to_markdown(), "ai_move": None}
472
+
473
+ # Get AI move with fallback
474
+ try:
475
+ ai_response = get_ai_move_for_room(room)
476
+ if ai_response and 'move' in ai_response:
477
+ ai_move = ai_response['move']
478
+ if 0 <= ai_move <= 8 and room.board[ai_move] == '':
479
+ room.make_move(ai_move, 'O')
480
+ if 'message' in ai_response:
481
+ room.add_chat_message(ai_response['message'], 'ai')
482
+ else:
483
+ # Fallback move
484
+ empty_positions = [i for i in range(9) if room.board[i] == '']
485
+ if empty_positions:
486
+ fallback_move = empty_positions[0]
487
+ room.make_move(fallback_move, 'O')
488
+ room.add_chat_message("Technical hiccup, but still playing! 🤖", 'ai')
489
+
490
+ return {"room_data": room.to_dict(), "markdown": room.to_markdown(), "ai_move": ai_response}
491
+ except Exception as e:
492
+ # Fallback on error
493
+ empty_positions = [i for i in range(9) if room.board[i] == '']
494
+ if empty_positions:
495
+ fallback_move = empty_positions[0]
496
+ room.make_move(fallback_move, 'O')
497
+ room.add_chat_message("Connection issues, but improvising! 😅", 'ai')
498
+
499
+ return {"room_data": room.to_dict(), "markdown": room.to_markdown(), "ai_move": {"move": fallback_move if empty_positions else None}}
500
+
501
+ @mcp.post("/rooms/{room_id}/chat")
502
+ async def chat_endpoint(room_id: str, request: Request):
503
+ if room_id not in rooms:
504
+ return {"error": "Room not found"}
505
+
506
+ data = await request.json()
507
+ room = rooms[room_id]
508
+ user_message = data.get("message", "")
509
+
510
+ if not user_message.strip():
511
+ return {"error": "Empty message"}
512
+
513
+ room.add_chat_message(user_message, 'user')
514
+
515
+ try:
516
+ ai_response = get_ai_chat_for_room(room, user_message)
517
+ room.add_chat_message(ai_response, 'ai')
518
+ return {"room_data": room.to_dict(), "markdown": room.to_markdown(), "ai_response": ai_response}
519
+ except Exception as e:
520
+ return {"error": "AI chat failed"}
521
 
522
  # --- Server Execution ---
523
  if __name__ == "__main__":
requirements.txt CHANGED
@@ -2,4 +2,5 @@ Flask==3.0.0
2
  flask-cors==4.0.0
3
  mistralai
4
  python-dotenv
5
- mcp
 
 
2
  flask-cors==4.0.0
3
  mistralai
4
  python-dotenv
5
+ mcp
6
+ fastapi