get_player_heroes
Retrieve a player's most frequently played Dota 2 heroes with performance statistics by providing their Steam32 account ID and optional limit parameter.
Instructions
Get a player's most played heroes.
Args:
account_id: Steam32 account ID of the player
limit: Number of heroes to retrieve (default: 5)
Returns:
List of most played heroes with stats
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | Yes | ||
| limit | No |
Implementation Reference
- src/opendota_server/server.py:543-630 (handler)The primary handler function for the 'get_player_heroes' tool. It fetches hero usage data from the OpenDota API for a given player account_id, sorts by games played, maps hero IDs to names, and formats the top 'limit' heroes with games, wins, win rate, and last played date. The @mcp.tool() decorator registers it as an MCP tool.@mcp.tool() async def get_player_heroes(account_id: int, limit: int = 5) -> str: """Get a player's most played heroes. Args: account_id: Steam32 account ID of the player limit: Number of heroes to retrieve (default: 5) Returns: List of most played heroes with stats """ if limit > 20: limit = 20 # Cap for reasonable response size # Get hero usage data heroes_data = await make_opendota_request(f"players/{account_id}/heroes") if "error" in heroes_data: return f"Error retrieving heroes data: {heroes_data['error']}" if not heroes_data or not isinstance(heroes_data, list) or len(heroes_data) == 0: return "No hero data found for this player." # Get hero lookup table from cache or API heroes_names = await make_opendota_request("heroes") hero_id_to_name = {} if isinstance(heroes_names, list) and heroes_names: # Process the heroes data to create a mapping for hero in heroes_names: if isinstance(hero, dict) and "id" in hero and "localized_name" in hero: hero_id = hero.get("id") hero_name = hero.get("localized_name") if hero_id is not None and hero_name is not None: hero_id_to_name[hero_id] = hero_name else: # Fallback to a minimal hero dictionary if API fails logger.warning("Failed to get hero names, using fallback dictionary") hero_id_to_name = { 1: "Anti-Mage", 2: "Axe", 3: "Bane", 4: "Bloodseeker", 5: "Crystal Maiden", 6: "Drow Ranger", 7: "Earthshaker", 8: "Juggernaut", 9: "Mirana", 10: "Morphling", 11: "Shadow Fiend", 12: "Phantom Lancer", 13: "Puck", 14: "Pudge", 15: "Razor", # This is just a small sample of common heroes } try: # Sort heroes by games played sorted_heroes = sorted( heroes_data, key=lambda x: x.get("games", 0), reverse=True ) formatted_heroes = [] for i, hero in enumerate(sorted_heroes[:limit]): hero_id = hero.get("hero_id", 0) hero_name = hero_id_to_name.get(hero_id, f"Hero {hero_id}") games = hero.get("games", 0) wins = hero.get("win", 0) win_rate = (wins / games * 100) if games > 0 else 0 last_played = format_timestamp(hero.get("last_played", 0)) formatted_heroes.append( f"{i+1}. {hero_name} (ID: {hero_id})\n" f" Games: {games}\n" f" Wins: {wins}\n" f" Win Rate: {win_rate:.2f}%\n" f" Last Played: {last_played}" ) return f"Most Played Heroes for Player ID {account_id}:\n\n" + "\n\n".join( formatted_heroes ) except Exception as e: logger.error(f"Error formatting hero data: {e}") return f"Error processing heroes data: {str(e)}"