Skip to main content
Glama

get_match_heroes

Retrieve the list of heroes selected by each player in a specific Dota 2 match using the match ID to analyze team compositions and individual picks.

Instructions

Get heroes played in a specific match.

Args: match_id: ID of the match to retrieve Returns: List of heroes played by each player in the match

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
match_idYes

Implementation Reference

  • The main handler function for the 'get_match_heroes' tool. It fetches match data from the OpenDota API, retrieves hero names, processes players from radiant and dire teams, and formats a string output listing heroes and KDA for each player.
    @mcp.tool() async def get_match_heroes(match_id: int) -> str: """Get heroes played in a specific match. Args: match_id: ID of the match to retrieve Returns: List of heroes played by each player in the match """ match_data = await make_opendota_request(f"matches/{match_id}") if "error" in match_data: return f"Error retrieving match data: {match_data['error']}" if not match_data or "players" not in match_data: return f"No data found for match ID {match_id}." # Get hero names heroes_data = await make_opendota_request("heroes") hero_id_to_name = {} if not isinstance(heroes_data, dict) and isinstance(heroes_data, list): for hero in heroes_data: 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 # Process players radiant_players = [] dire_players = [] for player in match_data["players"]: hero_id = player.get("hero_id", 0) hero_name = hero_id_to_name.get(hero_id, f"Hero {hero_id}") account_id = player.get("account_id", "Anonymous") name = player.get("personaname", "Unknown") kills = player.get("kills", 0) deaths = player.get("deaths", 0) assists = player.get("assists", 0) player_info = ( f"{name} (ID: {account_id}) - {hero_name}: {kills}/{deaths}/{assists}" ) if player.get("player_slot", 0) < 128: radiant_players.append(player_info) else: dire_players.append(player_info) # Match result radiant_win = match_data.get("radiant_win", False) result = "Radiant Victory" if radiant_win else "Dire Victory" return ( f"Heroes in Match {match_id} ({result}):\n\n" f"Radiant:\n" + "\n".join(f"- {p}" for p in radiant_players) + "\n\n" "Dire:\n" + "\n".join(f"- {p}" for p in dire_players) )
  • The @mcp.tool() decorator registers the get_match_heroes function as an MCP tool.
    @mcp.tool()
  • Core helper function used by get_match_heroes to make API requests to OpenDota with caching and rate limiting.
    async def make_opendota_request( endpoint: str, params: Optional[Dict[str, Any]] = None ) -> Dict[str, Any]: """Make a request to the OpenDota API with proper error handling and caching.""" # Apply rate limiting await apply_rate_limit() url = f"{OPENDOTA_API_BASE}/{endpoint}" request_params = API_PARAMS.copy() if params: request_params.update(params) # Create a cache key manually cache_key = endpoint if request_params: param_str = "&".join(f"{k}={v}" for k, v in sorted(request_params.items())) cache_key = f"{endpoint}?{param_str}" # Check cache cache_entry = api_cache.get(cache_key) if cache_entry: timestamp, data = cache_entry if time.time() - timestamp < CACHE_TTL: logger.debug(f"Cache hit for {cache_key}") return data logger.info(f"Making request to {endpoint} with params {request_params}") async with httpx.AsyncClient() as client: try: response = await client.get( url, params=request_params, headers={"User-Agent": USER_AGENT}, timeout=10.0, ) response.raise_for_status() data = response.json() # Cache the response api_cache[cache_key] = (time.time(), data) return data except httpx.HTTPStatusError as e: if e.response.status_code == 429: logger.error(f"Rate limit exceeded for {endpoint}") return { "error": "Rate limit exceeded. Consider using an API key for more requests." } if e.response.status_code == 404: logger.error(f"Resource not found: {endpoint}") return {"error": "Not found. The requested resource doesn't exist."} if e.response.status_code >= 500: logger.error(f"OpenDota API server error: {e.response.status_code}") return {"error": "OpenDota API server error. Please try again later."} logger.error( f"HTTP error {e.response.status_code} for {endpoint}: {e.response.text}" ) return {"error": f"HTTP error {e.response.status_code}: {e.response.text}"} except Exception as e: logger.error(f"Unexpected error for {endpoint}: {str(e)}") return {"error": f"Unexpected error: {str(e)}"}

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/asusevski/opendota-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server