Skip to main content
Glama

Fantasy Premier League MCP Server

MIT License
58
  • Apple
players.py13.1 kB
"""Player information tools for Fantasy Premier League.""" import logging from typing import Any, Dict, Optional from ..resources.players import get_player_by_id, find_players_by_name from ..resources.gameweeks import get_current_gameweek_resource from ..resources.fixtures import get_player_fixtures, get_player_gameweek_history async def get_player_info( player_id: Optional[int] = None, player_name: Optional[str] = None, start_gameweek: Optional[int] = None, end_gameweek: Optional[int] = None, include_history: bool = True, include_fixtures: bool = True ) -> Dict[str, Any]: """ Get detailed information for a specific player, optionally filtering stats by gameweek range. Args: player_id: FPL player ID (if provided, takes precedence over player_name) player_name: Player name to search for (used if player_id not provided) start_gameweek: Starting gameweek for filtering player history end_gameweek: Ending gameweek for filtering player history include_history: Whether to include gameweek-by-gameweek history include_fixtures: Whether to include upcoming fixtures Returns: Detailed player information including stats and history """ logger = logging.getLogger(__name__) logger.info(f"Getting player info: ID={player_id}, name={player_name}") # Get current gameweek current_gw_info = await get_current_gameweek_resource() current_gw = current_gw_info.get("id", 1) # Find player by ID or name player = None if player_id is not None: player = await get_player_by_id(player_id) elif player_name: matches = await find_players_by_name(player_name) if matches: player = matches[0] player_id = player.get("id") if not player: return { "error": f"Player not found: ID={player_id}, name={player_name}" } # Prepare result with basic player info result = { "player_id": player.get("id"), "name": player.get("name"), "web_name": player.get("web_name"), "team": player.get("team"), "team_short": player.get("team_short"), "position": player.get("position"), "price": player.get("price"), "season_stats": { "total_points": player.get("points"), "points_per_game": player.get("points_per_game"), "minutes": player.get("minutes"), "goals": player.get("goals"), "assists": player.get("assists"), "clean_sheets": player.get("clean_sheets"), "bonus": player.get("bonus"), "form": player.get("form"), }, "ownership": { "selected_by_percent": player.get("selected_by_percent"), "transfers_in_event": player.get("transfers_in_event"), "transfers_out_event": player.get("transfers_out_event"), }, "status": { "status": "available" if player.get("status") == "a" else "unavailable", "news": player.get("news"), "chance_of_playing_next_round": player.get("chance_of_playing_next_round"), } } # Add expected stats if available if "expected_goals" in player: result["expected_stats"] = { "expected_goals": player.get("expected_goals"), "expected_assists": player.get("expected_assists"), "expected_goal_involvements": player.get("expected_goal_involvements"), "expected_goals_conceded": player.get("expected_goals_conceded"), } # Add advanced metrics result["advanced_metrics"] = { "influence": player.get("influence"), "creativity": player.get("creativity"), "threat": player.get("threat"), "ict_index": player.get("ict_index"), "bps": player.get("bps"), } # Determine and validate gameweek range # Convert Optional[int] to int with defaults start_gw: int = 1 if start_gameweek is None else max(1, start_gameweek) end_gw: int = current_gw if end_gameweek is None else min(current_gw, end_gameweek) # Ensure start <= end if start_gw > end_gw: start_gw = end_gw # Set the validated values as int (not Optional[int]) start_gameweek = start_gw end_gameweek = end_gw # Include gameweek history if requested if include_history and "history" in player: # Filter history by gameweek range filtered_history = [ gw for gw in player.get("history", []) if start_gameweek <= gw.get("round", 0) <= end_gameweek ] # Get detailed gameweek history player_id_value = player.get("id") if player_id_value is not None: gw_count = max(1, end_gameweek - start_gameweek + 1) gameweek_history = await get_player_gameweek_history( [player_id_value], gw_count) else: gameweek_history = None # Combine data history_data = filtered_history if gameweek_history and "players" in gameweek_history: player_id_str = str(player.get("id", "")) if player_id_str in gameweek_history["players"]: detailed_history = gameweek_history["players"][player_id_str] # Enrich with additional stats if available for gw_data in history_data: gw_num = gw_data.get("round") # Find matching detailed gameweek matching_detailed = next(( gw for gw in detailed_history if gw.get("round") == gw_num or gw.get("gameweek") == gw_num ), None) if matching_detailed: for key, value in matching_detailed.items(): # Don't overwrite existing keys if key not in gw_data: gw_data[key] = value # Add summary stats for the filtered period period_stats = {} if history_data: # Calculate sums minutes = sum(gw.get("minutes", 0) for gw in history_data) points = sum(gw.get("total_points", 0) for gw in history_data) goals = sum(gw.get("goals_scored", 0) for gw in history_data) assists = sum(gw.get("assists", 0) for gw in history_data) bonus = sum(gw.get("bonus", 0) for gw in history_data) clean_sheets = sum(gw.get("clean_sheets", 0) for gw in history_data) # Calculate averages games_played = len(history_data) games_started = sum(1 for gw in history_data if gw.get("minutes", 0) >= 60) points_per_game = points / games_played if games_played > 0 else 0 period_stats = { "gameweeks_analyzed": games_played, "games_started": games_started, "minutes": minutes, "total_points": points, "points_per_game": round(points_per_game, 1), "goals": goals, "assists": assists, "goal_involvements": goals + assists, "clean_sheets": clean_sheets, "bonus": bonus, } result["gameweek_range"] = { "start": start_gameweek, "end": end_gameweek, } result["gameweek_history"] = history_data result["period_stats"] = period_stats # Include upcoming fixtures if requested if include_fixtures and player_id is not None: fixtures_data = await get_player_fixtures(player_id, 5) # Next 5 fixtures if fixtures_data: result["upcoming_fixtures"] = fixtures_data # Calculate average fixture difficulty difficulty_values = [f.get("difficulty", 3) for f in fixtures_data] avg_difficulty = ( sum(difficulty_values) / len(difficulty_values) if difficulty_values else 3 ) # Convert to a 1-10 scale where 10 is best (easiest fixtures) fixture_score = (6 - avg_difficulty) * 2 result["fixture_analysis"] = { "difficulty_score": round(fixture_score, 1), "fixtures_analyzed": len(fixtures_data), "home_matches": sum(1 for f in fixtures_data if f.get("location") == "home"), "away_matches": sum(1 for f in fixtures_data if f.get("location") == "away"), } # Add fixture difficulty assessment if "fixture_analysis" in result and isinstance(result["fixture_analysis"], dict): fixture_analysis = result["fixture_analysis"] if fixture_score >= 8: fixture_analysis["assessment"] = "Excellent fixtures" elif fixture_score >= 6: fixture_analysis["assessment"] = "Good fixtures" elif fixture_score >= 4: fixture_analysis["assessment"] = "Average fixtures" else: fixture_analysis["assessment"] = "Difficult fixtures" return result async def search_players( query: str, position: Optional[str] = None, team: Optional[str] = None, limit: int = 5 ) -> Dict[str, Any]: """ Search for players by name with optional filtering by position and team. Args: query: Player name or partial name to search for position: Optional position filter (GKP, DEF, MID, FWD) team: Optional team name filter limit: Maximum number of results to return Returns: List of matching players with details """ logger = logging.getLogger(__name__) logger.info(f"Searching players: query={query}, position={position}, team={team}") # Find players by name matches = await find_players_by_name(query, limit=limit * 2) # Get more than needed for filtering # Apply position filter if specified if position and matches: matches = [p for p in matches if p.get("position") == position.upper()] # Apply team filter if specified if team and matches: matches = [ p for p in matches if team.lower() in p.get("team", "").lower() or team.lower() in p.get("team_short", "").lower() ] # Limit results matches = matches[:limit] return { "query": query, "filters": { "position": position, "team": team, }, "total_matches": len(matches), "players": matches } def register_tools(mcp): """Register player-related tools with MCP.""" @mcp.tool() async def get_player_information( player_id: Optional[int] = None, player_name: Optional[str] = None, start_gameweek: Optional[int] = None, end_gameweek: Optional[int] = None, include_history: bool = True, include_fixtures: bool = True ) -> Dict[str, Any]: """Get detailed information and statistics for a specific player Args: player_id: FPL player ID (if provided, takes precedence over player_name) player_name: Player name to search for (used if player_id not provided) start_gameweek: Starting gameweek for filtering player history end_gameweek: Ending gameweek for filtering player history include_history: Whether to include gameweek-by-gameweek history include_fixtures: Whether to include upcoming fixtures Returns: Comprehensive player information including stats and history """ # Handle case when a dictionary is passed instead of expected types if isinstance(player_name, dict): if 'player_name' in player_name: player_name = player_name['player_name'] elif 'query' in player_name: player_name = player_name['query'] return await get_player_info( player_id, player_name, start_gameweek, end_gameweek, include_history, include_fixtures ) @mcp.tool() async def search_fpl_players( query: str, position: Optional[str] = None, team: Optional[str] = None, limit: int = 5 ) -> Dict[str, Any]: """Search for FPL players by name with optional filtering Args: query: Player name or partial name to search for position: Optional position filter (GKP, DEF, MID, FWD) team: Optional team name filter limit: Maximum number of results to return Returns: List of matching players with details """ # Handle case when a dictionary is passed instead of string if isinstance(query, dict) and 'query' in query: query = query['query'] return await search_players(query, position, team, limit) # Register tools register_tools = register_tools

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/rishijatia/fantasy-pl-mcp'

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