fpl-mcp-server 0.1.4__py3-none-any.whl → 0.1.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,105 @@
1
+ """
2
+ FPL MCP Prompts - Team Selection.
3
+
4
+ Prompts guide the LLM in selecting the optimal starting XI and bench ordering
5
+ for a specific gameweek.
6
+ """
7
+
8
+ from ..tools import mcp
9
+
10
+
11
+ @mcp.prompt()
12
+ def select_team(team_id: int, gameweek: int | None = None) -> str:
13
+ """
14
+ Optimize Starting XI and Bench using fixture analysis and player status.
15
+
16
+ This prompt guides the LLM to choose the best starting lineup and bench order
17
+ based on fixture difficulty, player availability, and form.
18
+
19
+ Args:
20
+ team_id: Manager's FPL team ID
21
+ gameweek: Target gameweek (defaults to current/next if None)
22
+ """
23
+ gameweek_text = f"gameweek {gameweek}" if gameweek else "the upcoming gameweek"
24
+ gameweek_display = f"{gameweek}" if gameweek else "Upcoming"
25
+
26
+ return f"""Optimize the Starting XI and Bench for team ID {team_id} in {gameweek_text}.
27
+ **OBJECTIVE: Select the highest-scoring Starting XI and optimize Bench ordering.**
28
+
29
+ ---
30
+
31
+ ## 🚦 **Workflow & Logic**
32
+
33
+ 1. **Get Squad & Status**: Fetch manager's team and check for injuries/suspensions.
34
+ 2. **Analyze Fixtures**: Evaluate opponent strength (Attack vs Defense).
35
+ 3. **Select Lineup**: Best 11 players regardless of formation (valid formations only: 3-4-3, 3-5-2, 4-4-2, 4-3-3, 5-3-2, etc.).
36
+
37
+ ---
38
+
39
+ ## 🧠 **Selection Strategy**
40
+
41
+ ### **1. Starting XI Priority (Must Starts)**
42
+ * **Premiums**: Always start (e.g., Salah, Haaland) unless injured.
43
+ * **Form Attackers**: Start players with xGI > 0.5 recently, even with tricky fixtures (Attack beats Defense).
44
+ * **Defenders with Clean Sheet Potential**: Start defenders vs Bottom 5 Attacks.
45
+ * **Attacking Defenders**: Start defenders with high xA (e.g., Trent, Porro) regardless of fixture, unless playing Man City/Arsenal away.
46
+
47
+ ### **2. Bench Decisions (The "Dilemma" Area)**
48
+ * **Bench Defenders vs Top 6 Attack**: If you have a decent backup mid/fwd, bench the defender playing a top team.
49
+ * **Bench Rotation Risks**: If a player is a massive rotation risk (e.g., Pep Roulette), they can still start if the ceiling is high, but have a secure #1 bench sub ready.
50
+ * **Bench Injured/Suspended**: Move to slots #2 and #3.
51
+
52
+ ### **3. Optimizing Bench Order**
53
+ * **Slot 1**: **Highest Ceiling**. The player who can score 10+ points if they come on (e.g., Explosive Winger vs tough defense > 2pt Defender).
54
+ * **Slot 2**: **Safety**. The 90-min defender who guarantees 1-2 points if Slot 1 doesn't play.
55
+ * **Slot 3**: **Fodder/Red Flags**.
56
+
57
+ ---
58
+
59
+ ## 📝 **Output Format:**
60
+
61
+ **Recommended Lineup for Gameweek {gameweek_display}**
62
+
63
+ *(Formation: [e.g. 3-4-3])*
64
+
65
+ **Defense**
66
+ * **GK**: [Name] (vs [Opponent])
67
+ * *Rationale*: [One line reason, e.g., "Opponent lowest xG in league"]
68
+ * **DEF**: [Name] (vs [Opponent])
69
+ * **DEF**: [Name] (vs [Opponent])
70
+ * ...
71
+
72
+ **Midfield**
73
+ * **MID**: [Name] (vs [Opponent])
74
+ * **MID**: [Name] (vs [Opponent])
75
+ * ...
76
+
77
+ **Forwards**
78
+ * **FWD**: [Name] (vs [Opponent])
79
+ * ...
80
+
81
+ **©️ Captain**: [Name] (Run `recommend_captain` for detailed analysis)
82
+ **⚡ Vice-Captain**: [Name] (Secure starter with highest ceiling)
83
+
84
+ ---
85
+
86
+ **Bench (Critical Order)**
87
+ 1. **[Name]** ([Pos] vs [Opponent])
88
+ * *Why #1?*: [e.g., "High ceiling upside despite tough fixture"]
89
+ 2. **[Name]** ([Pos] vs [Opponent])
90
+ 3. **[Name]** ([Pos] vs [Opponent])
91
+ 4. **GK [Name]** ([Pos] vs [Opponent])
92
+
93
+ ---
94
+
95
+ ## ⚠️ **Transfer Alert (Optional)**
96
+ * If the team has **>2 non-playing players** (Red flags/Bench fodder) in the starting XI/Bench 1:
97
+ * **Recommendation**: "Consider a transfer for [Player Name] → [Replacement Tool]"
98
+
99
+ ## 🔧 **Tool Usage**
100
+ 1. `fpl_get_manager_by_team_id(team_id={team_id})` → Get squad.
101
+ 2. `fpl_get_gameweek_fixtures(gameweek={gameweek})` → Get matchups.
102
+ 3. `fpl_get_player_summary(player_id=...)` -> Check status if flagged.
103
+
104
+ **Begin Selection Analysis.**
105
+ """
@@ -7,6 +7,7 @@ Bootstrap resources expose static FPL data that rarely changes during a season.
7
7
  from datetime import UTC, datetime
8
8
 
9
9
  from ..client import FPLClient
10
+ from ..constants import PlayerPosition
10
11
  from ..state import store
11
12
  from ..tools import mcp
12
13
 
@@ -31,7 +32,12 @@ async def get_all_players_resource() -> str:
31
32
  output = [f"**All FPL Players ({len(players)} total)**\n"]
32
33
 
33
34
  # Group by position
34
- positions = {"GKP": [], "DEF": [], "MID": [], "FWD": []}
35
+ positions = {
36
+ PlayerPosition.GOALKEEPER.value: [],
37
+ PlayerPosition.DEFENDER.value: [],
38
+ PlayerPosition.MIDFIELDER.value: [],
39
+ PlayerPosition.FORWARD.value: [],
40
+ }
35
41
  for p in players:
36
42
  if p.position in positions:
37
43
  positions[p.position].append(p)
src/state.py CHANGED
@@ -4,6 +4,12 @@ import logging
4
4
  from .cache import cache_manager
5
5
  from .client import FPLClient
6
6
  from .config import settings
7
+ from .constants import (
8
+ FUZZY_MATCH_PENALTY,
9
+ FUZZY_MATCH_THRESHOLD,
10
+ PERFECT_MATCH_SCORE,
11
+ SUBSTRING_MATCH_PENALTY,
12
+ )
7
13
  from .models import BootstrapData, ElementData, EventData, FixtureData
8
14
 
9
15
  logger = logging.getLogger("fpl_state")
@@ -193,7 +199,7 @@ class SessionStore:
193
199
  # 1. Exact match
194
200
  if normalized_query in self.player_name_map:
195
201
  for player_id in self.player_name_map[normalized_query]:
196
- results[player_id] = 1.0
202
+ results[player_id] = PERFECT_MATCH_SCORE
197
203
 
198
204
  # 2. Substring match (contains)
199
205
  if not results:
@@ -205,16 +211,16 @@ class SessionStore:
205
211
  )
206
212
  for player_id in player_ids:
207
213
  if player_id not in results or similarity > results[player_id]:
208
- results[player_id] = similarity * 0.9 # Slightly lower than exact
214
+ results[player_id] = similarity * SUBSTRING_MATCH_PENALTY
209
215
 
210
216
  # 3. Fuzzy matching (if enabled and no good matches yet)
211
217
  if fuzzy and (not results or max(results.values()) < 0.7):
212
218
  for name_key, player_ids in self.player_name_map.items():
213
219
  similarity = SequenceMatcher(None, normalized_query, name_key).ratio()
214
- if similarity >= 0.6: # Threshold for fuzzy matches
220
+ if similarity >= FUZZY_MATCH_THRESHOLD:
215
221
  for player_id in player_ids:
216
222
  if player_id not in results or similarity > results[player_id]:
217
- results[player_id] = similarity * 0.8 # Lower than substring
223
+ results[player_id] = similarity * FUZZY_MATCH_PENALTY
218
224
 
219
225
  # Convert to list of tuples and sort by score
220
226
  player_matches = [
src/tools/__init__.py CHANGED
@@ -6,8 +6,6 @@ from mcp.server.fastmcp import FastMCP
6
6
  # Create shared MCP instance following Python naming convention: {service}_mcp
7
7
  mcp = FastMCP("fpl_mcp")
8
8
 
9
- # Import all tool modules (this registers tools with mcp) # noqa: E402
10
- # Import resources and prompts (this registers them with mcp)
11
9
  from .. import (
12
10
  prompts, # noqa: F401
13
11
  resources, # noqa: F401
src/tools/fixtures.py CHANGED
@@ -11,14 +11,8 @@ from ..utils import (
11
11
  format_json_response,
12
12
  handle_api_error,
13
13
  )
14
-
15
- # Import shared mcp instance
16
14
  from . import mcp
17
15
 
18
- # =============================================================================
19
- # Pydantic Input Models
20
- # =============================================================================
21
-
22
16
 
23
17
  class GetFixturesForGameweekInput(BaseModel):
24
18
  """Input model for getting fixtures for a gameweek."""
@@ -34,11 +28,6 @@ class GetFixturesForGameweekInput(BaseModel):
34
28
  )
35
29
 
36
30
 
37
- # =============================================================================
38
- # Helper Functions
39
- # =============================================================================
40
-
41
-
42
31
  async def _create_client():
43
32
  """Create an unauthenticated FPL client for public API access and ensure data is loaded."""
44
33
  client = FPLClient(store=store)
@@ -47,11 +36,6 @@ async def _create_client():
47
36
  return client
48
37
 
49
38
 
50
- # =============================================================================
51
- # MCP Tools
52
- # =============================================================================
53
-
54
-
55
39
  @mcp.tool(
56
40
  name="fpl_get_fixtures_for_gameweek",
57
41
  annotations={
src/tools/gameweeks.py CHANGED
@@ -14,14 +14,8 @@ from ..utils import (
14
14
  format_json_response,
15
15
  handle_api_error,
16
16
  )
17
-
18
- # Import shared mcp instance
19
17
  from . import mcp
20
18
 
21
- # =============================================================================
22
- # Pydantic Input Models
23
- # =============================================================================
24
-
25
19
 
26
20
  class GetCurrentGameweekInput(BaseModel):
27
21
  """Input model for getting current gameweek."""
@@ -57,11 +51,6 @@ class ListAllGameweeksInput(BaseModel):
57
51
  )
58
52
 
59
53
 
60
- # =============================================================================
61
- # Helper Functions
62
- # =============================================================================
63
-
64
-
65
54
  async def _create_client():
66
55
  """Create an unauthenticated FPL client for public API access and ensure data is loaded."""
67
56
  client = FPLClient(store=store)
@@ -70,11 +59,6 @@ async def _create_client():
70
59
  return client
71
60
 
72
61
 
73
- # =============================================================================
74
- # MCP Tools
75
- # =============================================================================
76
-
77
-
78
62
  @mcp.tool(
79
63
  name="fpl_get_current_gameweek",
80
64
  annotations={
src/tools/leagues.py CHANGED
@@ -12,14 +12,8 @@ from ..utils import (
12
12
  format_json_response,
13
13
  handle_api_error,
14
14
  )
15
-
16
- # Import shared mcp instance
17
15
  from . import mcp
18
16
 
19
- # =============================================================================
20
- # Pydantic Input Models
21
- # =============================================================================
22
-
23
17
 
24
18
  class GetLeagueStandingsInput(BaseModel):
25
19
  """Input model for getting league standings."""
@@ -99,9 +93,26 @@ class GetManagerSquadInput(BaseModel):
99
93
  )
100
94
 
101
95
 
102
- # =============================================================================
103
- # Helper Functions
104
- # =============================================================================
96
+ class GetManagerByTeamIdInput(BaseModel):
97
+ """Input model for getting manager profile by team ID."""
98
+
99
+ model_config = ConfigDict(str_strip_whitespace=True, validate_assignment=True)
100
+
101
+ team_id: int = Field(
102
+ ...,
103
+ description="Manager's team ID (entry ID)",
104
+ ge=1,
105
+ )
106
+ gameweek: int | None = Field(
107
+ default=None,
108
+ description="Gameweek number (1-38). If not provided, uses current gameweek",
109
+ ge=1,
110
+ le=38,
111
+ )
112
+ response_format: ResponseFormat = Field(
113
+ default=ResponseFormat.MARKDOWN,
114
+ description="Output format: 'markdown' for human-readable or 'json' for machine-readable",
115
+ )
105
116
 
106
117
 
107
118
  async def _create_client():
@@ -112,11 +123,6 @@ async def _create_client():
112
123
  return client
113
124
 
114
125
 
115
- # =============================================================================
116
- # MCP Tools
117
- # =============================================================================
118
-
119
-
120
126
  @mcp.tool(
121
127
  name="fpl_get_league_standings",
122
128
  annotations={
@@ -588,3 +594,161 @@ async def fpl_get_manager_squad(params: GetManagerSquadInput) -> str:
588
594
 
589
595
  except Exception as e:
590
596
  return handle_api_error(e)
597
+
598
+
599
+ @mcp.tool(
600
+ name="fpl_get_manager_by_team_id",
601
+ annotations={
602
+ "title": "Get Manager Profile by Team ID",
603
+ "readOnlyHint": True,
604
+ "destructiveHint": False,
605
+ "idempotentHint": True,
606
+ "openWorldHint": True,
607
+ },
608
+ )
609
+ async def fpl_get_manager_by_team_id(params: GetManagerByTeamIdInput) -> str:
610
+ """
611
+ Get manager profile and squad information using team ID directly.
612
+
613
+ This tool provides the same functionality as fpl_get_manager_squad but with
614
+ a name that better reflects its purpose - getting manager information without
615
+ requiring league context. Shows the 15 players picked, captain/vice-captain
616
+ choices, formation, points scored, transfers made, and automatic substitutions.
617
+
618
+ Args:
619
+ params (GetManagerByTeamIdInput): Validated input parameters containing:
620
+ - team_id (int): Manager's team ID (entry ID)
621
+ - gameweek (int | None): Gameweek number (1-38), defaults to current GW
622
+ - response_format (ResponseFormat): 'markdown' or 'json' (default: markdown)
623
+
624
+ Returns:
625
+ str: Complete manager profile with squad, statistics, and team info
626
+
627
+ Examples:
628
+ - View current squad: team_id=123456
629
+ - View specific gameweek: team_id=123456, gameweek=20
630
+ - Get as JSON: team_id=123456, response_format="json"
631
+
632
+ Error Handling:
633
+ - Returns error if team ID not found (404)
634
+ - Returns error if gameweek not started yet
635
+ - Returns formatted error message if API fails
636
+ """
637
+ try:
638
+ client = await _create_client()
639
+
640
+ # Fetch manager entry to get team name and player name
641
+ try:
642
+ entry_data = await client.get_manager_entry(params.team_id)
643
+ except Exception:
644
+ return f"Manager with team ID {params.team_id} not found. Verify the team ID is correct."
645
+
646
+ team_name = entry_data.get("name", "Unknown Team")
647
+ player_name = f"{entry_data.get('player_first_name', '')} {entry_data.get('player_last_name', '')}".strip()
648
+
649
+ # Determine which gameweek to use
650
+ gameweek = params.gameweek
651
+ if gameweek is None:
652
+ current_gw = store.get_current_gameweek()
653
+ if not current_gw:
654
+ return "Error: Could not determine current gameweek. Please specify a gameweek number."
655
+ gameweek = current_gw.id
656
+
657
+ # Fetch gameweek picks from API
658
+ picks_data = await client.get_manager_gameweek_picks(params.team_id, gameweek)
659
+
660
+ picks = picks_data.get("picks", [])
661
+ entry_history = picks_data.get("entry_history", {})
662
+ auto_subs = picks_data.get("automatic_subs", [])
663
+
664
+ if not picks:
665
+ return f"No team data found for team ID {params.team_id} in gameweek {gameweek}. Gameweek {gameweek} may not have started yet. Please choose an earlier gameweek or wait until GW{gameweek} begins."
666
+
667
+ # Rehydrate player names
668
+ element_ids = [pick["element"] for pick in picks]
669
+ players_info = store.rehydrate_player_names(element_ids)
670
+
671
+ if params.response_format == ResponseFormat.JSON:
672
+ starting_xi = [p for p in picks if p["position"] <= 11]
673
+ bench = [p for p in picks if p["position"] > 11]
674
+
675
+ result = {
676
+ "team_id": params.team_id,
677
+ "team_name": team_name,
678
+ "player_name": player_name,
679
+ "gameweek": gameweek,
680
+ "stats": {
681
+ "points": entry_history.get("points", 0),
682
+ "total_points": entry_history.get("total_points", 0),
683
+ "overall_rank": entry_history.get("overall_rank"),
684
+ "team_value": entry_history.get("value", 0) / 10,
685
+ "bank": entry_history.get("bank", 0) / 10,
686
+ "transfers": entry_history.get("event_transfers", 0),
687
+ "transfer_cost": entry_history.get("event_transfers_cost", 0),
688
+ "points_on_bench": entry_history.get("points_on_bench", 0),
689
+ },
690
+ "active_chip": picks_data.get("active_chip"),
691
+ "starting_xi": [
692
+ {
693
+ "position": pick["position"],
694
+ "player_name": players_info.get(pick["element"], {}).get(
695
+ "web_name", "Unknown"
696
+ ),
697
+ "team": players_info.get(pick["element"], {}).get("team", "UNK"),
698
+ "player_position": players_info.get(pick["element"], {}).get(
699
+ "position", "UNK"
700
+ ),
701
+ "price": players_info.get(pick["element"], {}).get("price", 0),
702
+ "is_captain": pick["is_captain"],
703
+ "is_vice_captain": pick["is_vice_captain"],
704
+ "multiplier": pick["multiplier"],
705
+ }
706
+ for pick in starting_xi
707
+ ],
708
+ "bench": [
709
+ {
710
+ "position": pick["position"],
711
+ "player_name": players_info.get(pick["element"], {}).get(
712
+ "web_name", "Unknown"
713
+ ),
714
+ "team": players_info.get(pick["element"], {}).get("team", "UNK"),
715
+ "player_position": players_info.get(pick["element"], {}).get(
716
+ "position", "UNK"
717
+ ),
718
+ "price": players_info.get(pick["element"], {}).get("price", 0),
719
+ }
720
+ for pick in bench
721
+ ],
722
+ "automatic_subs": [
723
+ {
724
+ "player_out": store.get_player_name(sub["element_out"]),
725
+ "player_in": store.get_player_name(sub["element_in"]),
726
+ }
727
+ for sub in auto_subs
728
+ ],
729
+ }
730
+ return format_json_response(result)
731
+ else:
732
+ result = format_manager_squad(
733
+ team_name=team_name,
734
+ player_name=player_name,
735
+ team_id=params.team_id,
736
+ gameweek=gameweek,
737
+ entry_history=entry_history,
738
+ picks=picks,
739
+ players_info=players_info,
740
+ active_chip=picks_data.get("active_chip"),
741
+ )
742
+
743
+ if auto_subs:
744
+ result += "\n\n**Automatic Substitutions:**"
745
+ for sub in auto_subs:
746
+ player_out = store.get_player_name(sub["element_out"])
747
+ player_in = store.get_player_name(sub["element_in"])
748
+ result += f"\n├─ {player_out} → {player_in}"
749
+
750
+ truncated, _ = check_and_truncate(result, CHARACTER_LIMIT)
751
+ return truncated
752
+
753
+ except Exception as e:
754
+ return handle_api_error(e)
src/tools/players.py CHANGED
@@ -3,7 +3,7 @@
3
3
  from pydantic import BaseModel, ConfigDict, Field, field_validator
4
4
 
5
5
  from ..client import FPLClient
6
- from ..constants import CHARACTER_LIMIT
6
+ from ..constants import CHARACTER_LIMIT, PlayerPosition
7
7
  from ..formatting import format_player_details
8
8
  from ..state import store
9
9
  from ..utils import (
@@ -15,14 +15,8 @@ from ..utils import (
15
15
  format_status_indicator,
16
16
  handle_api_error,
17
17
  )
18
-
19
- # Import shared mcp instance
20
18
  from . import mcp
21
19
 
22
- # =============================================================================
23
- # Pydantic Input Models
24
- # =============================================================================
25
-
26
20
 
27
21
  class SearchPlayersInput(BaseModel):
28
22
  """Input model for searching players by name."""
@@ -126,11 +120,6 @@ class GetTopPlayersByMetricInput(BaseModel):
126
120
  )
127
121
 
128
122
 
129
- # =============================================================================
130
- # Helper Functions
131
- # =============================================================================
132
-
133
-
134
123
  async def _create_client():
135
124
  """Create an unauthenticated FPL client for public API access and ensure data is loaded."""
136
125
  client = FPLClient(store=store)
@@ -280,11 +269,6 @@ async def _aggregate_player_stats_from_fixtures(client: FPLClient, num_gameweeks
280
269
  }
281
270
 
282
271
 
283
- # =============================================================================
284
- # MCP Tools
285
- # =============================================================================
286
-
287
-
288
272
  @mcp.tool(
289
273
  name="fpl_search_players",
290
274
  annotations={
@@ -440,7 +424,12 @@ async def fpl_search_players_by_team(params: SearchPlayersByTeamInput) -> str:
440
424
  return f"No players found for {team.name}. This may be a data issue."
441
425
 
442
426
  # Sort by position and price
443
- position_order = {"GKP": 1, "DEF": 2, "MID": 3, "FWD": 4}
427
+ position_order = {
428
+ PlayerPosition.GOALKEEPER.value: 1,
429
+ PlayerPosition.DEFENDER.value: 2,
430
+ PlayerPosition.MIDFIELDER.value: 3,
431
+ PlayerPosition.FORWARD.value: 4,
432
+ }
444
433
  players_sorted = sorted(
445
434
  players,
446
435
  key=lambda p: (position_order.get(p.position or "ZZZ", 5), -p.now_cost),
src/tools/teams.py CHANGED
@@ -12,14 +12,8 @@ from ..utils import (
12
12
  format_json_response,
13
13
  handle_api_error,
14
14
  )
15
-
16
- # Import shared mcp instance
17
15
  from . import mcp
18
16
 
19
- # =============================================================================
20
- # Pydantic Input Models
21
- # =============================================================================
22
-
23
17
 
24
18
  class GetTeamInfoInput(BaseModel):
25
19
  """Input model for getting team information."""
@@ -69,11 +63,6 @@ class AnalyzeTeamFixturesInput(BaseModel):
69
63
  )
70
64
 
71
65
 
72
- # =============================================================================
73
- # Helper Functions
74
- # =============================================================================
75
-
76
-
77
66
  async def _create_client():
78
67
  """Create an unauthenticated FPL client for public API access and ensure data is loaded."""
79
68
  client = FPLClient(store=store)
@@ -82,11 +71,6 @@ async def _create_client():
82
71
  return client
83
72
 
84
73
 
85
- # =============================================================================
86
- # MCP Tools
87
- # =============================================================================
88
-
89
-
90
74
  @mcp.tool(
91
75
  name="fpl_get_team_info",
92
76
  annotations={
src/tools/transfers.py CHANGED
@@ -12,14 +12,8 @@ from ..utils import (
12
12
  format_player_price,
13
13
  handle_api_error,
14
14
  )
15
-
16
- # Import shared mcp instance
17
15
  from . import mcp
18
16
 
19
- # =============================================================================
20
- # Pydantic Input Models
21
- # =============================================================================
22
-
23
17
 
24
18
  class GetPlayerTransfersByGameweekInput(BaseModel):
25
19
  """Input model for getting player transfer statistics."""
@@ -56,11 +50,6 @@ class GetManagerTransfersByGameweekInput(BaseModel):
56
50
  gameweek: int = Field(..., description="Gameweek number (1-38)", ge=1, le=38)
57
51
 
58
52
 
59
- # =============================================================================
60
- # Helper Functions
61
- # =============================================================================
62
-
63
-
64
53
  async def _create_client():
65
54
  """Create an unauthenticated FPL client for public API access and ensure data is loaded."""
66
55
  client = FPLClient(store=store)
@@ -69,11 +58,6 @@ async def _create_client():
69
58
  return client
70
59
 
71
60
 
72
- # =============================================================================
73
- # MCP Tools
74
- # =============================================================================
75
-
76
-
77
61
  @mcp.tool(
78
62
  name="fpl_get_player_transfers_by_gameweek",
79
63
  annotations={
@@ -1,33 +0,0 @@
1
- src/cache.py,sha256=SeJAmddaY9507Ac5YRnbBBXGOQw_OwpIefB-kn11lDI,4604
2
- src/client.py,sha256=9c7jViZx-YavjDeNNeBt43cAqxVW_4NK08ztUbhYvZA,9737
3
- src/config.py,sha256=hfjW-W0gdH0PxmC6gEg-o9SqraajJ6gNy1SIlIOG-F4,845
4
- src/constants.py,sha256=kzcVmX__3miaHvs976H_zF2uBG9l-O3EzsLmwSsLJRE,4466
5
- src/exceptions.py,sha256=Q8waMbF8Sr1s6lOoAB8-doX0v6EvqZopwQHGxNQ7m-w,2972
6
- src/formatting.py,sha256=aLiJWM2hJw68gyGJ1Nc1nPAyfoSIqwyjPE8svr-7ufo,10236
7
- src/main.py,sha256=C6wX96rm0-b1jSvU2BrTv47hw2FGktkwcqJ5nEM8t5U,977
8
- src/models.py,sha256=0W6tZ6ZXxJTZrdLda3QGDQ-53XKeJ37GGkekR2w3E7Q,11725
9
- src/rate_limiter.py,sha256=GLk3ZRFFvEZxkZAQd-pZ7UxQdrAAUVch3pxe_aMU-J8,3450
10
- src/state.py,sha256=aZwZw9nuI3Ipf2MYVI_IXaLNGdbfUbst5uUZtyLLTLA,17412
11
- src/utils.py,sha256=WhcWQIXpc1vIjU8hyrGDJyKJSlcbVoG938k_3UMDlCM,7340
12
- src/validators.py,sha256=aU36TUNYWb26fvZH27Xnryrp8gve9DM2phvy7vEnAi8,6891
13
- src/prompts/__init__.py,sha256=ArMCl0rgPRwWHgrsHau8Uf1zoPD_HbLniSzfzuEEADU,459
14
- src/prompts/chips.py,sha256=zzv5bqr8HuUAkvXenonrTXVhwNYGMwH9OPSC-c-1Dtg,5524
15
- src/prompts/league_analysis.py,sha256=23rNhCYkU8hSmd5BesXgNgHLFo_B8qgszmw909MPHkA,8095
16
- src/prompts/player_analysis.py,sha256=SGyd0UYWMF0lgml9idfc853UHgXXBT_qLVLf-8PFePU,5242
17
- src/prompts/squad_analysis.py,sha256=7ixTIrvTITvLIE-9ATH744ci_pObWgzx3p5yUqVHmEk,5204
18
- src/prompts/team_analysis.py,sha256=lZZ2R1xlsclwy4UyiokMg41ziuCKAqxgN_CoT1mOvnY,4104
19
- src/prompts/transfers.py,sha256=B99xjzJDTRRdwMluANjKxr5DPWB6eg69nZqJ5uyTosA,5448
20
- src/resources/__init__.py,sha256=i7nlLVSLtiIrLtOnyoMiK3KTFGEnct4LXApB4b6URFM,303
21
- src/resources/bootstrap.py,sha256=H6s1vubqNm9I3hcc6U5fdQbEPM_TJNweQvlhKVYCc9Y,6773
22
- src/tools/__init__.py,sha256=mKHfS7-KsOcMOChZ-xfWTNpShJdKTi61ClnDHiToQQw,644
23
- src/tools/fixtures.py,sha256=C2d06MX7sbVgX25oHixDorkQyJEbD0DvPdpsrytXMS4,6204
24
- src/tools/gameweeks.py,sha256=qBsMjdQajiNvt6-DZm8YDdBOYi7ZQY46wST1MuPoK8I,15429
25
- src/tools/leagues.py,sha256=XRF8h6Dt70wFtGPiU8UD6Rgpe2SAdIM9cgnDOh2geT8,23285
26
- src/tools/players.py,sha256=Jd4FUzU_qvkc6UE8rMYxZ_EM_nBWnSgIUX4MBz8WoQA,30964
27
- src/tools/teams.py,sha256=kqths5I7K_1rtsf4HyIzXpn9g8i7uMuCWbJ7YNy_tfQ,14753
28
- src/tools/transfers.py,sha256=Hy8JXjtbzRjUrtX7kg6IaDZ0IqbstISmt2Ben2Di2XE,24591
29
- fpl_mcp_server-0.1.4.dist-info/METADATA,sha256=LvkIQ3YyfaNcUU9AVyfp97j4cCWtD85FnJ-aVnV7lzg,4787
30
- fpl_mcp_server-0.1.4.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
31
- fpl_mcp_server-0.1.4.dist-info/entry_points.txt,sha256=b3R5hBUMTLVnCGl07NfK7kyq9NCKtpn5Q8OsY79pMek,49
32
- fpl_mcp_server-0.1.4.dist-info/licenses/LICENSE,sha256=HCDOcdX83voRU2Eip214yj6P_tEyjVjCsCW_sixZFPw,1071
33
- fpl_mcp_server-0.1.4.dist-info/RECORD,,