Skip to main content
Glama

get_race_control_messages

Retrieve race control communications including flags, safety car periods, investigations, and penalties for specific Formula 1 sessions.

Instructions

Get race control messages - flags, safety cars, investigations, penalties.

Args: year: Season year (2018+) gp: Grand Prix name or round session: 'FP1', 'FP2', 'FP3', 'Q', 'S', 'R' message_type: Filter type - 'all', 'penalties', 'investigations', 'flags', 'safety_car' (default: 'all')

Returns: RaceControlMessagesResponse with filtered messages

Examples: get_race_control_messages(2024, "Monaco", "R") → All race control messages get_race_control_messages(2024, "Monaco", "R", "penalties") → Penalties only get_race_control_messages(2024, "Monaco", "R", "flags") → Flag periods only

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
yearYes
gpYes
sessionYes
message_typeNoall

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
messagesYesRace control messages
event_nameYesGrand Prix name
session_nameYesSession name
total_messagesYesTotal number of messages

Implementation Reference

  • Main handler function that fetches race control messages from FastF1, applies optional filtering by type, and returns structured Pydantic response.
    def get_race_control_messages(
        year: int,
        gp: Union[str, int],
        session: str,
        message_type: Optional[Literal["all", "penalties", "investigations", "flags", "safety_car"]] = "all"
    ) -> RaceControlMessagesResponse:
        """
        Get race control messages - flags, safety cars, investigations, penalties.
    
        Args:
            year: Season year (2018+)
            gp: Grand Prix name or round
            session: 'FP1', 'FP2', 'FP3', 'Q', 'S', 'R'
            message_type: Filter type - 'all', 'penalties', 'investigations', 'flags', 'safety_car' (default: 'all')
    
        Returns:
            RaceControlMessagesResponse with filtered messages
    
        Examples:
            get_race_control_messages(2024, "Monaco", "R") → All race control messages
            get_race_control_messages(2024, "Monaco", "R", "penalties") → Penalties only
            get_race_control_messages(2024, "Monaco", "R", "flags") → Flag periods only
        """
        session_obj = fastf1_client.get_session(year, gp, session)
        session_obj.load(laps=False, telemetry=False, weather=False, messages=True)
    
        event = session_obj.event
        messages_df = session_obj.race_control_messages
    
        # Define filter keywords based on message type
        filter_keywords = {
            "penalties": ['penalty', 'penalties', 'penalised', 'penalized', 'reprimand',
                          'time penalty', 'grid penalty', 'warning', 'fine', 'disqualified'],
            "investigations": ['investigation', 'investigated', 'under investigation', 'incident',
                              'noted', 'will be investigated', 'under review', 'reported'],
            "flags": ['yellow', 'red flag', 'green', 'double yellow', 'track clear', 'all clear'],
            "safety_car": ['safety car', 'virtual safety', 'vsc', 'sc deployed', 'sc ending']
        }
    
        # Convert to Pydantic models with optional filtering
        messages_list = []
        for idx, row in messages_df.iterrows():
            message_text = str(row.get('Message', '')).lower()
            category = str(row.get('Category', '')).lower()
            flag = str(row.get('Flag', '')).lower() if pd.notna(row.get('Flag')) else ''
    
            # Apply filter if not "all"
            if message_type != "all":
                keywords = filter_keywords.get(message_type, [])
    
                # Check if message matches filter
                matches = False
                if message_type == "flags":
                    # For flags, also check the Flag column
                    matches = (any(keyword in message_text for keyword in keywords) or
                              any(keyword in category for keyword in keywords) or
                              (pd.notna(row.get('Flag')) and row.get('Flag') not in ['', 'CLEAR']))
                else:
                    matches = (any(keyword in message_text for keyword in keywords) or
                              any(keyword in category for keyword in keywords))
    
                if not matches:
                    continue
    
            # Add message to list
            message = RaceControlMessage(
                time=str(row['Time']) if pd.notna(row.get('Time')) else None,
                category=str(row['Category']) if pd.notna(row.get('Category')) else None,
                message=str(row['Message']) if pd.notna(row.get('Message')) else None,
                status=str(row['Status']) if pd.notna(row.get('Status')) else None,
                flag=str(row['Flag']) if pd.notna(row.get('Flag')) else None,
                scope=str(row['Scope']) if pd.notna(row.get('Scope')) else None,
                sector=float(row['Sector']) if pd.notna(row.get('Sector')) else None,
                racing_number=str(row['RacingNumber']) if pd.notna(row.get('RacingNumber')) else None,
            )
            messages_list.append(message)
    
        return RaceControlMessagesResponse(
            session_name=session_obj.name,
            event_name=event['EventName'],
            messages=messages_list,
            total_messages=len(messages_list)
        )
  • Pydantic models defining the input/output schema for race control messages: RaceControlMessage (individual message) and RaceControlMessagesResponse (list wrapper with metadata).
    class RaceControlMessage(BaseModel):
        """Single race control message."""
    
        time: Optional[str] = Field(None, description="When the message was issued")
        category: Optional[str] = Field(None, description="Message category (e.g., Flag, SafetyCar, CarEvent)")
        message: Optional[str] = Field(None, description="The actual message text")
        status: Optional[str] = Field(None, description="Current session/track status")
        flag: Optional[str] = Field(None, description="Flag status (GREEN, YELLOW, RED, etc.)")
        scope: Optional[str] = Field(None, description="Scope of the message (Track, Sector, Driver)")
        sector: Optional[float] = Field(None, description="Relevant sector (if applicable)")
        racing_number: Optional[str] = Field(None, description="Driver number (if applicable)")
    
    
    class RaceControlMessagesResponse(BaseModel):
        """Race control messages response."""
    
        session_name: str = Field(description="Session name")
        event_name: str = Field(description="Grand Prix name")
        messages: list[RaceControlMessage] = Field(description="Race control messages")
        total_messages: int = Field(description="Total number of messages")
  • server.py:164-164 (registration)
    MCP server tool registration decorator applied to the get_race_control_messages function.
    mcp.tool()(get_race_control_messages)
Behavior2/5

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

With no annotations provided, the description carries full burden but offers minimal behavioral insight. It mentions filtering capabilities and return type but lacks details on permissions, rate limits, error conditions, or data freshness. For a tool with 4 parameters and no annotation coverage, this leaves significant behavioral gaps.

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

Conciseness4/5

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

The description is well-structured with clear sections (purpose, args, returns, examples) and uses minimal sentences that each add value. While slightly longer due to parameter explanations, it avoids redundancy and is appropriately sized for a tool with multiple parameters and filtering options.

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?

The description covers parameter semantics thoroughly and mentions the return type, but with no annotations and a complex tool (4 params, filtering), it lacks behavioral context like error handling or data limitations. The presence of an output schema reduces the need to explain return values, but overall completeness is moderate given the tool's complexity.

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?

Given 0% schema description coverage, the description compensates fully by explaining all 4 parameters in detail: year constraints (2018+), gp format (name or round), session codes with examples, and message_type options with default. The examples further clarify parameter usage, adding substantial value beyond the bare schema.

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

Purpose5/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 with specific verbs ('Get race control messages') and resources ('flags, safety cars, investigations, penalties'), distinguishing it from sibling tools like get_driver_radio or get_session_results that handle different data types. It precisely defines what data is retrieved without being vague or tautological.

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 lists examples, it doesn't explain scenarios where race control messages are needed over other data sources or mention any prerequisites, leaving the agent to infer usage context from parameter descriptions alone.

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/praneethravuri/pitstop'

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