arre99 commited on
Commit
d69ce5a
·
1 Parent(s): 7206ec7

deleted unused files and folders. cleaned up front-end UI a bit. Tidied up the notebooks for both APIs. Added mcp.json config info in the README

Browse files
README.md CHANGED
@@ -19,4 +19,35 @@ The MCP server is defined inside `app.py` and is hosted on HuggingFace spaces us
19
 
20
  ## MCP Client
21
 
22
- The MCP client is defined inside `mcp_client.py` and allows interaction with the MCP server through server side events (SSE) transport.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
  ## MCP Client
21
 
22
+ The MCP client is defined inside `mcp_client.py` and allows interaction with the MCP server through server side events (SSE) transport.
23
+
24
+ For MCP clients that support SSE transport (Not Claude Desktop, see below for info), the following configuration can be used:
25
+
26
+ ```json
27
+ {
28
+ "mcpServers": {
29
+ "gradio": {
30
+ "url": "https://agents-mcp-hackathon-f1-mcp-server.hf.space/gradio_api/mcp/sse"
31
+ }
32
+ }
33
+ }
34
+ ```
35
+
36
+ For Claude Desktop, the following configuration can instead be used, but make sure you have Node.js installed:
37
+
38
+ ```json
39
+ {
40
+ "mcpServers": {
41
+ "gradio": {
42
+ "command": "npx",
43
+ "args": [
44
+ "mcp-remote",
45
+ "https://agents-mcp-hackathon-f1-mcp-server.hf.space/gradio_api/mcp/sse",
46
+ "--transport",
47
+ "sse-only"
48
+ ]
49
+ }
50
+ }
51
+ }
52
+ ```
53
+
api_playground.ipynb CHANGED
@@ -136,357 +136,6 @@
136
  "circuit_info = session.get_circuit_info()\n",
137
  "pprint(circuit_info)"
138
  ]
139
- },
140
- {
141
- "cell_type": "markdown",
142
- "id": "a5047955",
143
- "metadata": {},
144
- "source": [
145
- "# OpenF1"
146
- ]
147
- },
148
- {
149
- "cell_type": "code",
150
- "execution_count": 3,
151
- "id": "b5d31092",
152
- "metadata": {},
153
- "outputs": [],
154
- "source": [
155
- "def make_request(api_action_string: str, debug: bool = False):\n",
156
- " try: \n",
157
- " response = urlopen(f\"https://api.openf1.org/v1/{api_action_string}\")\n",
158
- " data = json.loads(response.read().decode('utf-8'))\n",
159
- " if debug: pprint(data)\n",
160
- " return data\n",
161
- " except Exception as e:\n",
162
- " print(f\"Error: {e}\")"
163
- ]
164
- },
165
- {
166
- "cell_type": "code",
167
- "execution_count": 5,
168
- "id": "599aeec3",
169
- "metadata": {},
170
- "outputs": [
171
- {
172
- "name": "stdout",
173
- "output_type": "stream",
174
- "text": [
175
- "[{'brake': 0,\n",
176
- " 'date': '2023-09-15T13:08:19.923000+00:00',\n",
177
- " 'driver_number': 55,\n",
178
- " 'drs': 12,\n",
179
- " 'meeting_key': 1219,\n",
180
- " 'n_gear': 8,\n",
181
- " 'rpm': 11141,\n",
182
- " 'session_key': 9159,\n",
183
- " 'speed': 315,\n",
184
- " 'throttle': 99},\n",
185
- " {'brake': 100,\n",
186
- " 'date': '2023-09-15T13:35:41.808000+00:00',\n",
187
- " 'driver_number': 55,\n",
188
- " 'drs': 8,\n",
189
- " 'meeting_key': 1219,\n",
190
- " 'n_gear': 8,\n",
191
- " 'rpm': 11023,\n",
192
- " 'session_key': 9159,\n",
193
- " 'speed': 315,\n",
194
- " 'throttle': 57}]\n"
195
- ]
196
- }
197
- ],
198
- "source": [
199
- "# Respone object for OpenF1\n",
200
- "\n",
201
- "response = urlopen('https://api.openf1.org/v1/car_data?driver_number=55&session_key=9159&speed>=315')\n",
202
- "data = json.loads(response.read().decode('utf-8'))\n",
203
- "pprint(data)"
204
- ]
205
- },
206
- {
207
- "cell_type": "code",
208
- "execution_count": 19,
209
- "id": "2b06a5c0",
210
- "metadata": {},
211
- "outputs": [
212
- {
213
- "data": {
214
- "text/html": [
215
- "<div>\n",
216
- "<style scoped>\n",
217
- " .dataframe tbody tr th:only-of-type {\n",
218
- " vertical-align: middle;\n",
219
- " }\n",
220
- "\n",
221
- " .dataframe tbody tr th {\n",
222
- " vertical-align: top;\n",
223
- " }\n",
224
- "\n",
225
- " .dataframe thead th {\n",
226
- " text-align: right;\n",
227
- " }\n",
228
- "</style>\n",
229
- "<table border=\"1\" class=\"dataframe\">\n",
230
- " <thead>\n",
231
- " <tr style=\"text-align: right;\">\n",
232
- " <th></th>\n",
233
- " <th>meeting_key</th>\n",
234
- " <th>session_key</th>\n",
235
- " <th>location</th>\n",
236
- " <th>date_start</th>\n",
237
- " <th>date_end</th>\n",
238
- " <th>session_type</th>\n",
239
- " <th>session_name</th>\n",
240
- " <th>country_key</th>\n",
241
- " <th>country_code</th>\n",
242
- " <th>country_name</th>\n",
243
- " <th>circuit_key</th>\n",
244
- " <th>circuit_short_name</th>\n",
245
- " <th>gmt_offset</th>\n",
246
- " <th>year</th>\n",
247
- " </tr>\n",
248
- " </thead>\n",
249
- " <tbody>\n",
250
- " <tr>\n",
251
- " <th>0</th>\n",
252
- " <td>1262</td>\n",
253
- " <td>9964</td>\n",
254
- " <td>Barcelona</td>\n",
255
- " <td>2025-05-30T11:30:00+00:00</td>\n",
256
- " <td>2025-05-30T12:30:00+00:00</td>\n",
257
- " <td>Practice</td>\n",
258
- " <td>Practice 1</td>\n",
259
- " <td>1</td>\n",
260
- " <td>ESP</td>\n",
261
- " <td>Spain</td>\n",
262
- " <td>15</td>\n",
263
- " <td>Catalunya</td>\n",
264
- " <td>02:00:00</td>\n",
265
- " <td>2025</td>\n",
266
- " </tr>\n",
267
- " <tr>\n",
268
- " <th>1</th>\n",
269
- " <td>1262</td>\n",
270
- " <td>9965</td>\n",
271
- " <td>Barcelona</td>\n",
272
- " <td>2025-05-30T15:00:00+00:00</td>\n",
273
- " <td>2025-05-30T16:00:00+00:00</td>\n",
274
- " <td>Practice</td>\n",
275
- " <td>Practice 2</td>\n",
276
- " <td>1</td>\n",
277
- " <td>ESP</td>\n",
278
- " <td>Spain</td>\n",
279
- " <td>15</td>\n",
280
- " <td>Catalunya</td>\n",
281
- " <td>02:00:00</td>\n",
282
- " <td>2025</td>\n",
283
- " </tr>\n",
284
- " </tbody>\n",
285
- "</table>\n",
286
- "</div>"
287
- ],
288
- "text/plain": [
289
- " meeting_key session_key location date_start \\\n",
290
- "0 1262 9964 Barcelona 2025-05-30T11:30:00+00:00 \n",
291
- "1 1262 9965 Barcelona 2025-05-30T15:00:00+00:00 \n",
292
- "\n",
293
- " date_end session_type session_name country_key \\\n",
294
- "0 2025-05-30T12:30:00+00:00 Practice Practice 1 1 \n",
295
- "1 2025-05-30T16:00:00+00:00 Practice Practice 2 1 \n",
296
- "\n",
297
- " country_code country_name circuit_key circuit_short_name gmt_offset year \n",
298
- "0 ESP Spain 15 Catalunya 02:00:00 2025 \n",
299
- "1 ESP Spain 15 Catalunya 02:00:00 2025 "
300
- ]
301
- },
302
- "execution_count": 19,
303
- "metadata": {},
304
- "output_type": "execute_result"
305
- }
306
- ],
307
- "source": [
308
- "# Get session\n",
309
- "respone = make_request(\"sessions?country_name=Spain&year=2025\", debug=False)\n",
310
- "df = pd.DataFrame(respone)\n",
311
- "df.head(n=2)\n"
312
- ]
313
- },
314
- {
315
- "cell_type": "code",
316
- "execution_count": 18,
317
- "id": "f13e4f1a",
318
- "metadata": {},
319
- "outputs": [
320
- {
321
- "data": {
322
- "text/html": [
323
- "<div>\n",
324
- "<style scoped>\n",
325
- " .dataframe tbody tr th:only-of-type {\n",
326
- " vertical-align: middle;\n",
327
- " }\n",
328
- "\n",
329
- " .dataframe tbody tr th {\n",
330
- " vertical-align: top;\n",
331
- " }\n",
332
- "\n",
333
- " .dataframe thead th {\n",
334
- " text-align: right;\n",
335
- " }\n",
336
- "</style>\n",
337
- "<table border=\"1\" class=\"dataframe\">\n",
338
- " <thead>\n",
339
- " <tr style=\"text-align: right;\">\n",
340
- " <th></th>\n",
341
- " <th>meeting_key</th>\n",
342
- " <th>session_key</th>\n",
343
- " <th>location</th>\n",
344
- " <th>date_start</th>\n",
345
- " <th>date_end</th>\n",
346
- " <th>session_type</th>\n",
347
- " <th>session_name</th>\n",
348
- " <th>country_key</th>\n",
349
- " <th>country_code</th>\n",
350
- " <th>country_name</th>\n",
351
- " <th>circuit_key</th>\n",
352
- " <th>circuit_short_name</th>\n",
353
- " <th>gmt_offset</th>\n",
354
- " <th>year</th>\n",
355
- " </tr>\n",
356
- " </thead>\n",
357
- " <tbody>\n",
358
- " <tr>\n",
359
- " <th>0</th>\n",
360
- " <td>1262</td>\n",
361
- " <td>9966</td>\n",
362
- " <td>Barcelona</td>\n",
363
- " <td>2025-05-31T10:30:00+00:00</td>\n",
364
- " <td>2025-05-31T11:30:00+00:00</td>\n",
365
- " <td>Practice</td>\n",
366
- " <td>Practice 3</td>\n",
367
- " <td>1</td>\n",
368
- " <td>ESP</td>\n",
369
- " <td>Spain</td>\n",
370
- " <td>15</td>\n",
371
- " <td>Catalunya</td>\n",
372
- " <td>02:00:00</td>\n",
373
- " <td>2025</td>\n",
374
- " </tr>\n",
375
- " </tbody>\n",
376
- "</table>\n",
377
- "</div>"
378
- ],
379
- "text/plain": [
380
- " meeting_key session_key location date_start \\\n",
381
- "0 1262 9966 Barcelona 2025-05-31T10:30:00+00:00 \n",
382
- "\n",
383
- " date_end session_type session_name country_key \\\n",
384
- "0 2025-05-31T11:30:00+00:00 Practice Practice 3 1 \n",
385
- "\n",
386
- " country_code country_name circuit_key circuit_short_name gmt_offset year \n",
387
- "0 ESP Spain 15 Catalunya 02:00:00 2025 "
388
- ]
389
- },
390
- "execution_count": 18,
391
- "metadata": {},
392
- "output_type": "execute_result"
393
- }
394
- ],
395
- "source": [
396
- "# Current session id (called during FP3 in Spain)\n",
397
- "respone = make_request(\"sessions?session_key=latest\")\n",
398
- "df = pd.DataFrame(respone)\n",
399
- "df.head()"
400
- ]
401
- },
402
- {
403
- "cell_type": "code",
404
- "execution_count": null,
405
- "id": "80a5699e",
406
- "metadata": {},
407
- "outputs": [
408
- {
409
- "data": {
410
- "text/html": [
411
- "<div>\n",
412
- "<style scoped>\n",
413
- " .dataframe tbody tr th:only-of-type {\n",
414
- " vertical-align: middle;\n",
415
- " }\n",
416
- "\n",
417
- " .dataframe tbody tr th {\n",
418
- " vertical-align: top;\n",
419
- " }\n",
420
- "\n",
421
- " .dataframe thead th {\n",
422
- " text-align: right;\n",
423
- " }\n",
424
- "</style>\n",
425
- "<table border=\"1\" class=\"dataframe\">\n",
426
- " <thead>\n",
427
- " <tr style=\"text-align: right;\">\n",
428
- " <th></th>\n",
429
- " <th>meeting_key</th>\n",
430
- " <th>session_key</th>\n",
431
- " <th>location</th>\n",
432
- " <th>date_start</th>\n",
433
- " <th>date_end</th>\n",
434
- " <th>session_type</th>\n",
435
- " <th>session_name</th>\n",
436
- " <th>country_key</th>\n",
437
- " <th>country_code</th>\n",
438
- " <th>country_name</th>\n",
439
- " <th>circuit_key</th>\n",
440
- " <th>circuit_short_name</th>\n",
441
- " <th>gmt_offset</th>\n",
442
- " <th>year</th>\n",
443
- " </tr>\n",
444
- " </thead>\n",
445
- " <tbody>\n",
446
- " <tr>\n",
447
- " <th>0</th>\n",
448
- " <td>1262</td>\n",
449
- " <td>9966</td>\n",
450
- " <td>Barcelona</td>\n",
451
- " <td>2025-05-31T10:30:00+00:00</td>\n",
452
- " <td>2025-05-31T11:30:00+00:00</td>\n",
453
- " <td>Practice</td>\n",
454
- " <td>Practice 3</td>\n",
455
- " <td>1</td>\n",
456
- " <td>ESP</td>\n",
457
- " <td>Spain</td>\n",
458
- " <td>15</td>\n",
459
- " <td>Catalunya</td>\n",
460
- " <td>02:00:00</td>\n",
461
- " <td>2025</td>\n",
462
- " </tr>\n",
463
- " </tbody>\n",
464
- "</table>\n",
465
- "</div>"
466
- ],
467
- "text/plain": [
468
- " meeting_key session_key location date_start \\\n",
469
- "0 1262 9966 Barcelona 2025-05-31T10:30:00+00:00 \n",
470
- "\n",
471
- " date_end session_type session_name country_key \\\n",
472
- "0 2025-05-31T11:30:00+00:00 Practice Practice 3 1 \n",
473
- "\n",
474
- " country_code country_name circuit_key circuit_short_name gmt_offset year \n",
475
- "0 ESP Spain 15 Catalunya 02:00:00 2025 "
476
- ]
477
- },
478
- "execution_count": 5,
479
- "metadata": {},
480
- "output_type": "execute_result"
481
- }
482
- ],
483
- "source": [
484
- "# Current session id V2 (called between FP3 and Quali in Spain)\n",
485
- "respone = make_request(\"sessions?session_key=latest\")\n",
486
- "df = pd.DataFrame(respone)\n",
487
- "df.head()\n",
488
- "# session_key=latest points to the current or the most recent session NOT the upcoming one"
489
- ]
490
  }
491
  ],
492
  "metadata": {
 
136
  "circuit_info = session.get_circuit_info()\n",
137
  "pprint(circuit_info)"
138
  ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
  }
140
  ],
141
  "metadata": {
app.py CHANGED
@@ -118,6 +118,10 @@ with gr.Blocks() as markdown_tab:
118
  Use the tabs above to navigate between different sections and explore the wealth of F1 data available at your fingertips.
119
  """)
120
 
 
 
 
 
121
  named_interfaces = {
122
  "About": markdown_tab,
123
  "Driver Championship Standings": iface_driver_championship_standings,
 
118
  Use the tabs above to navigate between different sections and explore the wealth of F1 data available at your fingertips.
119
  """)
120
 
121
+
122
+
123
+
124
+
125
  named_interfaces = {
126
  "About": markdown_tab,
127
  "Driver Championship Standings": iface_driver_championship_standings,
mcp_client.py CHANGED
@@ -52,7 +52,7 @@ if __name__ == "__main__":
52
  tools = mcp_client.get_tools()
53
 
54
  print("### MCP tools ### ")
55
- print("\n".join(f"{i}: {t.name}: {t.description}" for i,t in enumerate(tools)))
56
 
57
  if only_list_tools:
58
  mcp_client.disconnect()
@@ -68,9 +68,9 @@ if __name__ == "__main__":
68
  )
69
  else:
70
  model = InferenceClientModel(
71
- model_id="Qwen/Qwen2.5-32B-Instruct",
72
- provider="",
73
- token=os.getenv("HF_TOKEN")
74
  )
75
 
76
  agent = ToolCallingAgent(tools=[*tools], model=model)
 
52
  tools = mcp_client.get_tools()
53
 
54
  print("### MCP tools ### ")
55
+ print("\n".join(f"Tool {1+i}: {t.name}: {t.description}" for i,t in enumerate(tools)))
56
 
57
  if only_list_tools:
58
  mcp_client.disconnect()
 
68
  )
69
  else:
70
  model = InferenceClientModel(
71
+ model_id="deepseek-ai/DeepSeek-R1",
72
+ provider="nebius",
73
+ api_key=os.getenv("NEBIUS_API_KEY")
74
  )
75
 
76
  agent = ToolCallingAgent(tools=[*tools], model=model)
openf1_tools.py CHANGED
@@ -161,9 +161,5 @@ if __name__ == "__main__":
161
  data = get_api_endpoint("sessions")
162
  pprint(data)
163
 
164
-
165
  pprint(get_endpoint_info("sessions"))
166
 
167
-
168
- # response = send_request(data["api_string"])
169
- # pprint(response)
 
161
  data = get_api_endpoint("sessions")
162
  pprint(data)
163
 
 
164
  pprint(get_endpoint_info("sessions"))
165
 
 
 
 
tests/test_resource_mappings.py DELETED
@@ -1,16 +0,0 @@
1
- """ Tests for resource mappings """
2
-
3
- import os
4
- import json
5
-
6
-
7
- # Load in driver names and numbers
8
- resource_dir = os.path.join(os.path.dirname(__file__), "..", "assets")
9
- driver_names = json.load(open(os.path.join(resource_dir, "driver_names.json")))
10
- driver_numbers = json.load(open(os.path.join(resource_dir, "driver_numbers.json")))
11
-
12
- for name in driver_names["drivers"]:
13
- number = driver_numbers.get(name, None)
14
- if number is None:
15
- raise ValueError(f"Driver {name} does not have a driver number")
16
- print("All driver names and numbers are mapped")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
utils/time_utils.py DELETED
@@ -1,13 +0,0 @@
1
- import datetime
2
-
3
-
4
-
5
- def get_current_time():
6
- """
7
- Returns the current time in the format: HH:MM:SS
8
- """
9
- # NOTE: I can perhaps modify what "now" is to instead be at a past F1
10
- # race when testing real-time tools
11
- return datetime.datetime.now().strftime("%H:%M:%S")
12
-
13
-