Skip to main content
Glama
rishijatia

Fantasy Premier League MCP Server

analyze_player_fixtures

Analyze upcoming fixtures for Fantasy Premier League players to assess difficulty ratings and optimize team selection decisions.

Instructions

Analyze upcoming fixtures for a player and provide a difficulty rating

Args:
    player_name: Player name to search for
    num_fixtures: Number of upcoming fixtures to analyze (default: 5)

Returns:
    Analysis of player's upcoming fixtures with difficulty ratings

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
player_nameYes
num_fixturesNo

Implementation Reference

  • Registration of the MCP tool 'analyze_player_fixtures'. This wrapper function handles player lookup by name and delegates to the core implementation.
    @mcp.tool()
    async def analyze_player_fixtures(player_name: str, num_fixtures: int = 5) -> Dict[str, Any]:
        """Analyze upcoming fixtures for a player and provide a difficulty rating
        
        Args:
            player_name: Player name to search for
            num_fixtures: Number of upcoming fixtures to analyze (default: 5)
        
        Returns:
            Analysis of player's upcoming fixtures with difficulty ratings
        """
        logger.info(f"Tool called: analyze_player_fixtures({player_name}, {num_fixtures})")
        
        # Handle case when a dictionary is passed instead of string (error case)
        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']
            else:
                # If we can't find a usable key, convert the dict to a string
                player_name = str(player_name)
        
        # Handle case when num_fixtures is a dict
        if isinstance(num_fixtures, dict):
            if 'num_fixtures' in num_fixtures:
                num_fixtures = num_fixtures['num_fixtures']
            else:
                # Default to 5 if we can't find a usable value
                num_fixtures = 5
        
        # Find the player
        player_matches = await players.find_players_by_name(player_name)
        if not player_matches:
            return {"error": f"No player found matching '{player_name}'"}
    
        
        player = player_matches[0]
        analysis = await fixtures.analyze_player_fixtures(player["id"], num_fixtures)
        
        return analysis
  • Core handler function that executes the tool logic: fetches player/team/position data, gets upcoming fixtures, calculates adjusted difficulty score (1-10, higher better), provides textual analysis.
    async def analyze_player_fixtures(player_id: int, num_fixtures: int = 5) -> Dict[str, Any]:
        """Analyze upcoming fixtures for a player and provide a difficulty rating
    
        Args:
            player_id: FPL ID of the player
            num_fixtures: Number of upcoming fixtures to analyze
    
        Returns:
            Analysis of player's upcoming fixtures with difficulty ratings
        """
        logger.info(f"Analyzing player fixtures (player_id={player_id}, num_fixtures={num_fixtures})")
        
        # Get player data
        players_data = await api.get_players()
        player = None
        for p in players_data:
            if p.get("id") == player_id:
                player = p
                break
        
        if not player:
            logger.warning(f"Player with ID {player_id} not found")
            return {"error": f"Player with ID {player_id} not found"}
        
        # Get team and position data for the player
        teams_data = await api.get_teams()
        team_map = {t["id"]: t for t in teams_data}
        logger.info("Analyze Player Fixtures: Team data loaded: %s", team_map)
        
        position_data = await api.get_bootstrap_static()
        position_map = {p["id"]: p for p in position_data.get("element_types", [])}
        logger.info("Analyze Player Fixtures: Position data loaded: %s", position_map)
        
        # Map team name
        logger.info("Searching for team name %s and position %s", player.get("team"), player.get("element_type"))
        team_id = player.get("team")
        team_info = team_map.get(team_id, {})
        team_name = team_info.get("name", "Unknown team")
    
        
        # Map position name
        position_id = player.get("element_type")
        position_info = position_map.get(position_id, {})
        position_code = position_info.get("singular_name_short", "Unknown position")
    
        logger.info("Player %s plays as %s for %s", player.get("web_name"), position_code, team_name)
        
        # Make sure position is one of GK, DEF, MID, FWD
        position_mapping = {
            "GKP": "GK",
            "DEF": "DEF",
            "MID": "MID", 
            "FWD": "FWD"
        }
        position = position_mapping.get(position_code, position_code)
        
        # Get player's fixtures
        fixtures = await get_player_fixtures(player_id, num_fixtures)
        if not fixtures:
            return {
                "player": {
                    "id": player_id,
                    "name": player.get("web_name", "Unknown player"),
                    "team": team_name,
                    "position": position,
                },
                "fixture_analysis": {
                    "fixtures_analyzed": [],
                    "difficulty_score": 0,
                    "analysis": "No upcoming fixtures found"
                }
            }
        
        # Calculate difficulty score (lower is better)
        total_difficulty = sum(f["difficulty"] for f in fixtures)
        avg_difficulty = total_difficulty / len(fixtures)
        
        # Adjust for home/away balance (home advantage)
        home_fixtures = [f for f in fixtures if f["location"] == "home"]
        home_percentage = len(home_fixtures) / len(fixtures) * 100
        
        # Scale to 1-10 (invert so higher is better)
        # Difficulty is originally 1-5, where 5 is most difficult
        # We want 1-10 where 10 is best fixtures
        fixture_score = (6 - avg_difficulty) * 2
        
        # Adjust for home advantage (up to +0.5 for all home, -0.5 for all away)
        home_adjustment = (home_percentage - 50) / 100
        adjusted_score = fixture_score + home_adjustment
        
        # Cap between 1-10
        final_score = max(1, min(10, adjusted_score))
        
        # Generate text analysis
        if final_score >= 8.5:
            analysis = "Excellent fixtures - highly favorable schedule"
        elif final_score >= 7:
            analysis = "Good fixtures - favorable schedule"
        elif final_score >= 5.5:
            analysis = "Average fixtures - balanced schedule"
        elif final_score >= 4:
            analysis = "Difficult fixtures - challenging schedule"
        else:
            analysis = "Very difficult fixtures - extremely challenging schedule"
        
        # Return formatted analysis
        return {
            "player": {
                "id": player_id,
                "name": player.get("web_name", "Unknown player"),
                "team": team_name,
                "position": position_code,
            },
            "fixture_analysis": {
                "fixtures_analyzed": fixtures,
                "difficulty_score": round(final_score, 1),
                "analysis": analysis,
                "home_fixtures_percentage": round(home_percentage, 1)
            }
        }
  • Key helper function called by the handler to retrieve and format the player's upcoming fixtures.
    async def get_player_fixtures(player_id: int, num_fixtures: int = 5) -> List[Dict[str, Any]]:
        """Get upcoming fixtures for a specific player
    
        Args:
            player_id: FPL ID of the player
            num_fixtures: Number of upcoming fixtures to return
    
        Returns:
            List of upcoming fixtures for the player
        """
        logger.info(f"Getting player fixtures (player_id={player_id}, num_fixtures={num_fixtures})")
        
        # Get player data to find their team
        players_data = await api.get_players()
        player = None
        for p in players_data:
            if p.get("id") == player_id:
                player = p
                break
        
        if not player:
            logger.warning(f"Player with ID {player_id} not found")
            return []
        
        team_id = player.get("team")
        if not team_id:
            logger.warning(f"Team ID not found for player {player_id}")
            return []
        
        # Get all fixtures
        all_fixtures = await api.get_fixtures()
        if not all_fixtures:
            logger.warning("No fixtures data found")
            return []
        
        # Get gameweeks to determine current gameweek
        gameweeks = await api.get_gameweeks()
        current_gameweek = None
        for gw in gameweeks:
            if gw.get("is_current"):
                current_gameweek = gw.get("id")
                break
        
        if not current_gameweek:
            for gw in gameweeks:
                if gw.get("is_next"):
                    current_gameweek = gw.get("id") - 1
                    break
        
        if not current_gameweek:
            logger.warning("Could not determine current gameweek")
            return []
        
        # Filter upcoming fixtures for player's team
        upcoming_fixtures = []
        
        for fixture in all_fixtures:
            # Only include fixtures from current gameweek onwards
            if fixture.get("event") and fixture.get("event") >= current_gameweek:
                # Check if player's team is involved
                if fixture.get("team_h") == team_id or fixture.get("team_a") == team_id:
                    upcoming_fixtures.append(fixture)
        
        # Sort by gameweek
        upcoming_fixtures.sort(key=lambda x: x.get("event", 0))
        
        # Limit to requested number of fixtures
        upcoming_fixtures = upcoming_fixtures[:num_fixtures]
        
        # Get teams data for mapping IDs to names
        teams_data = await api.get_teams()
        team_map = {t["id"]: t for t in teams_data}
        
        # Format fixtures
        formatted_fixtures = []
        for fixture in upcoming_fixtures:
            home_id = fixture.get("team_h", 0)
            away_id = fixture.get("team_a", 0)
            
            # Determine if player's team is home or away
            is_home = home_id == team_id
            
            # Get opponent team data
            opponent_id = away_id if is_home else home_id
            opponent_team = team_map.get(opponent_id, {})
            
            # Determine difficulty - higher is more difficult
            difficulty = fixture.get("team_h_difficulty" if is_home else "team_a_difficulty", 3)
            
            formatted_fixture = {
                "gameweek": fixture.get("event"),
                "kickoff_time": fixture.get("kickoff_time", ""),
                "location": "home" if is_home else "away",
                "opponent": opponent_team.get("name", f"Team {opponent_id}"),
                "opponent_short": opponent_team.get("short_name", ""),
                "difficulty": difficulty,
            }
            
            formatted_fixtures.append(formatted_fixture)
        
        return formatted_fixtures

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

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