|
import gradio as gr |
|
|
|
|
|
import fastf1_tools |
|
import openf1_tools |
|
from utils.constants import ( |
|
DRIVER_NAMES, |
|
CONSTRUCTOR_NAMES, |
|
CURRENT_YEAR, |
|
DROPDOWN_SESSION_TYPES, |
|
MARKDOWN_INTRODUCTION, |
|
MARKDOWN_OPENF1_EXAMPLES, |
|
OPENF1_TOOL_DESCRIPTION |
|
) |
|
|
|
iface_driver_championship_standings = gr.Interface( |
|
fn=fastf1_tools.driver_championship_standings, |
|
inputs=[ |
|
gr.Number(label="Calendar year", value=CURRENT_YEAR, minimum=1950, maximum=CURRENT_YEAR), |
|
gr.Dropdown(label="Driver", choices=DRIVER_NAMES) |
|
], |
|
outputs="text", |
|
title="World Driver Championship Standings", |
|
description="Get the world driver championship standings for a specific driver" |
|
) |
|
|
|
iface_constructor_championship_standings = gr.Interface( |
|
fn=fastf1_tools.constructor_championship_standings, |
|
inputs=[ |
|
gr.Number(label="Calendar year", value=CURRENT_YEAR, minimum=1950, maximum=CURRENT_YEAR), |
|
gr.Dropdown(label="Constructor", choices=CONSTRUCTOR_NAMES) |
|
], |
|
outputs="text", |
|
title="World Constructor Championship Standings", |
|
description="Get the world constructor championship standings for a specific constructor" |
|
) |
|
|
|
iface_event_info = gr.Interface( |
|
fn=fastf1_tools.get_event_info, |
|
inputs=[ |
|
gr.Number(label="Calendar year", value=CURRENT_YEAR, minimum=1950, maximum=CURRENT_YEAR), |
|
gr.Textbox(label="Grand Prix", placeholder="Ex: Monaco", info="The name of the GP/country/location (Fuzzy matching supported) or round number"), |
|
gr.Radio(["human", "LLM"], label="Display format", value="human") |
|
], |
|
outputs="text", |
|
title="Event Info", |
|
description="Get information about a specific Grand Prix event. Example: (2025,Monaco,human)" |
|
) |
|
|
|
iface_season_calendar = gr.Interface( |
|
fn=fastf1_tools.get_season_calendar, |
|
inputs=[ |
|
gr.Number(label="Calendar year", value=CURRENT_YEAR, minimum=1950, maximum=CURRENT_YEAR), |
|
], |
|
outputs="text", |
|
title="Season Calendar", |
|
description="Get the season calendar for the given year" |
|
) |
|
|
|
iface_track_visualization = gr.Interface( |
|
fn=fastf1_tools.track_visualization, |
|
inputs=[ |
|
gr.Number(label="Calendar year", value=CURRENT_YEAR, minimum=1950, maximum=CURRENT_YEAR), |
|
gr.Textbox(label="Grand Prix", placeholder="Ex: Monaco", info="The name of the GP/country/location (Fuzzy matching supported) or round number"), |
|
gr.Radio(["speed", "corners", "gear"], label="Visualization type", value="speed", info="What type of track visualization to generate"), |
|
gr.Dropdown(label="Driver", choices=DRIVER_NAMES, info="Only applied for speed visualization. gear uses fastest lap during race.") |
|
], |
|
outputs="image", |
|
title="Track Visualizations", |
|
description="Get the track visualization for the given Grand Prix. Example: (2025,Monaco,speed,Leclerc)" |
|
) |
|
|
|
iface_session_results = gr.Interface( |
|
fn=fastf1_tools.get_session_results, |
|
inputs=[ |
|
gr.Number(label="Calendar year", value=CURRENT_YEAR, minimum=1950, maximum=CURRENT_YEAR), |
|
gr.Textbox(label="Grand Prix", placeholder="Ex: Monaco", info="The name of the GP/country/location (Fuzzy matching supported) or round number"), |
|
gr.Dropdown([session_type for session_type in DROPDOWN_SESSION_TYPES if "practice" not in session_type], label="Session type", value="race", info="The session type to get results for. Dataframe's columns vary depending on session type.") |
|
], |
|
outputs=gr.Dataframe( |
|
headers=None, |
|
row_count=(0, "dynamic"), |
|
col_count=(0, "dynamic") |
|
), |
|
title="Session Results", |
|
description="Get the session results for the given Grand Prix. Example: (2025,Monaco,qualifying)" |
|
) |
|
|
|
iface_driver_info = gr.Interface( |
|
fn=fastf1_tools.get_driver_info, |
|
inputs=[ |
|
gr.Dropdown(label="Driver", choices=DRIVER_NAMES) |
|
], |
|
outputs="text", |
|
title="Driver Info", |
|
description="Get background information about a specific driver" |
|
) |
|
|
|
iface_constructor_info = gr.Interface( |
|
fn=fastf1_tools.get_constructor_info, |
|
inputs=[ |
|
gr.Dropdown(label="Constructor", choices=CONSTRUCTOR_NAMES) |
|
], |
|
outputs="text", |
|
title="Constructor Info", |
|
description="Get background information about a specific constructor" |
|
) |
|
|
|
|
|
|
|
with gr.Blocks() as markdown_tab: |
|
gr.Markdown(MARKDOWN_INTRODUCTION) |
|
|
|
|
|
|
|
|
|
def openf1_tools_tab(): |
|
with gr.Blocks() as openf1_tools_tab: |
|
gr.Markdown(OPENF1_TOOL_DESCRIPTION) |
|
with gr.Accordion("get_api_endpoints()", open=False): |
|
btn = gr.Button("Get all endpoints") |
|
output = gr.JSON() |
|
def _get_api_endpoints(): |
|
return openf1_tools.get_api_endpoints() |
|
btn.click(_get_api_endpoints, outputs=output) |
|
with gr.Accordion("get_api_endpoint(endpoint)", open=False): |
|
endpoint_in = gr.Textbox(label="Endpoint", placeholder="e.g. sessions") |
|
btn = gr.Button("Get endpoint info") |
|
output = gr.JSON() |
|
def _get_api_endpoint(endpoint): |
|
return openf1_tools.get_api_endpoint(endpoint) |
|
btn.click(_get_api_endpoint, inputs=endpoint_in, outputs=output) |
|
with gr.Accordion("get_endpoint_info(endpoint)", open=False): |
|
endpoint_in = gr.Textbox(label="Endpoint", placeholder="e.g. sessions") |
|
btn = gr.Button("Get endpoint details") |
|
output = gr.JSON() |
|
def _get_endpoint_info(endpoint): |
|
return openf1_tools.get_endpoint_info(endpoint) |
|
btn.click(_get_endpoint_info, inputs=endpoint_in, outputs=output) |
|
with gr.Accordion("get_filter_info(filter_name)", open=False): |
|
filter_in = gr.Textbox(label="Filter name", placeholder="e.g. driver_number") |
|
btn = gr.Button("Get filter info") |
|
output = gr.JSON() |
|
def _get_filter_info(filter_name): |
|
return openf1_tools.get_filter_info(filter_name) |
|
btn.click(_get_filter_info, inputs=filter_in, outputs=output) |
|
with gr.Accordion("get_filter_string(filter_name, filter_value, operator)", open=False): |
|
filter_name = gr.Textbox(label="Filter name", placeholder="e.g. driver_number") |
|
filter_value = gr.Textbox(label="Filter value", placeholder="e.g. 16") |
|
operator = gr.Dropdown(label="Operator", choices=["=", ">", "<", ">=", "<="], value="=") |
|
btn = gr.Button("Get filter string") |
|
output = gr.Textbox(label="Filter string", info="Example: driver_number=16&") |
|
def _get_filter_string(filter_name, filter_value, operator): |
|
return openf1_tools.get_filter_string(filter_name, filter_value, operator) |
|
btn.click(_get_filter_string, inputs=[filter_name, filter_value, operator], outputs=output) |
|
with gr.Accordion("apply_filters(api_string, *filters)", open=False): |
|
api_string = gr.Textbox(label="Base API string", placeholder="e.g. https://api.openf1.org/v1/sessions?") |
|
filters = gr.Textbox(label="Filters (comma-separated)", placeholder="e.g. driver_number=16&,session_key=123&") |
|
btn = gr.Button("Apply filters") |
|
output = gr.Textbox(label="Full API string") |
|
def _apply_filters(api_string, filters): |
|
|
|
filter_list = [f.strip() for f in filters.split(",") if f.strip()] |
|
return openf1_tools.apply_filters(api_string, *filter_list) |
|
btn.click(_apply_filters, inputs=[api_string, filters], outputs=output) |
|
with gr.Accordion("send_request(api_string)", open=False): |
|
with gr.Accordion("Example API requests (copy & paste into text box below)", open=False): |
|
gr.Markdown(MARKDOWN_OPENF1_EXAMPLES) |
|
api_string = gr.Textbox(label="Full API string", placeholder="e.g. https://api.openf1.org/v1/sessions?driver_number=16") |
|
btn = gr.Button("Send API request") |
|
output = gr.JSON() |
|
def _send_request(api_string): |
|
try: |
|
return openf1_tools.send_request(api_string) |
|
except Exception as e: |
|
return {"error": str(e)} |
|
btn.click(_send_request, inputs=api_string, outputs=output) |
|
return openf1_tools_tab |
|
|
|
|
|
|
|
named_interfaces = { |
|
"About": markdown_tab, |
|
"Driver Championship Standings": iface_driver_championship_standings, |
|
"Constructor Championship Standings": iface_constructor_championship_standings, |
|
"Event Info": iface_event_info, |
|
"Season Calendar": iface_season_calendar, |
|
"Track Visualizations": iface_track_visualization, |
|
"Session Results": iface_session_results, |
|
"Driver Info": iface_driver_info, |
|
"Constructor Info": iface_constructor_info, |
|
"OpenF1 Tools": openf1_tools_tab(), |
|
} |
|
|
|
|
|
tab_names = list(named_interfaces.keys()) |
|
interface_list = list(named_interfaces.values()) |
|
|
|
|
|
|
|
gradio_server = gr.TabbedInterface( |
|
interface_list, |
|
tab_names=tab_names, |
|
title="๐ Formula 1 MCP server ๐๏ธ" |
|
) |
|
|
|
|
|
if __name__ == "__main__": |
|
gradio_server.launch(mcp_server=True) |