Elbby Skermine commited on
Commit
ce8bb53
·
1 Parent(s): 8bc5d60

redeploy with minor changes and code cleaning

Browse files
Files changed (2) hide show
  1. main.py +1 -1
  2. tools.py +47 -244
main.py CHANGED
@@ -60,7 +60,7 @@ def get_firestore_client():
60
  _db = firestore.client()
61
  return _db
62
 
63
- mcp = FastMCP("Echo Server", port=7860, stateless_http=True, debug=True, host="0.0.0.0")
64
 
65
  # Import tools registration
66
  from tools import register_tools
 
60
  _db = firestore.client()
61
  return _db
62
 
63
+ mcp = FastMCP("Kahoot Game Alternative", port=7860, stateless_http=True, debug=True, host="0.0.0.0")
64
 
65
  # Import tools registration
66
  from tools import register_tools
tools.py CHANGED
@@ -14,14 +14,14 @@ def register_tools(mcp: FastMCP, db_getter):
14
  """Register all MCP tools with lazy database loading"""
15
 
16
  @mcp.tool(
17
- title="Add User to Session",
18
- description="Add a user to a session with their pseudo and score in the database",
19
  )
20
- async def add_user(
21
- session_id: str = Field(description="The ID of the session to add the user to"),
22
- user_pseudo: str = Field(description="The pseudo/username of the user to add")
23
  ) -> str:
24
- """Add a user to a session in the database"""
25
  try:
26
  # Get database client lazily
27
  db = db_getter()
@@ -34,39 +34,39 @@ def register_tools(mcp: FastMCP, db_getter):
34
 
35
  # Initialize session_data with default values
36
  session_data = {
37
- 'users': []
38
  }
39
 
40
  if session_doc.exists:
41
  session_data = session_doc.to_dict()
42
 
43
- # Add the new user to the users list
44
- new_user = {
45
- 'pseudo': user_pseudo,
46
  'score': 0 # Initialize score to 0
47
  }
48
 
49
- # Check if user already exists in this session
50
- users = session_data.get('users', [])
51
- existing_user = next((user for user in users if user.get('pseudo') == user_pseudo), None)
52
 
53
- if existing_user:
54
  result = {
55
- "user_pseudo": user_pseudo,
56
  "session_id": session_id,
57
- "score": existing_user.get('score', 0),
58
- "message": f"User '{user_pseudo}' already exists in session '{session_id}'",
59
  "already_exists": True
60
  }
61
  return json.dumps(result, indent=2)
62
 
63
- # Generate user_id for the new user
64
- user_id = str(uuid.uuid4())[:8]
65
- new_user['user_id'] = user_id
66
 
67
- # Add the new user
68
- users.append(new_user)
69
- session_data['users'] = users
70
 
71
  # Update the session document
72
  if not session_doc.exists:
@@ -79,18 +79,18 @@ def register_tools(mcp: FastMCP, db_getter):
79
  session_ref.set(session_data, merge=True)
80
 
81
  result = {
82
- "user_id": user_id,
83
- "user_pseudo": user_pseudo,
84
  "session_id": session_id,
85
  "score": 0,
86
- "message": f"Successfully added user '{user_pseudo}' to session '{session_id}'",
87
  "already_exists": False
88
  }
89
 
90
  return json.dumps(result, indent=2)
91
 
92
  except Exception as e:
93
- return f"Error adding user to session: {str(e)}"
94
 
95
  @mcp.tool(
96
  title="Get Next Question",
@@ -147,115 +147,13 @@ def register_tools(mcp: FastMCP, db_getter):
147
  except Exception as e:
148
  return f"Error getting next question: {str(e)}"
149
 
150
-
151
- @mcp.tool(
152
- title="Validate Answer",
153
- description="Check if a submitted answer is correct without updating scores",
154
- )
155
- async def validate_answer(
156
- session_id: str = Field(description="The ID of the quiz session"),
157
- question_id: int = Field(description="The ID of the question being answered"),
158
- answer_index: int = Field(description="The selected answer index (0-3)")
159
- ) -> str:
160
- """Validate if the submitted answer is correct"""
161
- try:
162
- # Get database client lazily
163
- db = db_getter()
164
- session_ref = db.collection('quiz_sessions').document(session_id)
165
- session_doc = session_ref.get()
166
-
167
- if not session_doc.exists:
168
- return f"Session '{session_id}' not found"
169
-
170
- session_data = session_doc.to_dict()
171
- questions = session_data.get('questions', [])
172
- current_question_index = session_data.get('current_question', 0)
173
-
174
- # Check if question exists
175
- if current_question_index >= len(questions):
176
- return "Quiz finished - no active question to validate"
177
-
178
- current_question = questions[current_question_index]
179
-
180
- # Validate question_id matches current question
181
- if current_question.get('id') != question_id:
182
- return f"Question ID mismatch. Expected {current_question.get('id')}, got {question_id}"
183
-
184
- correct_answer = current_question.get('correct')
185
- is_correct = answer_index == correct_answer
186
-
187
- result = {
188
- "correct": is_correct,
189
- "correct_answer_index": correct_answer,
190
- "submitted_answer_index": answer_index,
191
- "question_id": question_id
192
- }
193
-
194
- return json.dumps(result, indent=2)
195
-
196
- except Exception as e:
197
- return f"Error validating answer: {str(e)}"
198
-
199
- @mcp.tool(
200
- title="Update User Score",
201
- description="Update a user's score in the database",
202
- )
203
- async def update_score(
204
- session_id: str = Field(description="The ID of the quiz session"),
205
- user_pseudo: str = Field(description="The pseudo/username of the user"),
206
- correct: bool = Field(description="Whether the answer was correct")
207
- ) -> str:
208
- """Update user score in the database"""
209
- try:
210
- # Get database client lazily
211
- db = db_getter()
212
- session_ref = db.collection('quiz_sessions').document(session_id)
213
- session_doc = session_ref.get()
214
-
215
- if not session_doc.exists:
216
- return f"Session '{session_id}' not found"
217
-
218
- session_data = session_doc.to_dict()
219
- users = session_data.get('users', [])
220
-
221
- # Find user and update score
222
- user_found = False
223
- for user in users:
224
- if user.get('pseudo') == user_pseudo:
225
- if correct:
226
- user['score'] = user.get('score', 0) + 1
227
- user_found = True
228
- break
229
-
230
- if not user_found:
231
- return f"User '{user_pseudo}' not found in session '{session_id}'"
232
-
233
- # Update session document
234
- session_data['users'] = users
235
- session_ref.set(session_data, merge=True)
236
-
237
- # Get updated score
238
- updated_user = next(user for user in users if user.get('pseudo') == user_pseudo)
239
- new_score = updated_user.get('score', 0)
240
-
241
- result = {
242
- "user_pseudo": user_pseudo,
243
- "new_score": new_score,
244
- "score_increased": correct
245
- }
246
-
247
- return json.dumps(result, indent=2)
248
-
249
- except Exception as e:
250
- return f"Error updating score: {str(e)}"
251
-
252
  @mcp.tool(
253
  title="Submit Answer",
254
- description="Submit answer, validate it, and update score in one operation",
255
  )
256
  async def submit_answer(
257
  session_id: str = Field(description="The ID of the quiz session"),
258
- user_pseudo: str = Field(description="The pseudo/username of the user"),
259
  answer_index: int = Field(description="The selected answer index (0-3)")
260
  ) -> str:
261
  """Submit answer, validate, and update score atomically"""
@@ -271,7 +169,7 @@ def register_tools(mcp: FastMCP, db_getter):
271
  session_data = session_doc.to_dict()
272
  questions = session_data.get('questions', [])
273
  current_question_index = session_data.get('current_question', 0)
274
- users = session_data.get('users', [])
275
 
276
  # Check if question exists
277
  if current_question_index >= len(questions):
@@ -281,29 +179,29 @@ def register_tools(mcp: FastMCP, db_getter):
281
  correct_answer = current_question.get('correct')
282
  is_correct = answer_index == correct_answer
283
 
284
- # Find and update user score
285
- user_found = False
286
  new_score = 0
287
- for user in users:
288
- if user.get('pseudo') == user_pseudo:
289
  if is_correct:
290
- user['score'] = user.get('score', 0) + 1
291
- new_score = user.get('score', 0)
292
- user_found = True
293
  break
294
 
295
- if not user_found:
296
- return f"User '{user_pseudo}' not found in session '{session_id}'"
297
 
298
  # Update session document
299
- session_data['users'] = users
300
  session_ref.set(session_data, merge=True)
301
 
302
  result = {
303
  "correct": is_correct,
304
  "correct_answer_index": correct_answer,
305
  "submitted_answer_index": answer_index,
306
- "user_pseudo": user_pseudo,
307
  "new_score": new_score,
308
  "question_id": current_question.get('id')
309
  }
@@ -313,49 +211,9 @@ def register_tools(mcp: FastMCP, db_getter):
313
  except Exception as e:
314
  return f"Error submitting answer: {str(e)}"
315
 
316
- @mcp.tool(
317
- title="Advance Question",
318
- description="Move to the next question in the quiz session",
319
- )
320
- async def advance_question(
321
- session_id: str = Field(description="The ID of the quiz session")
322
- ) -> str:
323
- """Advance to the next question in the session"""
324
- try:
325
- # Get database client lazily
326
- db = db_getter()
327
- session_ref = db.collection('quiz_sessions').document(session_id)
328
- session_doc = session_ref.get()
329
-
330
- if not session_doc.exists:
331
- return f"Session '{session_id}' not found"
332
-
333
- session_data = session_doc.to_dict()
334
- current_question_index = session_data.get('current_question', 0)
335
- total_questions = len(session_data.get('questions', []))
336
-
337
- # Advance question index
338
- new_question_index = current_question_index + 1
339
- session_data['current_question'] = new_question_index
340
-
341
- # Update session document
342
- session_ref.set(session_data, merge=True)
343
-
344
- result = {
345
- "previous_question": current_question_index + 1,
346
- "current_question": new_question_index + 1,
347
- "total_questions": total_questions,
348
- "quiz_finished": new_question_index >= total_questions
349
- }
350
-
351
- return json.dumps(result, indent=2)
352
-
353
- except Exception as e:
354
- return f"Error advancing question: {str(e)}"
355
-
356
  @mcp.tool(
357
  title="Get Live Scores",
358
- description="Get the current scoreboard for a quiz session",
359
  )
360
  async def get_scores(
361
  session_id: str = Field(description="The ID of the quiz session")
@@ -371,16 +229,16 @@ def register_tools(mcp: FastMCP, db_getter):
371
  return f"Session '{session_id}' not found"
372
 
373
  session_data = session_doc.to_dict()
374
- users = session_data.get('users', [])
375
  current_question = session_data.get('current_question', 0)
376
  total_questions = len(session_data.get('questions', []))
377
 
378
  # Build and sort scoreboard
379
  scores = []
380
- for user in users:
381
  scores.append({
382
- "pseudo": user.get('pseudo'),
383
- "score": user.get('score', 0)
384
  })
385
 
386
  # Sort by score (highest first)
@@ -396,59 +254,4 @@ def register_tools(mcp: FastMCP, db_getter):
396
  return json.dumps(result, indent=2)
397
 
398
  except Exception as e:
399
- return f"Error getting scores: {str(e)}"
400
-
401
- @mcp.tool(
402
- title="Get Final Score",
403
- description="Get final results when quiz is completed",
404
- )
405
- async def get_final_score(
406
- session_id: str = Field(description="The ID of the quiz session")
407
- ) -> str:
408
- """Get final quiz results"""
409
- try:
410
- # Get database client lazily
411
- db = db_getter()
412
- session_ref = db.collection('quiz_sessions').document(session_id)
413
- session_doc = session_ref.get()
414
-
415
- if not session_doc.exists:
416
- return f"Session '{session_id}' not found"
417
-
418
- session_data = session_doc.to_dict()
419
- users = session_data.get('users', [])
420
- current_question = session_data.get('current_question', 0)
421
- total_questions = len(session_data.get('questions', []))
422
-
423
- # Check if quiz is finished
424
- quiz_finished = current_question >= total_questions
425
-
426
- # Build final scoreboard
427
- scores = []
428
- for user in users:
429
- score = user.get('score', 0)
430
- scores.append({
431
- "pseudo": user.get('pseudo'),
432
- "score": score,
433
- "percentage": round((score / total_questions) * 100, 1) if total_questions > 0 else 0
434
- })
435
-
436
- # Sort by score (highest first)
437
- scores.sort(key=lambda x: x["score"], reverse=True)
438
-
439
- # Add rankings
440
- for i, score_entry in enumerate(scores):
441
- score_entry["rank"] = i + 1
442
-
443
- result = {
444
- "final_scores": scores,
445
- "total_questions": total_questions,
446
- "quiz_finished": quiz_finished,
447
- "session_id": session_id,
448
- "theme": session_data.get('theme', 'Unknown')
449
- }
450
-
451
- return json.dumps(result, indent=2)
452
-
453
- except Exception as e:
454
- return f"Error getting final scores: {str(e)}"
 
14
  """Register all MCP tools with lazy database loading"""
15
 
16
  @mcp.tool(
17
+ title="Add Player to Session",
18
+ description="Add a player to a session with their pseudo and score in the database",
19
  )
20
+ async def add_player(
21
+ session_id: str = Field(description="The ID of the session to add the player to"),
22
+ player_pseudo: str = Field(description="The pseudo/username of the player to add")
23
  ) -> str:
24
+ """Add a player to a session in the database"""
25
  try:
26
  # Get database client lazily
27
  db = db_getter()
 
34
 
35
  # Initialize session_data with default values
36
  session_data = {
37
+ 'players': []
38
  }
39
 
40
  if session_doc.exists:
41
  session_data = session_doc.to_dict()
42
 
43
+ # Add the new player to the players list
44
+ new_player = {
45
+ 'pseudo': player_pseudo,
46
  'score': 0 # Initialize score to 0
47
  }
48
 
49
+ # Check if player already exists in this session
50
+ players = session_data.get('players', [])
51
+ existing_player = next((player for player in players if player.get('pseudo') == player_pseudo), None)
52
 
53
+ if existing_player:
54
  result = {
55
+ "player_pseudo": player_pseudo,
56
  "session_id": session_id,
57
+ "score": existing_player.get('score', 0),
58
+ "message": f"Player '{player_pseudo}' already exists in session '{session_id}'",
59
  "already_exists": True
60
  }
61
  return json.dumps(result, indent=2)
62
 
63
+ # Generate player_id for the new player
64
+ player_id = str(uuid.uuid4())[:8]
65
+ new_player['player_id'] = player_id
66
 
67
+ # Add the new player
68
+ players.append(new_player)
69
+ session_data['players'] = players
70
 
71
  # Update the session document
72
  if not session_doc.exists:
 
79
  session_ref.set(session_data, merge=True)
80
 
81
  result = {
82
+ "player_id": player_id,
83
+ "player_pseudo": player_pseudo,
84
  "session_id": session_id,
85
  "score": 0,
86
+ "message": f"Successfully added player '{player_pseudo}' to session '{session_id}'",
87
  "already_exists": False
88
  }
89
 
90
  return json.dumps(result, indent=2)
91
 
92
  except Exception as e:
93
+ return f"Error adding player to session: {str(e)}"
94
 
95
  @mcp.tool(
96
  title="Get Next Question",
 
147
  except Exception as e:
148
  return f"Error getting next question: {str(e)}"
149
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
  @mcp.tool(
151
  title="Submit Answer",
152
+ description="Submit answer, validate it, and update score in one operation for the current user",
153
  )
154
  async def submit_answer(
155
  session_id: str = Field(description="The ID of the quiz session"),
156
+ player_pseudo: str = Field(description="The pseudo/playername of the player"),
157
  answer_index: int = Field(description="The selected answer index (0-3)")
158
  ) -> str:
159
  """Submit answer, validate, and update score atomically"""
 
169
  session_data = session_doc.to_dict()
170
  questions = session_data.get('questions', [])
171
  current_question_index = session_data.get('current_question', 0)
172
+ players = session_data.get('players', [])
173
 
174
  # Check if question exists
175
  if current_question_index >= len(questions):
 
179
  correct_answer = current_question.get('correct')
180
  is_correct = answer_index == correct_answer
181
 
182
+ # Find and update player score
183
+ player_found = False
184
  new_score = 0
185
+ for player in players:
186
+ if player.get('pseudo') == player_pseudo:
187
  if is_correct:
188
+ player['score'] = player.get('score', 0) + 1
189
+ new_score = player.get('score', 0)
190
+ player_found = True
191
  break
192
 
193
+ if not player_found:
194
+ return f"User '{player_pseudo}' not found in session '{session_id}'"
195
 
196
  # Update session document
197
+ session_data['players'] = players
198
  session_ref.set(session_data, merge=True)
199
 
200
  result = {
201
  "correct": is_correct,
202
  "correct_answer_index": correct_answer,
203
  "submitted_answer_index": answer_index,
204
+ "player_pseudo": player_pseudo,
205
  "new_score": new_score,
206
  "question_id": current_question.get('id')
207
  }
 
211
  except Exception as e:
212
  return f"Error submitting answer: {str(e)}"
213
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
214
  @mcp.tool(
215
  title="Get Live Scores",
216
+ description="Get the current scoreboard for a quiz session for all players",
217
  )
218
  async def get_scores(
219
  session_id: str = Field(description="The ID of the quiz session")
 
229
  return f"Session '{session_id}' not found"
230
 
231
  session_data = session_doc.to_dict()
232
+ players = session_data.get('players', [])
233
  current_question = session_data.get('current_question', 0)
234
  total_questions = len(session_data.get('questions', []))
235
 
236
  # Build and sort scoreboard
237
  scores = []
238
+ for player in players:
239
  scores.append({
240
+ "pseudo": player.get('pseudo'),
241
+ "score": player.get('score', 0)
242
  })
243
 
244
  # Sort by score (highest first)
 
254
  return json.dumps(result, indent=2)
255
 
256
  except Exception as e:
257
+ return f"Error getting scores: {str(e)}"