outs_above_average
Retrieve Outs Above Average (OAA) leaderboards to evaluate defensive performance by position in MLB. This tool calculates how many outs a fielder saved compared to an average defender, using parameters like year, position, and minimum attempts.
Instructions
Outs Above Average (OAA) leaderboard by defensive position.
OAA estimates how many outs a fielder saved vs an average defender.
Args: year: Season year (e.g. 2024). position: One of: SS, 2B, 3B, 1B, LF, CF, RF, or ALL (all infield + outfield positions supported by Savant). Not available for catcher in this leaderboard. min_attempts: Minimum fielding attempts, or "q" for qualified (default). player_name: Optional. Filter to one fielder (use a position they actually play).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| year | Yes | ||
| position | Yes | ||
| min_attempts | No | q | |
| player_name | No |
Implementation Reference
- src/statcast_mcp/server.py:1257-1299 (handler)The outs_above_average function acts as the handler for the tool, retrieving data from pybaseball and formatting the result.
def outs_above_average( year: int, position: str, min_attempts: str | int = "q", player_name: str | None = None, ) -> str: """Outs Above Average (OAA) leaderboard by defensive position. OAA estimates how many outs a fielder saved vs an average defender. Args: year: Season year (e.g. 2024). position: One of: SS, 2B, 3B, 1B, LF, CF, RF, or ALL (all infield + outfield positions supported by Savant). Not available for catcher in this leaderboard. min_attempts: Minimum fielding attempts, or "q" for qualified (default). player_name: Optional. Filter to one fielder (use a position they actually play). """ from pybaseball import statcast_outs_above_average as _fn pos = position.strip().upper() if pos == "ALL": pos = "all" try: data = _fn(year, pos, min_att=min_attempts) except ValueError as e: return str(e) except Exception as e: return f"Error fetching OAA: {e}" if player_name: try: data = _filter_player_rows(data, player_name) except ValueError as e: return str(e) if data.empty: return ( f"No OAA row for {player_name} at position {position} in {year}. " "Try position=ALL or a different position." ) return _fmt(data, max_rows=50)