┌─────────────────────────────────────────────────────────────────────┐
│ Claude Desktop │
│ (MCP Client / Consumer) │
└────────────────────────┬────────────────────────────────────────────┘
│
MCP Protocol
│
┌────────────────────────▼────────────────────────────────────────────┐
│ riot-games-api MCP Server │
│ (src/server.py) │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ CONSTANTS & TYPE DEFINITIONS │ │
│ │ ┌─────────────────┬──────────────────┬─────────────┐ │ │
│ │ │ Platform Routes │ Regional Routes │ Mappings │ │ │
│ │ │ (11 regions) │ (4 regions) │ (auto map) │ │ │
│ │ └─────────────────┴──────────────────┴─────────────┘ │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ HELPER FUNCTIONS │ │
│ │ ┌─────────────┬──────────────┬────────────────────────┐ │ │
│ │ │ API Request │ Account/Auth │ Data Retrieval │ │ │
│ │ │ │ │ │ │ │
│ │ │ •riot_req │ •get_puuid │ •get_champion_map │ │ │
│ │ │ •regional │ •get_account │ •get_summoner │ │ │
│ │ │ _request │ │ •get_rank │ │ │
│ │ │ │ │ •get_top_champions │ │ │
│ │ │ │ │ •get_tft_summoner │ │ │
│ │ └─────────────┴──────────────┴────────────────────────┘ │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ MCP TOOLS (PUBLIC API) │ │
│ │ │ │
│ │ League of Legends (8 tools) TFT (2 tools) │ │
│ │ ──────────────────────── ───────────────── │ │
│ │ • lol_get_player_summary • tft_get_player_summary │ │
│ │ • lol_get_top_champions • tft_get_recent_matches │ │
│ │ • lol_get_recent_matches │ │
│ │ • lol_get_champion_mastery Legacy Tools (5) │ │
│ │ • lol_get_match_details ────────────── │ │
│ │ • lol_get_challenges • get_player_summary │ │
│ │ • lol_get_league_entries • get_top_champions_tool│ │
│ │ • lol_get_spectator • get_recent_matches_tool│ │
│ │ • get_champion_mastery_tool│ │
│ │ • get_match_summary │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────┬────────────────────────────────────────────┘
│
HTTPX Async Client
│
┌─────────────────┼─────────────────┐
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Riot Games │ │ Riot Games │ │ DataDragon │
│ Platform API │ │ Regional API │ │ (Champion) │
│ │ │ │ │ │
│ - Summoner │ │ - Matches │ │ - Versions │
│ - League │ │ - Accounts │ │ - Champions │
│ - Champion │ │ - Challenges │ │ - Localiz. │
│ Mastery │ │ - Spectator │ │ │
│ │ │ - TFT │ │ │
└──────────────┘ └──────────────┘ └──────────────┘
/home/shaun/repos/mcp-riot/
│
├── src/
│ ├── __init__.py (Empty module marker)
│ └── server.py (MAIN FILE - 1000+ lines)
│ ├── Imports & Setup
│ ├── Constants (Platform/Regional routing)
│ ├── Helper: API Requests
│ ├── Helper: Account/Auth
│ ├── Helper: Data Retrieval
│ ├── Tools: League of Legends (8 tools)
│ ├── Tools: Team Fight Tactics (2 tools)
│ └── Tools: Backwards Compatibility (5 tools)
│
├── .env (API Key - keep secret!)
├── .env.example (Template for .env)
├── .gitignore (Exclude sensitive files)
├── pyproject.toml (Project configuration)
├── uv.lock (Dependency lock file)
│
├── README.md (Overview & setup)
├── TOOLS_REFERENCE.md (Complete tool reference)
├── ENHANCEMENTS.md (What's new in v2.0)
├── EXAMPLES.md (Code examples & patterns)
├── ARCHITECTURE.md (This file)
│
└── .git/ (Version control)
User Request:
lol_get_player_summary("Air Coots", "Prime")
▼
1. get_puuid("Air Coots", "Prime")
└─ riot_regional_request()
└─ https://americas.api.riotgames.com/riot/account/v1/...
└─ Return: PUUID
▼
2. get_summoner_by_puuid(puuid, "na")
└─ riot_request()
└─ https://na1.api.riotgames.com/lol/summoner/v4/...
└─ Return: {level, profileIcon, ...}
▼
3. get_rank_by_puuid(puuid, "na")
└─ riot_request()
└─ https://na1.api.riotgames.com/lol/league/v4/...
└─ Return: [{queueType, tier, rank, lp, ...}]
▼
4. get_top_champions(puuid, champ_map, count=5)
└─ riot_request()
└─ https://na1.api.riotgames.com/lol/champion-mastery/v4/...
└─ Return: [{championId, level, points}]
▼
5. get_recent_matches(puuid, count=5)
└─ riot_regional_request()
└─ https://americas.api.riotgames.com/lol/match/v5/matches/by-puuid/
└─ Return: [match_id_1, match_id_2, ...]
▼
6. For each match_id, fetch match details
└─ riot_regional_request(/lol/match/v5/matches/{match_id})
└─ Return: {info: {participants: [...]}}
▼
7. Extract player participant data
▼
Return Combined: {gameName, level, soloRank, topChampions, recentMatches}
User specifies: platform="na"
▼
PLATFORM_ROUTING["na"] = "na1"
▼
Use in API call: https://na1.api.riotgames.com/...
▼
Also maps to regional: PLATFORM_TO_REGION["na"] = "americas"
▼
For regional endpoints: https://americas.api.riotgames.com/...
Lines 1-50:
- Imports (mcp, httpx, os, typing, dotenv, datetime)
- MCP server initialization
- API key loading from .env
- Platform/Regional routing dictionaries
- Champion cache initializationLines 51-120:
- riot_request()
* Platform-routed requests
* Error handling (404, HTTP status codes)
* Timeout management
* Header setup
- riot_regional_request()
* Regional-routed requests
* Same error handling approach
* Used for matches, accounts, challengesLines 121-145:
- get_puuid()
* Takes game_name, tag_line
* Returns PUUID via Riot Account API
- get_riot_account()
* Full account information
* Used for future extensibilityLines 146-165:
- get_champion_map()
* Fetches from DataDragon
* Caches results (key: language)
* Maps champion_id → name
* Called for champion name resolutionLines 166-230:
- get_summoner_by_puuid()
- get_rank_by_puuid()
- get_top_champions()
These are private helpers called by public toolsLines 231-240:
- get_tft_summoner()
* TFT-specific summoner dataLines 241-600:
@mcp.tool() decorated functions:
1. lol_get_player_summary()
2. lol_get_top_champions()
3. lol_get_recent_matches()
4. lol_get_champion_mastery()
5. lol_get_match_details()
6. lol_get_challenges()
7. lol_get_league_entries()
8. lol_get_spectator()Lines 601-700:
@mcp.tool() decorated functions:
1. tft_get_player_summary()
2. tft_get_recent_matches()Lines 701-820:
Original tools that maintain interface compatibility:
1. get_player_summary()
2. get_top_champions_tool()
3. get_recent_matches_tool()
4. get_champion_mastery_tool()
5. get_match_summary()Lines 821-823:
if __name__ == "__main__":
mcp.run()Why: Riot's API uses two different routing strategies
- Platform routing (na1, euw1, kr) for player-specific data
- Regional routing (americas, europe) for match/account data
Implementation: Two separate request functions with clear naming
Why: Reduces code duplication and makes adding new tools easier
Pattern: Private helpers (get_*) → Public tools (lol_get_*)
Why: Don't break existing code that uses the tool
Solution: Original 5 tools wrap new tools internally
Why: Predictable error responses make error handling easier
Pattern: Return {"error": "description"} on failures
Why: Calculate useful metrics from raw API data
Examples:
- CS per minute (from duration and CS)
- Win rate (from wins/losses)
- KDA ratio (from K/D/A)
- Damage efficiency (from damage dealt/taken)
Why: Hide complexity of platform↔region mapping from users
Benefit: Single platform="na" parameter handles both needs
platform: Literal["na", "euw", "kr", "br", "las", "lan", "ru", "tr", "jp", "oc", "pbe"]
language: str # e.g., "en_US", "ko_KR"
tier: Literal["IRON", "BRONZE", ..., "CHALLENGER"]
rank: Literal["I", "II", "III", "IV"]
count: int # Usually 1-100
page: int # For paginationdict[str, Any] # Structured response
list[Any] # Multiple items
dict[str, Any] | None # Can be None on error
str # Formatted string (legacy tools){
"gameName": str,
"tagLine": str,
"puuid": str, # Usually included
# Main data field(s)
"rank": {...},
"champions": [...],
"matches": [...],
# OR error case
"error": str
}async def get_new_data(puuid: str, param: str) -> dict | None:
"""Fetch new data type from API"""
routing = PLATFORM_ROUTING.get("na", "na1")
return await riot_request(
f"/lol/new-endpoint/v1/endpoint/{puuid}",
platform_routing=routing,
params={"param": param}
)@mcp.tool()
async def lol_get_new_feature(
game_name: str,
tag_line: str,
param: str = "default",
platform: str = "na"
) -> dict[str, Any]:
"""
📊 Get new feature data from League of Legends.
Returns: [description of return value]
"""
puuid = await get_puuid(game_name, tag_line)
if not puuid:
return {"error": "Failed to find player"}
data = await get_new_data(puuid, param)
if not data:
return {"error": "Could not retrieve new data"}
return {
"gameName": game_name,
"tagLine": tag_line,
"puuid": puuid,
"newData": data
}# Tool automatically available via MCP after restart### `lol_get_new_feature`
Description...
Parameters...
Returns...
Use Cases...import logging
logging.basicConfig(level=logging.DEBUG)Add print statements in helper functions:
async def riot_request(...):
full_url = f"https://{platform_routing}.api.riotgames.com{url}"
print(f"DEBUG: Requesting {full_url}") # Add this
...echo $RIOT_API_KEY # Check if set# In interactive Python
import asyncio
from src.server import lol_get_player_summary
result = asyncio.run(lol_get_player_summary("Name", "Tag"))
print(result)| Operation | API Calls | Time Est. |
|---|---|---|
| Player Summary | 5-7 | 500-1000ms |
| Recent Matches (10) | 11 | 1-2 seconds |
| Match Details (1) | 1 | 200-400ms |
| Top 100 Games Analysis | 102 | 10-20 seconds |
- Champion map cache: ~2MB (per language)
- Typical response: 5-50KB
- No significant memory accumulation
- Champion map: Cached per language (100% hit rate after first call)
- No aggressive caching (always get fresh data)
-
Legends of Runeterra
- Mirrors LoL structure
- Change endpoints to
/lor/ - Add
lor_get_*tools
-
Valorant
- Similar pattern
- Use
/val/endpoints - Add
val_get_*tools
-
Match Timeline
- Already have match_id
- Fetch from
/lol/match/v5/matches/{id}/timeline - Parse frame-by-frame data
-
Live Spectator Streaming
- Implement polling
- Call
lol_get_spectator()repeatedly - Push updates via WebSocket
- Helper functions easily wrap new endpoints
- Consistent routing logic for new games
- Error handling patterns established
- Tool registration is automatic via
@mcp.tool()decorator
| Document | Purpose | Audience |
|---|---|---|
| README.md | Overview & setup | Everyone |
| TOOLS_REFERENCE.md | Complete API reference | Developers |
| EXAMPLES.md | Code examples | Developers |
| ENHANCEMENTS.md | What's new | Users upgrading |
| ARCHITECTURE.md | System design | Contributors |
- Follow existing code style
- Add docstrings to all functions
- Use type hints throughout
- Update TOOLS_REFERENCE.md for new tools
- Add examples to EXAMPLES.md
- Test with multiple regions
- Handle errors gracefully
Last Updated: 2025-01-02
Version: 2.0.0
Status: Production Ready