Skip to main content
Glama
GovIndLok

f1-mcp-server

by GovIndLok
README.md
# Formula 1 MCP Server

A Model Context Protocol (MCP) server that empowers AI assistants (such as Claude Desktop, Cursor, or custom agents) to inspect, explore, and query Formula 1 data hosted on AWS.

Built using [FastMCP](https://github.com/jlowin/fastmcp), this server integrates natively with **AWS Glue Data Catalog** (schema metadata) and **Amazon Athena** (serverless SQL execution over S3 Parquet tables).

---

## Relationship to Upstream Data Pipeline

This repository is designed as a **downstream AI consumption layer** built directly on top of the [Formula 1 Enterprise Data Pipeline (`aws-f1-pipeline`)](https://github.com/GovIndLok/aws-f1-pipeline).

### How It Fits into the End-to-End Architecture

```
                            UPSTREAM DATA PIPELINE
                          (GovIndLok/aws-f1-pipeline)
            ┌─────────────────────────────────────────────────────┐
            │          Amazon S3 Data Lake (dbt-athena)           │
            │               Bronze ➔ Silver ➔ Gold                │
            └──────────────────────────┬──────────────────────────┘
                                       │ (Table & Schema Metadata)
                                       ▼
                           ┌───────────────────────┐
                           │ AWS Glue Data Catalog │
                           │    (Gold Database)    │
                           └───────────┬───────────┘
                                       │
═══════════════════════════════════════╪═══════════════════════════════════════
                         DOWNSTREAM AI INTERFACE
                            (This Repository)
                                       │
                                       ▼
                         ┌───────────────────────────┐
                         │       f1-mcp-server       │
                         │  - FastMCP (Python)       │
                         │  - Boto3 (Glue & Athena)  │
                         └─────────────┬─────────────┘
                                       │ (stdio / SSE JSON-RPC)
                                       ▼
                         ┌───────────────────────────┐
                         │        AI Clients         │
                         │ (Claude Desktop / Cursor) │
                         └───────────────────────────┘
```

1. **Upstream Pipeline (`aws-f1-pipeline`)**:
   - Transforms Formula 1 race and telemetry data using `dbt-athena` across Medallion layers (**Bronze** $\rightarrow$ **Silver** $\rightarrow$ **Gold**), materializing optimized Apache Parquet tables in Amazon S3.
   - Registers dimensional models, facts, and analytical marts into the **AWS Glue Data Catalog**.

2. **Downstream Application (`f1-mcp-server`)**:
   - Connects directly to the curated **Gold** schema in AWS Glue.
   - Translates high-level agent intents into validated Athena queries.
   - Exposes structured tools that allow LLMs to explore schemas, sample records, and perform multi-table joins without writing SQL by hand or needing direct AWS console access.

---

## Gold Data Schema

The server queries the `gold` database generated by the upstream pipeline, organized into a Star schema:

| Layer | Tables | Description |
|---|---|---|
| **Dimensions (`dim_*`)** | `dim_drivers`<br>`dim_constructors`<br>`dim_circuits`<br>`dim_races` | Reference data containing driver details, teams, circuits, track coordinates, and race calendars. |
| **Facts (`fct_*`)** | `fct_results`<br>`fct_lap_times`<br>`fct_pit_stops`<br>`fct_qualifyings` | Granular race events, grid positions, finishing results, lap timing, and pit stop durations. |
| **Marts (`mart_*`)** | `mart_drivers_season_stats`<br>`mart_constructors_season_stats` | Pre-aggregated standings and championship points for fast retrieval. |

---

## MCP Tools

The server registers 4 tools under the FastMCP framework:

### 1. `list_tables`
Discovers tables available in the Gold schema, automatically grouped by marts, facts, and dimensions.
- **Argument:** `table_type` (*optional*): Filter by `"marts"`, `"facts"`, or `"dims"`.
- **Returns:** Dictionary listing tables and their descriptions.

### 2. `tables_schema`
Fetches column names and data types for one or more tables from the Glue Data Catalog.
- **Argument:** `table_s`: List of table names, e.g. `["dim_drivers", "fct_results"]`.
- **Returns:** Dictionary mapping table names to their column definitions.

### 3. `get_sample_data`
Previews the top 10 rows of a table with schema-validated column filters.
- **Arguments:**
  - `table_name`: Name of the table to sample.
  - `filters` (*optional*): List of filter rules: `[{"column": "nationality", "operator": "=", "value": "British"}]`. Supported operators include `=`, `!=`, `>`, `<`, `>=`, `<=`, `IN`, `BETWEEN`, `LIKE`.
  - `join_logic` (*optional*): Combine multiple filters using `"AND"` (default) or `"OR"`.
- **Returns:** JSON object containing sample rows.

### 4. `run_a_query`
Executes custom analytical queries joining fact and dimension tables on Athena.
- **Arguments:**
  - `main_table`: Primary table to query (e.g. `"fct_results"`).
  - `columns`: Dictionary mapping tables to requested column names, e.g. `{"fct_results": ["position", "points"], "dim_drivers": ["forename", "surname"]}`.
  - `join` (*optional*): List of joins: `[{"table": "dim_drivers", "join_column": "driver_id", "on_column": "driver_id"}]`.
  - `filters` (*optional*): Filter criteria with automatic type and operator formatting.
  - `filter_logic` (*optional*): `"AND"` (default) or `"OR"`.
  - `limit` (*optional*): Maximum rows to return (default: 20, max: 500).
- **Validation:**
  - Ensures every table referenced in `columns` is either the `main_table` or explicitly joined.
  - Formats strings with single quotes, tuples for `IN`, and numeric bounds for `BETWEEN`.

---

## Environment Configuration

Copy `.env.example` to `.env` and provide your AWS and Athena details:

```bash
cp .env.example .env
```

Configuration reference:

```dotenv
# AWS Configuration
AWS_PROFILE=your-aws-profile
AWS_REGION=your-aws-region

# Athena & Glue Settings
GLUE_DATABASE=gold
S3_RESULTS_BUCKET=s3://<your-athena-query-results-bucket>/staging/query-results/
QUERY_TIMEOUT_SECONDS=15

# MCP Server Settings
MCP_SERVER_HOST=127.0.0.1
MCP_SERVER_PORT=8000
```

---

## Getting Started

### 1. Prerequisites
- Python 3.12+
- [uv](https://github.com/astral-sh/uv) (recommended) or standard `pip`
- Valid AWS credentials with permissions for Athena (`StartQueryExecution`, `GetQueryExecution`, `GetQueryResults`), Glue (`GetTables`, `GetTable`), and S3 (read/write access to query results bucket).

### 2. Installation
```bash
# Clone the repository
git clone https://github.com/GovIndLok/f1_mcp_server.git
cd f1_mcp_server

# Install dependencies using uv
uv sync

# Activate the virtual environment
source .venv/bin/activate
```

### 3. Running the Server

#### Standard Input/Output (`stdio`) — Default for local AI clients:
```bash
source .venv/bin/activate
python -m src.server.mcp_server --transport stdio
```

#### Server-Sent Events (`sse`) — For network or containerized setups:
```bash
source .venv/bin/activate
python -m src.server.mcp_server --transport sse --port 8080
```

---

## Client Integration

### Claude Desktop
Add the server definition to your `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "f1-mcp-server": {
      "command": "/path/to/f1_mcp_server/.venv/bin/python",
      "args": ["-m", "src.server.mcp_server", "--transport", "stdio"],
      "cwd": "/path/to/f1_mcp_server",
      "env": {
        "AWS_PROFILE": "your-aws-profile",
        "AWS_REGION": "your-aws-region",
        "GLUE_DATABASE": "gold",
        "S3_RESULTS_BUCKET": "s3://<your-athena-query-results-bucket>/staging/query-results/"
      }
    }
  }
}
```

### Cursor
In Cursor Settings $\rightarrow$ Features $\rightarrow$ MCP Servers, add:
- **Name:** `f1-data`
- **Type:** `command`
- **Command:** `python -m src.server.mcp_server --transport stdio`

---

## Deployment

For containerized or remote deployments, run the server using the SSE transport (`--transport sse --port 8080`). It can be deployed as an AWS ECS Fargate container behind an Application Load Balancer (ALB) or API reverse proxy, with an IAM Task Role configured for least-privilege access to Athena, Glue, and S3.

TDQS

B3.3/5.0

Scored across 4 tools

Disambiguation3/5

list_tables and tables_schema are clearly distinct, but get_sample_data and run_a_query overlap significantly—both can query a single table with filters, and run_a_query can reproduce sample-style queries with limit. The descriptions hint at different use cases (quick sample vs. custom joins), but the boundary is not sharply defined.

Naming Consistency3/5

Names are snake_case and somewhat readable, but styles are mixed: list_tables and get_sample_data use a verb+noun pattern, run_a_query adds an article, and tables_schema uses a noun phrase with no verb. Overall it is still predictable enough to navigate, but not a clean consistent convention.

Tool Count4/5

Four tools is small but appropriate for a read-only F1 data exploration server. Each tool covers a meaningful step: discover tables, inspect schemas, sample data, and run custom queries. It does not feel padded or trivially thin.

Completeness4/5

The set covers the core read-only workflow well: list available tables, understand their schema, preview data, and execute arbitrary queries. Minor gaps include no pagination/offset support and no explicit relationship metadata, but agents can work around these via run_a_query and tables_schema.

Maintenance

ActivityMaintained
ResponsivenessNo issues