Skip to main content
Glama
alex-rimerman

Statcast MCP Server

expected_stats_batch

Retrieve expected batting statistics (xBA, xSLG, xwOBA) for multiple players in a single request to analyze lineup or rotation performance.

Instructions

Expected stats (xBA, xSLG, xwOBA vs actual) for multiple batters and/or pitchers in one call.

Use this when the user asks for a lineup, rotation, "team starters", or any named group (e.g. Yankees 1–9 and five starters). Pass comma-separated names. The MCP does not fetch MLB rosters automatically — use current player names from context or a quick web lookup, then list them here.

Args: year: Season year (e.g. 2026). If Savant has not published that season’s leaderboard yet (common before Opening Day or in early April), the table may be empty — use the prior year for full-season expected stats, or lower min_plate_appearances once enough games are played. batters: Comma-separated hitter names, e.g. "Aaron Judge, Juan Soto, Giancarlo Stanton, Anthony Volpe, ..." pitchers: Comma-separated pitcher names, e.g. "Gerrit Cole, Carlos Rodon, Marcus Stroman, Clarke Schmidt, Luis Gil" min_plate_appearances: Minimum PA to qualify (default 50).

Provide at least one of batters or pitchers. Semicolons and newlines also separate names.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
yearYes
battersNo
pitchersNo
min_plate_appearancesNo

Implementation Reference

  • The implementation of the 'expected_stats_batch' tool, which fetches and filters expected statistics for multiple batters and pitchers.
    def expected_stats_batch(
        year: int,
        batters: str | None = None,
        pitchers: str | None = None,
        min_plate_appearances: int = 50,
    ) -> str:
        """Expected stats (xBA, xSLG, xwOBA vs actual) for *multiple* batters and/or pitchers in one call.
    
        Use this when the user asks for a lineup, rotation, "team starters",
        or any named group (e.g. Yankees 1–9 and five starters). Pass comma-separated
        names. The MCP does not fetch MLB rosters automatically — use current
        player names from context or a quick web lookup, then list them here.
    
        Args:
            year: Season year (e.g. 2026). If Savant has not published that season’s leaderboard
                yet (common before Opening Day or in early April), the table may be empty — use
                the prior year for full-season expected stats, or lower ``min_plate_appearances``
                once enough games are played.
            batters: Comma-separated hitter names, e.g.
                "Aaron Judge, Juan Soto, Giancarlo Stanton, Anthony Volpe, ..."
            pitchers: Comma-separated pitcher names, e.g.
                "Gerrit Cole, Carlos Rodon, Marcus Stroman, Clarke Schmidt, Luis Gil"
            min_plate_appearances: Minimum PA to qualify (default 50).
    
        Provide at least one of batters or pitchers. Semicolons and newlines also separate names.
        """
        from pybaseball import (
            statcast_batter_expected_stats as _bat_exp,
            statcast_pitcher_expected_stats as _pit_exp,
        )
    
        batter_names = _parse_player_name_list(batters or "")
        pitcher_names = _parse_player_name_list(pitchers or "")
        if not batter_names and not pitcher_names:
            return (
                "Provide at least one of batters or pitchers as a comma-separated list "
                '(e.g. batters="Aaron Judge, Juan Soto").'
            )
    
        sections: list[str] = []
    
        def _empty_leaderboard_note(role: str, min_pa: int) -> str:
            return (
                f"**No Statcast data for {year} yet** — the `{role}` expected-stats leaderboard "
                f"returned zero rows at `min_plate_appearances={min_pa}`. "
                "That usually means the regular season has not produced enough qualified players "
                "in Savant’s feed yet, or the year’s table is not published. "
                f"Use **`year={year - 1}`** for a complete prior-season leaderboard, or retry "
                "after more games with a **lower** `min_plate_appearances`.\n\n"
            )
    
        if batter_names:
            try:
                df = _bat_exp(year, minPA=min_plate_appearances)
            except Exception as e:
                return f"Error fetching batter expected stats: {e}"
            if df is None or getattr(df, "empty", True):
                sections.append(f"### Batters (expected stats, {year})\n\n")
                sections.append(_empty_leaderboard_note("batter", min_plate_appearances))
            else:
                merged, errs = _batch_filter_players(df, batter_names)
                sections.append(f"### Batters (expected stats, {year})\n\n")
                if merged.empty:
                    sections.append("No batter rows matched.\n\n")
                else:
                    sections.append(_fmt(merged, max_rows=len(merged)))
                if errs:
                    sections.append("\n**Notes:** " + " | ".join(errs))
    
        if pitcher_names:
            try:
                df = _pit_exp(year, minPA=min_plate_appearances)
            except Exception as e:
                return f"Error fetching pitcher expected stats: {e}"
            if df is None or getattr(df, "empty", True):
                sections.append(f"\n\n### Pitchers (expected stats allowed, {year})\n\n")
                sections.append(_empty_leaderboard_note("pitcher", min_plate_appearances))
            else:
                merged, errs = _batch_filter_players(df, pitcher_names)
                sections.append(f"\n\n### Pitchers (expected stats allowed, {year})\n\n")
                if merged.empty:
                    sections.append("No pitcher rows matched.\n\n")
                else:
                    sections.append(_fmt(merged, max_rows=len(merged)))
                if errs:
                    sections.append("\n**Notes:** " + " | ".join(errs))
    
        return "".join(sections).strip()
  • The registration of the 'expected_stats_batch' tool using the @mcp.tool() decorator.
    @mcp.tool()
    def expected_stats_batch(

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/alex-rimerman/statcast-mcp'

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