jobsearch-mcp-server / src /services /profile_service.py
daniielyan's picture
πŸ”¨ Implement core functionality for Job Search MCP Server, including user profile management, job search, cover letter generation, and Q&A response tools. Add configuration and service layers, and establish dependency management with uv. Introduce .gitignore and .python-version files for environment setup.
4fd18a2
"""Profile service for managing user profiles and data."""
import json
import os
from datetime import datetime
from typing import Any, Dict, Optional
from pydantic import BaseModel, Field
from ..config import get_settings
class UserProfile(BaseModel):
"""User profile data model."""
user_id: str
resume: str
skills: list[str]
salary_wish: str
career_goals: str
experience_level: Optional[str] = None
location: Optional[str] = None
education: Optional[str] = None
certifications: Optional[list[str]] = None
created_at: datetime = Field(default_factory=datetime.now)
updated_at: datetime = Field(default_factory=datetime.now)
class ProfileService:
"""Service for managing user profiles."""
def __init__(self):
self.settings = get_settings()
self.profiles_path = self.settings.profiles_db_path
self._ensure_data_dir()
def _ensure_data_dir(self):
"""Ensure data directory exists."""
os.makedirs(os.path.dirname(self.profiles_path), exist_ok=True)
def _load_profiles(self) -> Dict[str, Dict[str, Any]]:
"""Load profiles from file."""
if not os.path.exists(self.profiles_path):
return {}
try:
with open(self.profiles_path, "r", encoding="utf-8") as f:
return json.load(f)
except (json.JSONDecodeError, FileNotFoundError):
return {}
def _save_profiles(self, profiles: Dict[str, Dict[str, Any]]):
"""Save profiles to file."""
with open(self.profiles_path, "w", encoding="utf-8") as f:
json.dump(profiles, f, indent=2, default=str)
def upsert_profile(self, user_id: str, profile_data: str) -> Dict[str, Any]:
"""
Store or update user profile.
Args:
user_id: Unique user identifier
profile_data: JSON string containing profile information
Returns:
Dict with operation result
"""
try:
# Parse profile data
profile_dict = json.loads(profile_data)
# Validate required fields
required_fields = ["resume", "skills", "salary_wish", "career_goals"]
missing_fields = [
field for field in required_fields if field not in profile_dict
]
if missing_fields:
return {
"success": False,
"message": f"Missing required fields: {', '.join(missing_fields)}",
}
# Create profile model
profile_dict["user_id"] = user_id
profile = UserProfile(**profile_dict)
# Load existing profiles
profiles = self._load_profiles()
# Update timestamp if profile exists
if user_id in profiles:
profile.updated_at = datetime.now()
# Store profile
profiles[user_id] = profile.dict()
self._save_profiles(profiles)
return {
"success": True,
"message": "Profile updated successfully",
"user_id": user_id,
"profile": {
"skills_count": len(profile.skills),
"updated_at": profile.updated_at.isoformat(),
},
}
except json.JSONDecodeError:
return {"success": False, "message": "Invalid JSON format in profile data"}
except Exception as e:
return {"success": False, "message": f"Error updating profile: {str(e)}"}
def get_profile(self, user_id: str) -> Optional[UserProfile]:
"""Get user profile by ID."""
profiles = self._load_profiles()
profile_data = profiles.get(user_id)
if profile_data:
return UserProfile(**profile_data)
return None
def delete_profile(self, user_id: str) -> bool:
"""Delete user profile."""
profiles = self._load_profiles()
if user_id in profiles:
del profiles[user_id]
self._save_profiles(profiles)
return True
return False
def list_profiles(self) -> list[str]:
"""List all user IDs."""
profiles = self._load_profiles()
return list(profiles.keys())