MCP Dota 2 Match Analysis Server
Provides tools for analyzing Dota 2 matches using replay files and the OpenDota API, including death analysis, combat logs, objectives, timelines, and draft analysis.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@MCP Dota 2 Match Analysis Server analyze match 1234567890"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
MCP Dota 2 Match Analysis Server
FastMCP server for Dota 2 match analysis using replay files and OpenDota API.
Built-in coaching instructions guide LLMs to provide meaningful analysis - pattern recognition, objective rotations, networth swings linked to teamfights, and actionable coaching advice.
Quick Start
Local
git clone https://github.com/DeepBlueCoding/mcp-replay-dota2.git
cd mcp-replay-dota2
uv sync
uv run python dota_match_mcp_server.pyDocker
docker build -t dota2-mcp-server .
docker run -p 8081:8081 dota2-mcp-server --transport sse
# Connect to http://localhost:8081/sseRelated MCP server: Scalene-MCP
What It Does
Resources: Static reference data (heroes, map, pro players/teams)
Tools: Match analysis (deaths, combat log, objectives, timelines, drafts)
Instructions: Built-in coaching guidance for meaningful LLM responses
See full documentation for API reference and integration guides.
Development
uv run pytest # Run tests
uv run pytest -m "not integration" # Skip slow testsLicense
MIT
Available Tools
41 toolsdelete_replayA
Delete cached replay file and parsed data for a match.
Use this tool when:
A replay appears to be corrupted and needs to be re-downloaded
You want to force a fresh download of a replay
Cached parsed data seems incorrect or outdated
After deletion, the next analysis request for this match will trigger a fresh download and parse.
Args: match_id: The Dota 2 match ID to delete cached data for
Returns: DeleteReplayResponse with deletion status
Inputs: match_id (required). Returns: Response for delete_replay tool.
download_replayA
Download and cache the replay file for a Dota 2 match.
Use this tool FIRST before asking analysis questions about a match. Replay files are large (50-400MB) and can take 1-5 minutes to download.
Once downloaded, the replay is cached locally and subsequent queries for the same match will be instant.
Progress is reported during download:
0-10%: Checking cache and getting replay URL
10-40%: Downloading compressed file
40-50%: Extracting replay
50-95%: Parsing replay
95-100%: Caching results
Args: match_id: The Dota 2 match ID (from OpenDota, Dotabuff, or in-game)
Returns: DownloadReplayResponse with success status and file info
Inputs: match_id (required). Returns: Response for download_replay tool.
get_camp_stacksC
Get all neutral camp stacks in a Dota 2 match.
Inputs: match_id (required), hero_filter. Returns: Response for get_camp_stacks tool.
get_client_capabilitiesA
Diagnostic tool to check what MCP capabilities the connected client supports.
Returns information about sampling, roots, and other client capabilities.
Inputs: no named parameters. Returns: object
get_courier_killsA
Get all courier kills in a Dota 2 match.
Returns a list of courier kill events with:
game_time: Seconds since game start
game_time_str: Formatted as M:SS
killer: Hero that killed the courier
killer_is_hero: Whether the killer was a hero
team: Team whose courier was killed (radiant/dire)
Args: match_id: The Dota 2 match ID
Returns: CourierKillsResponse with list of courier kill events
Inputs: match_id (required). Returns: Response for get_courier_kills tool.
get_cs_at_minuteB
Get last hits, denies, gold, and level for all heroes at a specific minute.
Inputs: minute (required), match_id (required). Returns: Response for get_cs_at_minute tool.
get_farming_patternC
Analyze a hero's farming pattern with camp sequences, power spikes, and routes.
Inputs: hero (required), match_id (required), end_minute, start_minute. Returns: Response for get_farming_pattern tool.
get_fightC
Get detailed information about a specific fight.
Inputs: fight_id (required), match_id (required). Returns: Response for get_fight tool.
get_fight_combat_logA
Get detailed event-by-event combat log for a specific fight.
Automatically detects the fight around reference_time and returns the sequence of deaths, abilities, and key moments.
Args: match_id: The Dota 2 match ID reference_time: Game time in seconds (e.g., 1530 for 25:30) hero: Optional hero to anchor fight detection detail_level: "narrative" (default), "tactical", or "full" max_events: Maximum events to return
Inputs: match_id (required), reference_time (required), hero, max_events, +1 more. Returns: Response for get_fight_combat_log tool.
get_fight_replayC
Get high-resolution replay data for a fight.
Inputs: end_time (required), match_id (required), start_time (required), interval_seconds. Returns: Response for get_fight_replay tool.
get_hero_deathsA
Get chronological list of ALL hero deaths in a match.
Returns all deaths with killer, victim, time, location, and ability used. Use for global death timeline, first blood, or death pattern analysis.
Args: match_id: The Dota 2 match ID killer: Filter by killer hero (partial match, e.g. 'jugg') victim: Filter by victim hero (partial match) location: Filter by map location (partial match, e.g. 't1', 'roshan') ability: Filter by killing ability (partial match) start_time: Filter deaths after this game time (seconds) end_time: Filter deaths before this game time (seconds)
Inputs: match_id (required), killer, victim, ability, +3 more. Returns: Response for get_hero_deaths tool.
get_hero_performanceA
Get comprehensive performance data for a hero.
Returns kills, deaths, assists, ability stats (casts, hit rate), and per-fight breakdowns. Use ability_filter for specific ability analysis.
Time filtering: Use start_time/end_time to analyze specific game phases. Common time ranges:
Early game: start_time=0, end_time=900 (0-15 min)
Mid game: start_time=900, end_time=1800 (15-30 min)
Late game: start_time=1800 (30+ min)
Args: match_id: The Dota 2 match ID hero: Hero name (e.g., "jakiro", "mars", "batrider") ability_filter: Filter to specific ability (e.g., "ice_path", "flaming_lasso") start_time: Filter fights starting after this game time (seconds) end_time: Filter fights starting before this game time (seconds)
Inputs: hero (required), match_id (required), end_time, start_time, +1 more. Returns: Response for get_hero_combat_analysis tool.
get_hero_positionsB
Get hero positions at a specific minute in a Dota 2 match.
Inputs: minute (required), match_id (required). Returns: Response for get_hero_positions tool.
get_item_purchasesA
Get item purchase timings for heroes in a Dota 2 match.
Returns a chronological list of item purchases with:
game_time: Seconds since game start (can be negative for pre-horn purchases)
game_time_str: Formatted as M:SS
hero: Hero that purchased the item
item: Item name (e.g., "item_bfury", "item_power_treads")
Use this to answer questions like:
"When did Juggernaut finish Battlefury?"
"What was Anti-Mage's item progression?"
"Who bought the first BKB?"
Args: match_id: The Dota 2 match ID hero_filter: Only include purchases by this hero, e.g. "juggernaut" (optional)
Returns: ItemPurchasesResponse with list of item purchase events
Inputs: match_id (required), hero_filter. Returns: Response for get_item_purchases tool.
get_jungle_summaryB
Get jungle activity summary for a Dota 2 match.
Inputs: match_id (required). Returns: Response for get_jungle_summary tool.
get_lane_summaryC
Get laning phase summary for a Dota 2 match.
Inputs: match_id (required). Returns: Response for get_lane_summary tool.
get_league_matchesB
Get matches from a specific league/tournament with series grouping.
Inputs: league_id (required), limit. Returns: Response for get_league_matches tool.
get_leaguesC
Get all Dota 2 leagues/tournaments.
Inputs: tier. Returns: Response for get_leagues tool.
get_match_draftB
Get the complete draft (picks and bans) for a Dota 2 match with drafting context.
Inputs: match_id (required). Returns: Response for get_match_draft tool.
get_match_heroesC
Get the 10 heroes in a Dota 2 match with detailed stats.
Inputs: match_id (required). Returns: Response for get_match_heroes tool.
get_match_infoC
Get match metadata and player information for a Dota 2 match.
Inputs: match_id (required). Returns: Response for get_match_info tool.
get_match_playersB
Get the 10 players in a Dota 2 match with their hero assignments.
Inputs: match_id (required). Returns: Response for get_match_players tool.
get_match_timelineC
Get time-series data for a Dota 2 match.
Inputs: match_id (required). Returns: Response for get_match_timeline tool.
get_objective_killsA
Get all major objective kills in a Dota 2 match.
Returns kills of:
Roshan: game_time, killer, team, kill_number (1st, 2nd, 3rd Roshan)
Tormentor: game_time, killer, team, side (which Tormentor was killed)
Towers: game_time, tower name, team, tier, lane, killer
Barracks: game_time, barracks name, team, lane, type (melee/ranged), killer
Use this to analyze:
When did each team take Roshan?
Tower trade patterns and timing
High ground pushes and barracks destruction
Tormentor control
Args: match_id: The Dota 2 match ID
Returns: ObjectiveKillsResponse with all objective kill events
Inputs: match_id (required). Returns: Response for get_objective_kills tool.
get_position_timelineA
Get hero positions over a time range at regular intervals.
Inputs: end_time (required), match_id (required), start_time (required), hero_filter, +1 more. Returns: Response for get_position_timeline tool.
get_pro_matchesA
Get recent professional Dota 2 matches as a flat list.
Returns individual matches without series grouping. Use get_tournament_series for bracket/series analysis.
Args: limit: Maximum matches to return (default 50) tier: Filter by league tier (premium, professional, amateur) team1_name: Filter by first team (fuzzy match). Alone: all matches for team. team2_name: Filter by second team (fuzzy match). With team1: head-to-head matches. league_name: Filter by league/tournament name (contains, case-insensitive) days_back: Only return matches from last N days
Inputs: tier, limit, days_back, team1_name, +2 more. Returns: Response for get_pro_matches tool - flat list of matches.
get_pro_playerC
Get detailed information about a professional player by account ID.
Inputs: account_id (required). Returns: Response for get_pro_player tool.
get_pro_player_by_nameC
Get detailed information about a professional player by name.
Inputs: name (required). Returns: Response for get_pro_player tool.
get_raw_combat_eventsA
Get raw combat events for a specific time window.
Use for analyzing non-fight moments (e.g., Roshan attempts, specific plays). detail_level: "narrative" (deaths/abilities), "tactical" (+damage), "full" (all).
Args: match_id: The Dota 2 match ID start_time: Start of time window in seconds end_time: End of time window in seconds hero_filter: Filter to specific hero ability_filter: Filter to specific ability detail_level: "narrative", "tactical", or "full" max_events: Maximum events to return
Inputs: match_id (required), end_time, max_events, start_time, +3 more. Returns: Response for get_combat_log tool.
get_rotation_analysisB
Analyze hero rotations - movement patterns between lanes and outcomes.
Returns rotation events, gank attempts, and their success rates.
Inputs: match_id (required), end_minute, start_minute. Returns: Response for get_rotation_analysis tool.
get_rune_pickupsA
Get power rune pickups in a Dota 2 match.
Returns a list of power rune pickup events with:
game_time: Seconds since game start
game_time_str: Formatted as M:SS
hero: Hero that picked up the rune
rune_type: Type of rune (haste, double_damage, arcane, invisibility, regeneration, shield)
Note: Only power runes are trackable. Bounty, wisdom, and water runes don't leave detectable events in the replay data.
Use this to answer questions like:
"Who got the most power runes?"
"What runes did the mid player secure?"
"When did they get a DD rune before fighting?"
Args: match_id: The Dota 2 match ID
Returns: RunePickupsResponse with list of power rune pickup events
Inputs: match_id (required). Returns: Response for get_rune_pickups tool.
get_snapshot_at_timeC
Get game state snapshot at a specific game time.
Inputs: match_id (required), game_time (required). Returns: Response for get_snapshot_at_time tool.
get_stats_at_minuteB
Get player stats at a specific minute in a Dota 2 match.
Inputs: minute (required), match_id (required). Returns: Response for get_stats_at_minute tool.
get_teamA
Get detailed information about a team by ID.
Inputs: team_id (required). Returns: Response for get_team tool.
get_team_by_nameC
Get detailed information about a team by name.
Inputs: name (required). Returns: Response for get_team tool.
get_teamfightsA
Get major teamfights (3+ deaths) with coaching analysis.
Returns teamfight timing, participants, death sequences, and analysis.
Args: match_id: The Dota 2 match ID min_deaths: Minimum deaths to classify as teamfight (default 3) location: Filter by map location (partial match, e.g. 't1', 'roshan_pit') start_time: Filter teamfights starting after this game time (seconds) end_time: Filter teamfights starting before this game time (seconds)
Inputs: match_id (required), end_time, location, min_deaths, +1 more. Returns: Response for get_teamfights tool.
get_team_matchesC
Get recent matches for a team.
Inputs: team_id (required), limit. Returns: Response for get_team_matches tool.
get_tournament_seriesA
Get tournament series with bracket/game details.
Use this for tournament progression analysis: series results, Bo3/Bo5 outcomes, team advancement through brackets.
Args: league_name: Filter by league/tournament name (fuzzy match) league_id: Filter by specific league ID team_name: Filter series involving this team limit: Maximum series to return (default 20) days_back: Only series from last N days
Inputs: limit, days_back, league_id, team_name, +1 more. Returns: Response for get_tournament_series tool - series with nested games.
list_fightsA
List all fights/skirmishes in a match with death summaries.
Returns fight count, timing, participants, and deaths for each fight.
Args: match_id: The Dota 2 match ID location: Filter by map location (partial match, e.g. 't1', 'roshan_pit') min_deaths: Filter to fights with at least this many deaths is_teamfight: Filter to teamfights only (True) or skirmishes only (False) start_time: Filter fights starting after this game time (seconds) end_time: Filter fights starting before this game time (seconds)
Inputs: match_id (required), end_time, location, min_deaths, +2 more. Returns: Response for list_fights tool.
search_pro_playerB
Search for professional Dota 2 players by name or alias.
Inputs: query (required), max_results. Returns: Response for player search tool.
search_teamA
Search for professional Dota 2 teams by name, tag, or alias.
Inputs: query (required), max_results. Returns: Response for team search tool.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 41 tools
Several tools have overlapping boundaries: get_fight, get_fight_combat_log, get_fight_replay, list_fights, and get_teamfights all cover fight analysis, and get_fight/get_fight_replay lack clear arguments to distinguish them. Similarly, search_pro_player vs get_pro_player_by_name and search_team vs get_team_by_name create predictable confusion.
The majority of tools follow a clear snake_case verb_noun pattern (get_*, list_*, search_*, delete_*, download_*), making the set generally predictable. Minor inconsistencies like get_teamfights vs get_team_fights, search_pro_player vs get_team_by_name, and get_pro_matches vs get_league_matches keep it from a perfect score.
41 tools is a heavy surface for an agent to reason over, especially since the server bundles replay-level match analysis with professional scene lookup. While each tool targets real Dota functionality, the count creates significant selection overhead and would benefit from being split into separate server concerns.
The server covers the major match-analysis workflows: replay download, fights, deaths, item/runes, objectives, farming, lane summaries, timelines, drafts, and professional scene data. Minor gaps exist (e.g., no ward/vision analysis, no player match-history lookup, no team roster tool), but agents can generally work around them.
Maintenance
Related MCP Connectors
MCP server providing access to the Scorecard API to evaluate and optimize LLM systems.
MCP server for building and testing AI agents with multi-model experimentation and insights.
MCP server for VC pitch-deck scoring, thesis-fit matching, and deal-flow management.
Related MCP Servers
- AlicenseBqualityDmaintenanceModel Context Protocol server that enables LLMs and AI assistants to retrieve real-time Dota 2 statistics, match data, player information, and game metrics through a standardized interface.179MIT
- FlicenseAqualityDmaintenanceA FastMCP server that provides LLMs with structured access to Scalene's CPU, GPU, and memory profiling for Python applications. It enables automated performance analysis, bottleneck identification, and optimization suggestions through natural language interactions in supported IDEs.71-
- AlicenseAqualityDmaintenanceMCP server for log file analysis. Gives LLMs the ability to efficiently analyze large log files without loading them into context.7101MIT
- AlicenseBqualityBmaintenanceMCP server exposing 30 tools for League of Legends player analysis, match review, and training-plan generation.3513 npm1MIT