competitions.py•9.81 kB
"""Competition tools for Kaggle API."""
import os
import json
import tempfile
from typing import Optional, Dict, Any
from kaggle_mcp.tools.auth import api, ensure_authenticated
def init_competition_tools(mcp_instance):
"""Initialize competition tools with the given MCP instance."""
@mcp_instance.tool()
def competitions_list(search: str = "", category: str = "all", group: str = "general",
sort_by: str = "latestDeadline", page: int = 1) -> str:
"""List available Kaggle competitions.
Args:
search: Term(s) to search for
category: Filter by category (all, featured, research, recruitment, gettingStarted, masters, playground)
group: Filter by group (general, entered, inClass)
sort_by: Sort by (grouped, prize, earliestDeadline, latestDeadline, numberOfTeams, recentlyCreated)
page: Page number for results paging
Returns:
JSON string with competition details
"""
authenticated, msg = ensure_authenticated()
if not authenticated:
return msg
try:
competitions = api.competitions_list(search=search, category=category,
group=group, sort_by=sort_by, page=page)
result = []
for comp in competitions:
result.append({
"ref": comp.ref,
"title": comp.title,
"url": comp.url,
"category": comp.category,
"deadline": str(comp.deadline) if comp.deadline else None,
"reward": comp.reward,
"teamCount": comp.teamCount,
"userHasEntered": comp.userHasEntered,
"description": comp.description
})
return json.dumps(result, indent=2)
except Exception as e:
return f"Error listing competitions: {str(e)}"
@mcp_instance.tool()
def competition_details(competition: str) -> str:
"""Get details about a specific competition.
Args:
competition: Competition URL suffix (e.g., 'titanic')
Returns:
JSON string with competition details
"""
authenticated, msg = ensure_authenticated()
if not authenticated:
return msg
try:
comp = api.competition_get(competition)
result = {
"ref": comp.ref,
"title": comp.title,
"url": comp.url,
"category": comp.category,
"deadline": str(comp.deadline) if comp.deadline else None,
"reward": comp.reward,
"teamCount": comp.teamCount,
"userHasEntered": comp.userHasEntered,
"description": comp.description,
"evaluationMetric": comp.evaluationMetric,
"isKernelsSubmissionsOnly": comp.isKernelsSubmissionsOnly,
"tags": comp.tags
}
return json.dumps(result, indent=2)
except Exception as e:
return f"Error getting competition details: {str(e)}"
@mcp_instance.tool()
def competition_download_files(competition: str, path: str = "",
file_name: str = "", force: bool = False) -> str:
"""Download competition files.
Args:
competition: Competition URL suffix (e.g., 'titanic')
path: Folder where file(s) will be downloaded (defaults to a temp directory)
file_name: File name, all files downloaded if not provided
force: Force download even if files exist
Returns:
Success message or error details
"""
authenticated, msg = ensure_authenticated()
if not authenticated:
return msg
# Create a temporary directory if no path is specified
use_temp = False
if not path:
path = tempfile.mkdtemp()
use_temp = True
try:
if file_name:
api.competition_download_file(competition, file_name, path=path, force=force)
result = f"Downloaded file '{file_name}' to {path}"
else:
api.competition_download_files(competition, path=path, force=force)
result = f"Downloaded all competition files to {path}"
return result
except Exception as e:
if use_temp:
try:
os.rmdir(path)
except:
pass
return f"Error downloading competition files: {str(e)}"
@mcp_instance.tool()
def competition_list_files(competition: str) -> str:
"""List files in a competition.
Args:
competition: Competition URL suffix (e.g., 'titanic')
Returns:
JSON string with file details
"""
authenticated, msg = ensure_authenticated()
if not authenticated:
return msg
try:
files = api.competition_list_files(competition)
result = []
for file in files:
result.append({
"name": file.name,
"size": file.size,
"creationDate": str(file.creationDate) if hasattr(file, 'creationDate') else None
})
return json.dumps(result, indent=2)
except Exception as e:
return f"Error listing competition files: {str(e)}"
@mcp_instance.tool()
def competition_submissions(competition: str) -> str:
"""List your submissions for a competition.
Args:
competition: Competition URL suffix (e.g., 'titanic')
Returns:
JSON string with submission details
"""
authenticated, msg = ensure_authenticated()
if not authenticated:
return msg
try:
submissions = api.competition_submissions(competition)
result = []
for sub in submissions:
result.append({
"ref": sub.ref if hasattr(sub, 'ref') else None,
"fileName": sub.fileName if hasattr(sub, 'fileName') else None,
"date": str(sub.date) if hasattr(sub, 'date') else None,
"description": sub.description if hasattr(sub, 'description') else None,
"status": sub.status if hasattr(sub, 'status') else None,
"publicScore": sub.publicScore if hasattr(sub, 'publicScore') else None,
"privateScore": sub.privateScore if hasattr(sub, 'privateScore') else None
})
return json.dumps(result, indent=2)
except Exception as e:
return f"Error listing submissions: {str(e)}"
@mcp_instance.tool()
def competition_leaderboard(competition: str) -> str:
"""Get the competition leaderboard.
Args:
competition: Competition URL suffix (e.g., 'titanic')
Returns:
JSON string with leaderboard details
"""
authenticated, msg = ensure_authenticated()
if not authenticated:
return msg
try:
leaderboard = api.competition_leaderboard_view(competition)
result = []
for entry in leaderboard:
result.append({
"teamId": entry.teamId if hasattr(entry, 'teamId') else None,
"teamName": entry.teamName if hasattr(entry, 'teamName') else None,
"submissionDate": str(entry.submissionDate) if hasattr(entry, 'submissionDate') else None,
"score": entry.score if hasattr(entry, 'score') else None,
"rank": entry.rank if hasattr(entry, 'rank') else None
})
return json.dumps(result, indent=2)
except Exception as e:
return f"Error retrieving leaderboard: {str(e)}"
@mcp_instance.tool()
def competition_submit(competition: str, file_path: str, message: str) -> str:
"""Submit to a competition.
Args:
competition: Competition URL suffix (e.g., 'titanic')
file_path: Path to the submission file
message: Submission description
Returns:
Success message or error details
"""
authenticated, msg = ensure_authenticated()
if not authenticated:
return msg
try:
# Check if file exists
if not os.path.isfile(file_path):
return f"Error: File not found at {file_path}"
# Get file size and last modified date
file_size = os.path.getsize(file_path)
last_modified = int(os.path.getmtime(file_path))
# Generate submission URL
submission_url = api.competition_submit_url(competition, file_size, last_modified)
# Upload the file
result = api.competition_submit_file(file_path, submission_url['createUrl'])
# Submit with the file token
response = api.competition_submit(competition, result['token'], message)
return f"Submission successful! Status: {response.status}"
except Exception as e:
return f"Error submitting to competition: {str(e)}"