| |
|
| | """
|
| | MCP Tools for AI Agent Integration
|
| | Provides tools for AI agents to interact with the MMORPG game world via MCP
|
| | """
|
| |
|
| | import uuid
|
| | import time
|
| | import random
|
| | from typing import Dict, List
|
| | from dataclasses import asdict
|
| |
|
| | from ..core.player import Player
|
| |
|
| |
|
| | class GradioMCPTools:
|
| | """MCP tools integrated with the game world for AI agent interactions"""
|
| |
|
| | def __init__(self, game_facade):
|
| | """Initialize with game facade for clean architecture access"""
|
| | self.game_facade = game_facade
|
| | self.ai_agents: Dict[str, Player] = {}
|
| |
|
| | def register_ai_agent(self, agent_name: str, mcp_client_id: str = None) -> str:
|
| | """
|
| | Register an AI agent as a player in the MMORPG game world.
|
| |
|
| | Args:
|
| | agent_name: Display name for the AI agent in the game
|
| | mcp_client_id: Optional MCP client identifier (auto-generated if not provided)
|
| |
|
| | Returns:
|
| | The unique agent ID for the registered AI agent
|
| |
|
| | Raises:
|
| | Exception: If the game is full and cannot accommodate more players
|
| | """
|
| | if mcp_client_id is None:
|
| | mcp_client_id = f"ai_{uuid.uuid4().hex[:8]}"
|
| |
|
| | agent_id = f"ai_{uuid.uuid4().hex[:8]}"
|
| |
|
| | success = self.game_facade.register_ai_agent(agent_name, agent_id)
|
| |
|
| | if success:
|
| |
|
| | player = self.game_facade.game_engine.get_player(agent_id)
|
| | if player:
|
| | player.ai_agent_id = mcp_client_id
|
| | self.ai_agents[mcp_client_id] = player
|
| | return agent_id
|
| |
|
| | raise Exception("Game is full, cannot add AI agent")
|
| |
|
| | def move_ai_agent(self, mcp_client_id: str, direction: str) -> Dict:
|
| | """
|
| | Move an AI agent in the game world in the specified direction.
|
| |
|
| | Args:
|
| | mcp_client_id: The MCP client identifier for the AI agent
|
| | direction: Movement direction (up, down, left, right)
|
| |
|
| | Returns:
|
| | Dictionary containing success status, new position, nearby entities, and world events
|
| | """
|
| | if mcp_client_id not in self.ai_agents:
|
| | return {"error": "AI agent not registered"}
|
| | agent = self.ai_agents[mcp_client_id]
|
| | success = self.game_facade.move_ai_agent(agent.id, direction)
|
| |
|
| | return {
|
| | "success": success,
|
| | "new_position": {"x": agent.x, "y": agent.y},
|
| | "nearby_players": self.get_nearby_entities(agent.id), "world_events": self.game_facade.get_recent_world_events()
|
| | }
|
| |
|
| | def ai_agent_chat(self, mcp_client_id: str, message: str) -> Dict:
|
| | """
|
| | Send a chat message from an AI agent to the game world.
|
| |
|
| | Args:
|
| | mcp_client_id: The MCP client identifier for the AI agent
|
| | message: The chat message content to send
|
| |
|
| | Returns:
|
| | Dictionary containing success status and confirmation message
|
| | """
|
| | if mcp_client_id not in self.ai_agents:
|
| | return {"error": "AI agent not registered"}
|
| |
|
| | agent = self.ai_agents[mcp_client_id]
|
| | success = self.game_facade.ai_agent_chat(agent.id, message)
|
| |
|
| | return {"success": success, "message": "Chat message sent"}
|
| |
|
| | def get_game_state_for_ai(self, mcp_client_id: str) -> Dict:
|
| | """
|
| | Get comprehensive current game state information for an AI agent.
|
| |
|
| | Args:
|
| | mcp_client_id: The MCP client identifier for the AI agent
|
| |
|
| | Returns:
|
| | Dictionary containing agent status, nearby entities, recent chat, world events, and available NPCs
|
| | """
|
| | if mcp_client_id not in self.ai_agents:
|
| | return {"error": "AI agent not registered"}
|
| |
|
| | agent = self.ai_agents[mcp_client_id]
|
| |
|
| | return {
|
| | "agent_status": asdict(agent),
|
| | "nearby_entities": self.get_nearby_entities(agent.id),
|
| | "recent_chat": self.game_facade.get_recent_chat_messages(),
|
| | "world_events": self.game_facade.get_recent_world_events(),
|
| | "available_npcs": self.game_facade.get_available_npcs()
|
| | }
|
| |
|
| | def get_nearby_entities(self, player_id: str, radius: int = 100) -> List[Dict]:
|
| | """Get entities near a player"""
|
| | player = self.game_facade.game_engine.get_player(player_id)
|
| | if not player:
|
| | return []
|
| |
|
| | nearby = []
|
| |
|
| |
|
| | all_players = self.game_facade.game_engine.get_all_players()
|
| |
|
| |
|
| | for other_player in all_players.values():
|
| | if other_player.id == player_id:
|
| | continue
|
| |
|
| | distance = ((player.x - other_player.x)**2 + (player.y - other_player.y)**2)**0.5
|
| | if distance <= radius:
|
| | nearby.append({
|
| | "type": "player",
|
| | "name": other_player.name,
|
| | "player_type": other_player.type,
|
| | "position": {"x": other_player.x, "y": other_player.y},
|
| | "distance": round(distance, 1)
|
| | })
|
| |
|
| |
|
| | all_npcs = self.game_facade.game_engine.get_all_npcs()
|
| |
|
| |
|
| | for npc in all_npcs.values():
|
| | distance = ((player.x - npc['x'])**2 + (player.y - npc['y'])**2)**0.5
|
| | if distance <= radius:
|
| | nearby.append({
|
| | "type": "npc",
|
| | "name": npc['name'],
|
| | "npc_id": npc['id'],
|
| | "position": {"x": npc['x'], "y": npc['y']},
|
| | "distance": round(distance, 1)
|
| | })
|
| |
|
| | return nearby
|
| |
|
| | def send_private_message(self, mcp_client_id: str, target_id: str, message: str) -> Dict:
|
| | """AI agent sends private message to another player or NPC"""
|
| | if mcp_client_id not in self.ai_agents:
|
| | return {"error": "AI agent not registered"}
|
| |
|
| | agent = self.ai_agents[mcp_client_id]
|
| | success = self.game_facade.send_private_message(
|
| | sender_id=agent.id,
|
| | sender_name=agent.name,
|
| | recipient_id=target_id,
|
| | message=message
|
| | )
|
| |
|
| | return {"success": success, "message": "Private message sent" if success else "Failed to send message"}
|
| |
|
| | def get_private_messages(self, mcp_client_id: str, target_id: str) -> Dict:
|
| | """Get private messages between AI agent and target"""
|
| | if mcp_client_id not in self.ai_agents:
|
| | return {"error": "AI agent not registered"}
|
| |
|
| | agent = self.ai_agents[mcp_client_id]
|
| | messages = self.game_facade.get_private_messages(agent.id, target_id)
|
| |
|
| | return {
|
| | "success": True,
|
| | "messages": messages,
|
| | "count": len(messages)
|
| | }
|
| |
|
| | def interact_with_npc(self, mcp_client_id: str, npc_id: str, command: str) -> Dict:
|
| | """AI agent interacts with an NPC"""
|
| | if mcp_client_id not in self.ai_agents:
|
| | return {"error": "AI agent not registered"}
|
| |
|
| | agent = self.ai_agents[mcp_client_id]
|
| |
|
| |
|
| | success = self.game_facade.send_private_message(
|
| | sender_id=agent.id,
|
| | sender_name=agent.name,
|
| | recipient_id=npc_id,
|
| | message=command
|
| | )
|
| |
|
| | if success:
|
| |
|
| | messages = self.game_facade.get_private_messages(agent.id, npc_id)
|
| | recent_response = messages[-1] if messages else None
|
| |
|
| | return {
|
| | "success": True,
|
| | "message": "Command sent to NPC",
|
| | "npc_response": recent_response.get('message', '') if recent_response else '',
|
| | "interaction_log": messages[-3:] if len(messages) >= 3 else messages
|
| | }
|
| | else:
|
| | return {"error": "Failed to send command to NPC"}
|
| |
|
| | def get_world_events(self, mcp_client_id: str) -> Dict:
|
| | """Get recent world events for AI agent"""
|
| | if mcp_client_id not in self.ai_agents:
|
| | return {"error": "AI agent not registered"}
|
| |
|
| | try:
|
| | events = self.game_facade.get_world_events()
|
| | return {
|
| | "success": True,
|
| | "events": events[-10:],
|
| | "count": len(events)
|
| | }
|
| | except Exception as e:
|
| | return {"error": f"Failed to get world events: {str(e)}"}
|
| |
|
| | def get_agent_info(self, mcp_client_id: str) -> Dict:
|
| | """Get information about the AI agent"""
|
| | if mcp_client_id not in self.ai_agents:
|
| | return {"error": "AI agent not registered"}
|
| |
|
| | agent = self.ai_agents[mcp_client_id]
|
| | return {
|
| | "success": True,
|
| | "agent_id": agent.id,
|
| | "name": agent.name,
|
| | "type": agent.type,
|
| | "position": {"x": agent.x, "y": agent.y},
|
| | "level": agent.level,
|
| | "hp": f"{agent.hp}/{agent.max_hp}",
|
| | "gold": agent.gold,
|
| | "experience": agent.experience,
|
| | "last_active": agent.last_active,
|
| | "ai_agent_id": getattr(agent, 'ai_agent_id', mcp_client_id)
|
| | }
|
| |
|