Recruitment_Copilot / backend /mcp_server /tools /application_status.py
Ashgen12's picture
Recruitment Copilot
14fdc5e verified
Raw
History Blame Contribute Delete
5.97 kB
from __future__ import annotations
from fastmcp import FastMCP
from sqlalchemy import select
from core.db import SessionLocal
from core.models import ApplicationStatus
DEFAULT_STAGES = [
"Applied",
"Screening",
"Shortlisted",
"Interview Scheduled",
"Technical Round",
"Final Interview",
"Offered",
"Hired",
"Rejected",
]
def register(mcp: FastMCP) -> None:
@mcp.tool()
def manage_application_status(
mode: str,
candidate_id: str | None = None,
candidate_name: str | None = None,
role_applied: str | None = None,
stage: str | None = None,
status: str | None = None,
notes: str | None = None,
) -> dict:
"""Create, update, and retrieve application statuses for candidates."""
normalized_mode = mode.strip().lower()
with SessionLocal() as db:
if normalized_mode in {"upsert", "update"}:
if not candidate_id:
return {"status": "error", "message": "candidate_id is required for upsert."}
existing = db.execute(
select(ApplicationStatus).where(ApplicationStatus.candidate_id == candidate_id)
).scalar_one_or_none()
if existing is None:
existing = ApplicationStatus(candidate_id=candidate_id)
db.add(existing)
if candidate_name is not None:
existing.candidate_name = candidate_name
if role_applied is not None:
existing.role_applied = role_applied
if stage is not None:
existing.stage = stage
if status is not None:
existing.status = status
if notes is not None:
existing.notes = notes
db.commit()
db.refresh(existing)
return {
"status": "success",
"message": "Application status upserted.",
"record": {
"candidate_id": existing.candidate_id,
"candidate_name": existing.candidate_name,
"role_applied": existing.role_applied,
"stage": existing.stage,
"status_text": existing.status,
"notes": existing.notes,
},
}
if normalized_mode == "advance":
if not candidate_id:
return {"status": "error", "message": "candidate_id is required to advance stage."}
existing = db.execute(
select(ApplicationStatus).where(ApplicationStatus.candidate_id == candidate_id)
).scalar_one_or_none()
if existing is None:
return {"status": "not_found", "message": "Candidate application not found."}
current_stage = existing.stage or "Applied"
if current_stage not in DEFAULT_STAGES:
existing.stage = "Applied"
else:
idx = DEFAULT_STAGES.index(current_stage)
next_idx = min(idx + 1, len(DEFAULT_STAGES) - 1)
existing.stage = DEFAULT_STAGES[next_idx]
if notes:
existing.notes = notes
db.commit()
db.refresh(existing)
return {
"status": "success",
"message": "Application stage advanced.",
"record": {
"candidate_id": existing.candidate_id,
"stage": existing.stage,
"status_text": existing.status,
"notes": existing.notes,
},
}
if normalized_mode == "get":
if not candidate_id:
return {"status": "error", "message": "candidate_id is required for get."}
existing = db.execute(
select(ApplicationStatus).where(ApplicationStatus.candidate_id == candidate_id)
).scalar_one_or_none()
if existing is None:
return {"status": "not_found", "message": "Candidate application not found."}
return {
"status": "success",
"record": {
"candidate_id": existing.candidate_id,
"candidate_name": existing.candidate_name,
"role_applied": existing.role_applied,
"stage": existing.stage,
"status_text": existing.status,
"notes": existing.notes,
},
}
if normalized_mode == "list":
rows = db.execute(
select(ApplicationStatus).order_by(ApplicationStatus.updated_at.desc()).limit(50)
).scalars().all()
records = [
{
"candidate_id": row.candidate_id,
"candidate_name": row.candidate_name,
"role_applied": row.role_applied,
"stage": row.stage,
"status_text": row.status,
}
for row in rows
]
return {
"status": "success",
"count": len(records),
"records": records,
}
return {
"status": "error",
"message": "Unsupported mode. Use upsert, update, advance, get, or list.",
}