Skip to main content
Glama
lenwood

cfbd-mcp-server

by lenwood

get-drives

Retrieve college football drive data from the College Football Data API by specifying parameters like year, team, conference, or game details.

Instructions

Note: When using this tool, please explicitly mention that you are retrieving data from the College Football Data API. You must mention "College Football Data API" in every response.

Get college football drive data.
        Required: year
        Optional: season_type, week, team, offense, defense, conference, offense_conference, defense_conference, classification
        Example valid queries:
        - year=2023
        - year=2023, team="Alabama"
        - year=2023, offense="Alabama", defense="Auburn"
        

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
yearYes
season_typeNo
weekNo
teamNo
offenseNo
defenseNo
conferenceNo
offense_conferenceNo
defense_conferenceNo
classificationNo

Implementation Reference

  • Main handler for all MCP tools including 'get-drives'. Validates arguments using the getDrives schema, maps to CFBD API endpoint '/drives', performs HTTP GET request, and returns JSON response as text.
    @server.call_tool()
    async def handle_call_tool(
        name: str,
        arguments: dict[str, Any] | None
    ) -> list[types.TextContent]:
        """Handle tool execution requests."""
        if not arguments:
            raise ValueError("Arguments are required")
    
        # Map tool names to their parameter schemas
        schema_map = {
            "get-games": getGames,
            "get-records": getTeamRecords,
            "get-games-teams": getGamesTeams,
            "get-plays": getPlays,
            "get-drives": getDrives,
            "get-play-stats": getPlayStats,
            "get-rankings": getRankings,
            "get-pregame-win-probability": getMetricsPregameWp,
            "get-advanced-box-score": getAdvancedBoxScore
        }
    
        if name not in schema_map:
            raise ValueError(f"Unknown tool: {name}")
    
        # Validate parameters against schema
        try:
            validated_params = validate_params(arguments, schema_map[name])
        except ValueError as e:
            return [types.TextContent(
                type="text",
                text=f"Validation error: {str(e)}"
            )]
    
        endpoint_map = {
            "get-games": "/games",
            "get-records": "/records",
            "get-games-teams": "/games/teams",
            "get-plays": "/plays",
            "get-drives": "/drives",
            "get-play-stats": "/play/stats",
            "get-rankings": "/rankings",
            "get-pregame-win-probability": "/metrics/wp/pregame",
            "get-advanced-box-score": "/game/box/advanced"
        }
       
        async with await get_api_client() as client:
            try:
                response = await client.get(endpoint_map[name], params=arguments)
                response.raise_for_status()
                data = response.json()
                return [types.TextContent(
                    type="text",
                    text=str(data)
                )]
            except httpx.HTTPStatusError as e:
                if e.response.status_code == 401:
                    return [types.TextContent(
                        type="text",
                        text="401: API authentication failed. Please check your API key."
                    )]
                elif e.response.status_code == 403:
                    return [types.TextContent(
                        type="text",
                        text="403: API access forbidden. Please check your permission."
                    )]
                elif e.response.status_code == 429:
                    return [types.TextContent(
                        type="text",
                        text="429: Rate limit exceeded. Please try again later."
                    )]
                else:
                    return [types.TextContent(
                        type="text",
                        text=f"API Error: {e}"
                    )]
            except httpx.RequestError as e:
                return [types.TextContent(
                    type="text",
                    text=f"Network error: {str(e)}"
                )]
  • Registers the 'get-drives' tool with the MCP server in list_tools(), defining its name, description, and input schema from getDrives TypedDict.
    types.Tool(
        name="get-drives",
        description=base_description + """Get college football drive data.
        Required: year
        Optional: season_type, week, team, offense, defense, conference, offense_conference, defense_conference, classification
        Example valid queries:
        - year=2023
        - year=2023, team="Alabama"
        - year=2023, offense="Alabama", defense="Auburn"
        """,
        inputSchema=create_tool_schema(getDrives)
    ),
  • TypedDict defining the input parameters for the 'get-drives' tool corresponding to CFBD /drives endpoint.
    class getDrives(TypedDict): # /drives endpoint
        year: int
        season_type: Optional[str]
        week: Optional[int]
        team: Optional[str]
        offense: Optional[str]
        defense: Optional[str]
        conference: Optional[str]
        offense_conference: Optional[str]
        defense_conference: Optional[str]
        classification: Optional[str]
  • TypedDict defining the expected response structure from CFBD /drives endpoint used by 'get-drives' tool.
    class DrivesResponse(TypedDict): # /drives response
        offense: str
        offense_conference: Optional[str]  # Optional since team might not have conference
        defense: str
        defense_conference: Optional[str]
        game_id: int
        id: int
        drive_number: int
        scoring: bool
        start_period: int
        start_yardline: int
        start_yards_to_goal: int
        start_time: GameClock
        end_period: int
        end_yardline: int
        end_yards_to_goal: int
        end_time: GameClock
        plays: int
        yards: int
        drive_result: str
        is_home_offense: bool
        start_offense_score: int
        start_defense_score: int
        end_offense_score: int
        end_defense_score: int
  • Helper function to validate tool input parameters against TypedDict schema (e.g., getDrives), enforces types, optionality, and valid values for classification.
    def validate_params(params: dict, schema_class: Type[TypedDict]) -> dict:
        """Validate parameters against a TypedDict schema."""
        try:
            # Get the annotations from the schema class
            expected_types = schema_class.__annotations__
            validated_params = {}
    
            # Validate each parameter
            for key, value in params.items():
                if key not in expected_types:
                    raise ValueError(f"Unexpected parameter: {key}")
    
                expected_type = expected_types[key]
    
                # Special handling for classification parameter
                if key == "classification" and value is not None:
                    value = value.lower()
                    if value not in VALID_DIVISIONS:
                        raise ValueError(f"Invalid Classification: Must be one of: {', '.join(VALID_DIVISIONS)}")
    
                # Handle Optional types
                if hasattr(expected_type, "__origin__") and expected_type.__origin__ is Union:
                    if type(None) in expected_type.__args__:
                        # Parameter is optional
                        if value is not None:
                            # Validate against the non-None type
                            non_none_type = next(t for t in expected_type.__args__ if t != type(None))
                            # Handle primitive types
                            if non_none_type in (str, int, float, bool):
                                if not isinstance(value, non_none_type):
                                    raise ValueError(f"Parameter {key} must be of type {non_none_type.__name__}")
                            validated_params[key] = value
                        else:
                            validated_params[key] = None
                else:
                    # Parameter is required
                    if not isinstance(value, expected_type):
                        raise ValueError(f"Parameter {key} must be of type {expected_type.__name__}")
                    validated_params[key] = value
    
            # Check for required parameters
            for param, param_type in expected_types.items():
                is_optional = (hasattr(param_type, "__origin__") and 
                             param_type.__origin__ is Union and 
                             type(None) in param_type.__args__)
                if not is_optional and param not in params:
                    raise ValueError(f"Missing required parameter: {param}")
    
            return validated_params
        
        except Exception as e:
            raise ValueError(f"Parameter validation failed: {str(e)}")
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries full burden for behavioral disclosure. It mentions a formatting requirement ('mention College Football Data API in every response'), which is useful context. However, it doesn't describe critical behavioral traits like whether this is a read-only operation, potential rate limits, authentication needs, error handling, or what the return format looks like (no output schema exists).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is appropriately sized but not optimally structured. The first paragraph contains a formatting requirement that belongs elsewhere (not core tool functionality). The core purpose statement is clear, but the parameter information could be more front-loaded. The example queries are helpful but could be more efficiently integrated.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (10 parameters, no annotations, no output schema), the description provides adequate but incomplete coverage. It documents parameters well but lacks behavioral context about the operation's safety, performance characteristics, or return format. The formatting requirement adds some context but doesn't address core completeness gaps for a data retrieval tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description adds substantial value beyond the input schema, which has 0% description coverage. It clearly identifies which parameter is required ('year') versus optional, lists all 10 parameters by name, and provides three concrete example queries showing how parameters combine. This compensates fully for the schema's lack of documentation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Get college football drive data.' It specifies the resource (drive data) and domain (college football), making the verb+resource combination clear. However, it doesn't explicitly differentiate this tool from its siblings like 'get-plays' or 'get-games', which would be needed for a perfect score.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. While it mentions the College Football Data API in a formatting requirement, it doesn't explain when to choose 'get-drives' over sibling tools like 'get-plays' or 'get-games' for related football data queries. The example queries show parameter usage but not tool selection criteria.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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/lenwood/cfbd-mcp-server'

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