Changelog¶
🤖 AI Summary
Project changelog following Keep a Changelog format. v1.2.0 release includes: MCP prompts for coaching analysis, DockerHub + PyPI distribution, versioned documentation, unified filter system with 37 map regions, position-specific coaching frameworks, enhanced OpenDota SDK integration, and major performance improvements.
All notable changes to this project will be documented in this file.
[1.2.0] - 2025-12-31¶
Major release with MCP prompts, Docker distribution, and comprehensive filtering system.
Installation¶
# PyPI (recommended)
pip install mcp-replay-dota2
# Docker
docker pull dbcjuanma/mcp_replay_dota2
docker run -p 8081:8081 dbcjuanma/mcp_replay_dota2 --transport sse
Added¶
Distribution¶
- PyPI package - Install via
pip install mcp-replay-dota2oruv add mcp-replay-dota2 - DockerHub images - Multi-platform builds (
linux/amd64+linux/arm64) atdbcjuanma/mcp_replay_dota2 - Versioned documentation - Version selector with mike, social links to GitHub/PyPI/DockerHub
MCP Prompts (7 coaching prompts)¶
analyze_draft- Draft analysis with lane matchups, synergies, countersreview_hero_performance- Hero performance review with position-specific frameworkanalyze_deaths- Death pattern analysis with 5-question frameworkanalyze_teamfight- Teamfight breakdown with before/during/after analysisanalyze_laning- Laning phase analysisanalyze_farming- Farming efficiency analysisfull_match_review- Complete match review
Filtering System¶
- Unified filter models (
src/models/filters.py) -EventFilters,CombatFilters,FightFilters,DeathFilters - 37 map regions - Tower fights, landmarks (roshan_pit, tormentors), farming areas (triangles, ancients)
- Multi-filter support - killer, victim, location, ability, start_time, end_time across tools
- Time filtering for
get_hero_performance- Filter stats to specific game phases
Coaching Framework¶
- Position-specific personas - Carry analysis framework in
data/personas/pos1_carry.md - Coaching persona - Senior analyst with TI/11k background in
data/personas/coaching_persona.md - Recovery frameworks - Lane recovery, late game analysis
Tools¶
delete_replay- Manual cache management for corrupt replaysget_tournament_series- Tournament bracket/series analysis- League fuzzy search - "TI 2025" matches "The International 2025"
Data¶
- Draft lane assignment -
lanefield for correct lane matchups - HeroStats expected_lane - Detect trilanes and unusual setups
- OpenDota SDK 7.40 fields - rank_tier, teamfight_participation, lane_efficiency, draft_timings
Fixed¶
- 550x performance improvement -
get_combat_logfrom 493s → 0.89s (in-memory caching) - Position assignment - Uses lane_role not GPM for pos 4/5
- Dire triangle region - Correct map coordinates
get_match_timelineteam_graphs - Fixed null response- Expired replay messages - Clear "Valve returned 502" errors
Changed¶
- python-opendota-sdk upgraded to 7.40.3 with
wait_for_replaysupport - python-manta upgraded to 1.4.7.3 with attack collector
- Test suite - 788 tests with real match data validation
- Removed Sampling column from MCP client table (not widely supported)
[1.0.9] - 2025-12-12¶
Fixed¶
- get_match_info and get_match_draft returning generic "Could not parse" errors
- Exception handling now propagates actual error messages instead of swallowing with generic messages
- get_pro_matches league_name filter now uses bidirectional matching (e.g., "Blast Slam V" finds "SLAM V")
[1.2.0] - 2025-12-11¶
Added¶
- Position (1-5) assignment for all match tools:
get_match_heroes,get_match_players,get_match_draftnow includepositionfield- Position determined from OpenDota lane data (
lane_role) and GPM:- Pos 1 = Safelane core (lane_role=1, highest GPM)
- Pos 2 = Mid (lane_role=2)
- Pos 3 = Offlane core (lane_role=3, highest GPM)
- Pos 4 = Soft support (higher GPM support)
- Pos 5 = Hard support (lowest GPM support)
-
Fixes LLM incorrectly guessing positions (e.g., Axe as pos5 instead of pos3)
-
Draft context data in
get_match_draftpicks: counters: Heroes that counter this pick (bad matchups)good_against: Heroes this pick counters (favorable matchups)when_to_pick: Conditions when this hero is strong- Helps LLM understand draft decisions and counter-picking
Changed¶
assign_roles()renamed toassign_positions()in match_fetcher.pyDraftActionmodel now includesposition,counters,good_against,when_to_pickfieldsHeroStatsandMatchPlayerInfomodels now includepositionfield
[1.1.4] - 2025-12-11¶
Changed¶
get_pro_matchestool - Enhanced team filtering with head-to-head support:- Renamed
team_nameparameter toteam1_name - Added
team2_nameparameter for head-to-head filtering - Single team filter (
team1_nameonly): Returns all matches involving that team - Head-to-head filter (
team1_name+team2_name): Returns only matches where both teams played against each other, regardless of radiant/dire side - Combine with
league_name,tier, anddays_backfor deep filtering (e.g., Spirit vs OG at The International)
[1.1.3] - 2025-12-10¶
Added¶
ability_filterparameter for focused ability analysis:get_raw_combat_events: Filter combat log by specific ability (e.g., "ice_path", "chronosphere")get_hero_performance: Filter ability summary and per-fight abilities by name- Case-insensitive partial matching (e.g., "fissure" matches "earthshaker_fissure")
Changed¶
- Tool renames for clarity (LLM routing improvement):
get_combat_log→get_raw_combat_events(emphasizes raw event debugging)-
get_hero_combat_analysis→get_hero_performance(clearer purpose) -
Added routing hints to competing tools:
get_hero_deaths,list_fights,get_teamfights,get_rotation_analysisnow include "NOT FOR HERO PERFORMANCE QUESTIONS → Use get_hero_performance instead" in docstrings
Fixed¶
- Ability counting now covers entire match - Previously only counted abilities used during detected fights; now counts ALL ability usage across the entire match with per-fight breakdown preserved
[1.1.2] - 2025-12-09¶
Added¶
detail_levelparameter for combat log tools - Controls token usage (~98% reduction withnarrative):narrative(default): Deaths, abilities, items, purchases, buybacks (~500-2,000 tokens)tactical: Adds hero-to-hero damage and debuffs (~2,000-5,000 tokens)full: All events including creeps (~50,000+ tokens, debugging only)- Applied to
get_combat_logandget_fight_combat_logtools max_eventsparameter added (default 500, max 2000) to prevent overflowtruncatedfield in response indicates if results were capped
Changed¶
- Removed
significant_onlyparameter - Replaced bydetail_levelenum for finer control - Default behavior now uses
narrativedetail level (was equivalent tosignificant_only=True)
[1.1.1] - 2025-12-08¶
Added¶
get_hero_combat_analysistool - Per-hero combat performance analysis across all fights:- Tracks kills, deaths, assists per fight
- Ability usage with hit rates (total casts vs hero hits)
- Damage dealt and received per fight
- Teamfight vs skirmish classification
- Ground-targeted ability tracking: Ice Path, Fissure, etc. track hits via MODIFIER_ADD events (stun debuffs applied)
- Hit rate can exceed 100% for AoE abilities hitting multiple heroes per cast
- Aggregate stats across all fights for the hero
[1.1.0] - 2025-12-08¶
Changed¶
- Major refactor: Tools split into domain-specific modules (92% code reduction in main entry point)
dota_match_mcp_server.py: 2606 → 206 lines- New
src/tools/directory with modular tool registration:replay_tools.py- Replay download toolcombat_tools.py- Deaths, combat log, objectives, runes, couriersfight_tools.py- Fight detection, teamfights, fight replaymatch_tools.py- Match info, timeline, draft, heroes, positionspro_scene_tools.py- Pro players, teams, leagues, matchesanalysis_tools.py- Jungle, lane, farming patterns, rotations
- Service injection pattern via
register_all_tools(mcp, services)coordinator - No functional changes - all 30+ tools work identically
Technical¶
- Clean separation of concerns: each tool module handles one domain
- Services dictionary pattern for dependency injection
- Easier maintenance and testing of individual tool groups
[1.0.4] - 2025-12-08¶
Added¶
- Hero counter picks database integrated into
/heroesresource: - 848 counter matchups with mechanical explanations (WHY a hero counters another)
- 438 favorable matchups (heroes each hero is good against)
- 529 "when_to_pick" conditions describing optimal draft situations
-
Curated data based on game mechanics: BKB-piercing, silences, roots, mana burn, Blademail, saves, mobility
-
New fields in
dota2://heroes/allresource: counters: List of heroes that counter this hero with reasonsgood_against: List of heroes this hero counters with reasons-
when_to_pick: Draft conditions when the hero is strong -
Pydantic models for counter data in
src/models/hero_counters.py: CounterMatchup,HeroCounters,HeroCountersDatabase-
CounterPickResponse,DraftCounterAnalysis,DraftAnalysisResponse -
HeroesResourcemethods for counter data access: get_hero_counters(hero_id): Get counter data for a specific hero-
get_all_hero_counters(): Get all hero counter data -
get_match_heroestool now includes counter picks for each hero: - Enables draft analysis directly from match data
- Each hero includes counters, good_against, when_to_pick
Changed¶
dota2://heroes/allnow includes counter picks data for draft analysisget_match_heroesenriched with counter picks for draft analysis- Updated documentation with counter picks examples
[1.0.3] - 2025-12-08¶
Added¶
- Combat-intensity based fight detection - Major refactor of fight detection algorithm:
- Fights are now detected based on hero-to-hero combat activity, not just deaths
- Catches teamfights where teams disengage before anyone dies
- Properly captures fight initiation phase (BKB+Blink) before first death
- Uses intensity-based windowing to separate distinct engagements
- Filters out harassment/poke (brief exchanges that aren't real fights)
-
New
detect_fights_from_combat()andget_fight_at_time_from_combat()methods -
Extended fight highlight detection with new patterns:
- BKB + Blink combos: Detects BKB + Blink → Big Ability (either order), marks first as initiator, rest as follow-ups
- Coordinated ultimates: Detects when 2+ heroes from the same team use big teamfight abilities within 3 seconds. Includes
teamfield (radiant/dire) - Refresher combos: Detects when a hero uses Refresher to double-cast an ultimate
- Clutch saves: Detects self-saves (Outworld Staff, Aeon Disk) and ally saves (Glimmer Cape, Lotus Orb, Force Staff, Shadow Demon Disruption)
-
Self-save detection includes tracking what ability the hero was saved FROM (e.g., Omnislash)
-
New data models in
combat_data.py: BKBBlinkCombo: BKB + Blink combo withis_initiatorflagCoordinatedUltimates: Multiple heroes ulting together withteamfield and window trackingRefresherCombo: Refresher double ultimate with cast timesClutchSave: Save detection with saver, save type, and ability saved from-
CombatWindow: Internal dataclass for combat-intensity based fight detection -
Added
nevermore_requiemalias to BIG_TEAMFIGHT_ABILITIES (replays use old internal name)
Changed¶
get_fight_combat_lognow uses combat-based detection by default (captures initiation)- Fight detection parameters tuned: 8s combat gap, 3s intensity window, 5 min events per window
- Removed
fight_initiatorandinitiation_abilityfields (replaced bybkb_blink_comboswithis_initiatorflag)
Fixed¶
- Generic AoE detection now properly filters self-targeting (e.g., Echo Slam damaging caster)
- BKB+Blink detection now accepts either order (BKB→Blink or Blink→BKB)
- Clutch saves now require target to be "in danger" (3+ hero damage hits in 2s) to filter false positives
- Hero deaths include position coordinates and location descriptions from entity snapshots
significant_onlyfilter now excludes non-hero deaths (creep kills) from combat events- Autoattack kills now show
"ability": "attack"instead of"dota_unknown" - Coordinated ultimates now only detects same-team coordination (was incorrectly grouping opposing team abilities)
- Team hero extraction now correctly finds all 10 heroes by scanning entity snapshots after game start
[1.0.2] - 2025-12-08¶
Fixed¶
- Fixed
get_pro_matchesandget_league_matchesreturningnullteam names - OpenDota API doesn't always include team names in match responses
- Now resolves team names from cached teams data when missing
-
Eliminates need for extra
get_teamtool calls to resolve team names -
Fixed
get_match_heroesvalidation error with item fields - Items now return human-readable names (e.g., "Blink Dagger") instead of integer IDs
- Added
get_item_name()andconvert_item_ids_to_names()to constants_fetcher - Neutral items also converted to display names
Added¶
- Model validation tests (
tests/test_model_validation.py) - Tests for HeroStats, MatchHeroesResponse, MatchPlayerInfo validation
- Tests for item ID to name conversion
- Ensures Pydantic models reject invalid data types
[1.0.1] - 2025-12-08¶
Fixed¶
- Updated examples documentation to match v1.0.0 Pydantic response models
- Added fight highlights to
get_fight_combat_logexamples (multi_hero_abilities, kill_streaks, team_wipes) - Fixed
get_farming_patternexample to usecamp_sequenceandlevel_timings - Added missing standard fields to all tool response examples
[1.0.0] - 2025-12-08¶
Added¶
MCP Resources¶
dota2://heroes/all- All Dota 2 heroes with stats and abilitiesdota2://map- Map geometry with towers, barracks, neutral camps, runes, landmarksdota2://pro/players- Pro player database with team affiliationsdota2://pro/teams- Pro team database with rosters
Match Analysis Tools¶
download_replay- Pre-cache replay files before analysis (50-400MB files)get_hero_deaths- All hero deaths with positions and abilitiesget_combat_log- Raw combat events with time/hero filtersget_fight_combat_log- Auto-detect fight boundaries with highlights:- Multi-hero abilities (Chronosphere, Black Hole, Ravage hitting 2+ heroes)
- Kill streaks (Double kill through Rampage, 18-second window)
- Team wipes (Aces)
- Fight initiation detection
get_item_purchases- Item purchase timelineget_objective_kills- Roshan, tormentors, towers, barracksget_match_timeline- Net worth, XP, KDA over time for all playersget_stats_at_minute- Snapshot of all players at specific minuteget_courier_kills- Courier snipes with positionsget_rune_pickups- Rune pickup trackingget_match_draft- Complete draft order for Captains Modeget_match_info- Match metadata (teams, players, winner, duration)get_match_heroes- 10 heroes with KDA, items, statsget_match_players- 10 players with names and hero assignments
Game State Tools¶
list_fights- All fights with teamfight/skirmish classificationget_teamfights- Major teamfights (3+ deaths)get_fight- Detailed fight information with positionsget_camp_stacks- Neutral camp stacking eventsget_jungle_summary- Stacking efficiency by heroget_lane_summary- Laning phase winners and hero stats (OpenDota integration)get_cs_at_minute- CS/gold/level at specific minuteget_hero_positions- Hero positions at specific minuteget_snapshot_at_time- High-resolution game state at specific timeget_position_timeline- Hero movement over time rangeget_fight_replay- High-resolution replay data for fights
Farming & Rotation Analysis¶
get_farming_pattern- Minute-by-minute farming breakdown:- Lane vs jungle creeps, camp type identification
- Position tracking, key transitions (first jungle, left lane)
- Summary stats: jungle %, GPM, CS/min, camps by type
get_rotation_analysis- Hero rotation tracking:- Rotation detection when heroes leave assigned lane
- Rune correlation (power runes → rotations)
- Fight outcomes: kill, died, traded, fight, no_engagement
- Power/wisdom rune event tracking
Pro Scene Features¶
search_pro_player/search_team- Fuzzy search with alias supportget_pro_player/get_pro_player_by_name- Player detailsget_team/get_team_by_name- Team details with rosterget_team_matches- Recent matches for a teamget_leagues/get_league_matches- League informationget_pro_matches- Pro matches with filters (tier, team, league, days_back)- Series grouping for Bo1/Bo3/Bo5 detection
- Player signature heroes and role data
Pydantic Response Models¶
- 40+ typed models with Field descriptions in
src/models/tool_responses.py - Timeline:
KDASnapshot,PlayerTimeline,TeamGraphs - Fights:
FightSummary,FightHighlights,MultiHeroAbility,KillStreak - Game state:
HeroSnapshot,HeroPosition,PositionPoint - Better IDE autocomplete and documentation
Developer Experience¶
- Comprehensive MkDocs documentation with Material theme
- AI Summary sections on all documentation pages
- Parallel-safe tool hints for LLM optimization
- Server instructions with Dota 2 game knowledge
Technical¶
Replay Parsing¶
- Single-pass parsing with python-manta v2 API
ReplayService.get_parsed_data(match_id)as main entry point- Disk caching via diskcache for parsed replay data
- CDOTAMatchMetadataFile extraction for timeline data
Architecture¶
- Services layer:
CombatService,FightService,FarmingService,RotationService - Clean separation: services have no MCP dependencies
- Pydantic models throughout for type safety