| """MCP Tool definitions for HR Onboarding/Offboarding environment. |
| |
| Each tool is a callable that takes parameters and operates on the WorldState. |
| Tools are designed to mirror realistic enterprise HR/IT APIs. |
| """ |
|
|
| import json |
| from typing import Any, Callable |
| try: |
| from .world import WorldState |
| except ImportError: |
| from world import WorldState |
|
|
|
|
| TOOL_DEFINITIONS = [ |
| { |
| "name": "hr_create_employee", |
| "description": "Create a new employee record in the HR system. Requires name, department, level, and role. Returns the created employee record with generated emp_id.", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "name": {"type": "string", "description": "Full name of the employee"}, |
| "department": {"type": "string", "description": "Department name (Engineering, Product, Marketing, Sales, Finance, HR, Data Science, Security)"}, |
| "level": {"type": "string", "description": "Employee level (L1-L6)"}, |
| "role": {"type": "string", "description": "Job title/role"}, |
| "manager_id": {"type": "string", "description": "Employee ID of the manager"}, |
| "is_contractor": {"type": "boolean", "description": "Whether this is a contractor (default: false)"}, |
| "location": {"type": "string", "description": "Office location"}, |
| "date_of_joining": {"type": "string", "description": "Start date (YYYY-MM-DD)"}, |
| }, |
| "required": ["name", "department", "level", "role"], |
| }, |
| }, |
| { |
| "name": "hr_read_employee", |
| "description": "Look up an employee by their employee ID or email address. Returns full employee record.", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "emp_id": {"type": "string", "description": "Employee ID (e.g. emp_0001)"}, |
| "email": {"type": "string", "description": "Employee email address"}, |
| }, |
| }, |
| }, |
| { |
| "name": "hr_update_employee", |
| "description": "Update fields on an existing employee record. Cannot modify emp_id.", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "emp_id": {"type": "string", "description": "Employee ID to update"}, |
| "updates": {"type": "object", "description": "Dictionary of fields to update (e.g. {status: 'active', department: 'Engineering'})"}, |
| }, |
| "required": ["emp_id", "updates"], |
| }, |
| }, |
| { |
| "name": "hr_search_employees", |
| "description": "Search employees by criteria. Filter by department, level, status, location, or role.", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "department": {"type": "string", "description": "Filter by department"}, |
| "level": {"type": "string", "description": "Filter by level (L1-L6)"}, |
| "status": {"type": "string", "description": "Filter by status (active, pending, offboarded)"}, |
| "location": {"type": "string", "description": "Filter by location"}, |
| "role": {"type": "string", "description": "Filter by role/title"}, |
| "name": {"type": "string", "description": "Filter by name (exact match)"}, |
| }, |
| }, |
| }, |
| { |
| "name": "hr_get_org_chart", |
| "description": "Get the organizational hierarchy/reporting structure for a department. Shows manager-report relationships.", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "department": {"type": "string", "description": "Department name"}, |
| }, |
| "required": ["department"], |
| }, |
| }, |
| { |
| "name": "onboarding_create_request", |
| "description": "Initiate an onboarding request for a new hire. The employee must exist in the HR system with 'pending' status. Creates a checklist of onboarding steps based on department.", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "employee_id": {"type": "string", "description": "Employee ID of the new hire"}, |
| }, |
| "required": ["employee_id"], |
| }, |
| }, |
| { |
| "name": "onboarding_get_status", |
| "description": "Check the status of an onboarding request. Can look up by request ID or employee ID.", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "request_id": {"type": "string", "description": "Onboarding request ID"}, |
| "employee_id": {"type": "string", "description": "Employee ID"}, |
| }, |
| }, |
| }, |
| { |
| "name": "onboarding_complete_step", |
| "description": "Mark an onboarding step as completed. Steps must be valid for the request.", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "request_id": {"type": "string", "description": "Onboarding request ID"}, |
| "step": {"type": "string", "description": "Step name to mark as completed"}, |
| }, |
| "required": ["request_id", "step"], |
| }, |
| }, |
| { |
| "name": "offboarding_create_request", |
| "description": "Initiate an offboarding request for a departing employee. Specify reason (resignation, termination, transfer) and optional exit date.", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "employee_id": {"type": "string", "description": "Employee ID"}, |
| "reason": {"type": "string", "description": "Reason for offboarding (resignation, termination, transfer)"}, |
| "exit_date": {"type": "string", "description": "Last working date (YYYY-MM-DD)"}, |
| }, |
| "required": ["employee_id"], |
| }, |
| }, |
| { |
| "name": "offboarding_get_status", |
| "description": "Check the status of an offboarding request. Can look up by request ID or employee ID.", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "request_id": {"type": "string", "description": "Offboarding request ID"}, |
| "employee_id": {"type": "string", "description": "Employee ID"}, |
| }, |
| }, |
| }, |
| { |
| "name": "offboarding_complete_step", |
| "description": "Mark an offboarding step as completed.", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "request_id": {"type": "string", "description": "Offboarding request ID"}, |
| "step": {"type": "string", "description": "Step name to mark as completed"}, |
| }, |
| "required": ["request_id", "step"], |
| }, |
| }, |
| { |
| "name": "it_assign_asset", |
| "description": "Assign an IT asset (laptop, monitor, phone, headset) to an employee. Asset must be available.", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "asset_id": {"type": "string", "description": "Asset ID to assign"}, |
| "employee_id": {"type": "string", "description": "Employee ID to assign to"}, |
| }, |
| "required": ["asset_id", "employee_id"], |
| }, |
| }, |
| { |
| "name": "it_get_available_assets", |
| "description": "List available (unassigned) IT assets. Optionally filter by type.", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "asset_type": {"type": "string", "description": "Filter by asset type (laptop, monitor, phone, headset)"}, |
| }, |
| }, |
| }, |
| { |
| "name": "it_create_account", |
| "description": "Create IT accounts (email, Slack, VPN, etc.) for an employee.", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "employee_id": {"type": "string", "description": "Employee ID"}, |
| "account_types": { |
| "type": "array", |
| "items": {"type": "string"}, |
| "description": "Types of accounts to create (email, slack, vpn, github, jira, etc.)", |
| }, |
| }, |
| "required": ["employee_id"], |
| }, |
| }, |
| { |
| "name": "it_revoke_access", |
| "description": "Revoke all IT system access for an employee (used during offboarding).", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "employee_id": {"type": "string", "description": "Employee ID"}, |
| }, |
| "required": ["employee_id"], |
| }, |
| }, |
| { |
| "name": "it_get_software_licenses", |
| "description": "Check software license availability. Optionally filter by software name.", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "software_name": {"type": "string", "description": "Filter by software name"}, |
| }, |
| }, |
| }, |
| { |
| "name": "access_assign_role", |
| "description": "Assign an access role to an employee. Checks level requirements and department restrictions.", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "employee_id": {"type": "string", "description": "Employee ID"}, |
| "role_id": {"type": "string", "description": "Access role ID to assign"}, |
| }, |
| "required": ["employee_id", "role_id"], |
| }, |
| }, |
| { |
| "name": "access_create_badge", |
| "description": "Create a physical access badge for an employee. Server room access requires L4+ security approval.", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "employee_id": {"type": "string", "description": "Employee ID"}, |
| "access_zones": { |
| "type": "array", |
| "items": {"type": "string"}, |
| "description": "List of access zones (main_entrance, floor_X, server_room, parking)", |
| }, |
| }, |
| "required": ["employee_id"], |
| }, |
| }, |
| { |
| "name": "access_revoke_role", |
| "description": "Revoke a specific access role from an employee.", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "employee_id": {"type": "string", "description": "Employee ID"}, |
| "role_id": {"type": "string", "description": "Access role ID to revoke"}, |
| }, |
| "required": ["employee_id", "role_id"], |
| }, |
| }, |
| { |
| "name": "access_get_security_groups", |
| "description": "List all security groups. Optionally see members and resources.", |
| "parameters": { |
| "type": "object", |
| "properties": {}, |
| }, |
| }, |
| { |
| "name": "email_send", |
| "description": "Send an email. Used for welcome emails, notifications, farewell messages, etc.", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "from_address": {"type": "string", "description": "Sender email address"}, |
| "to_address": {"type": "string", "description": "Recipient email address"}, |
| "subject": {"type": "string", "description": "Email subject line"}, |
| "body": {"type": "string", "description": "Email body text"}, |
| }, |
| "required": ["from_address", "to_address", "subject", "body"], |
| }, |
| }, |
| { |
| "name": "slack_send_message", |
| "description": "Post a message in a Slack channel or send a DM.", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "channel": {"type": "string", "description": "Slack channel (e.g. #engineering, #general, @username)"}, |
| "sender": {"type": "string", "description": "Sender username or bot name"}, |
| "text": {"type": "string", "description": "Message text"}, |
| }, |
| "required": ["channel", "sender", "text"], |
| }, |
| }, |
| { |
| "name": "meeting_schedule", |
| "description": "Schedule a meeting (orientation, 1-on-1, exit interview, etc.).", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "title": {"type": "string", "description": "Meeting title"}, |
| "attendees": { |
| "type": "array", |
| "items": {"type": "string"}, |
| "description": "List of attendee employee IDs or emails", |
| }, |
| "datetime": {"type": "string", "description": "Meeting date and time (ISO format)"}, |
| "meeting_type": {"type": "string", "description": "Type of meeting (orientation, one_on_one, exit_interview, team_intro)"}, |
| }, |
| "required": ["title", "attendees", "datetime"], |
| }, |
| }, |
| { |
| "name": "policy_lookup", |
| "description": "Look up company policies by topic or department. Returns policy content and key rules.", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "topic": {"type": "string", "description": "Policy topic to search for"}, |
| "department": {"type": "string", "description": "Department-specific policies"}, |
| "policy_id": {"type": "string", "description": "Specific policy ID"}, |
| }, |
| }, |
| }, |
| { |
| "name": "approval_request", |
| "description": "Submit an approval request (manager approval, IT approval, security approval). Approver must meet level requirements.", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "request_id": {"type": "string", "description": "The onboarding/offboarding request ID this approval is for"}, |
| "approver_id": {"type": "string", "description": "Employee ID of the approver"}, |
| "approval_type": {"type": "string", "description": "Type of approval (manager_approval, it_approval, security_approval, legal_approval)"}, |
| }, |
| "required": ["request_id", "approver_id", "approval_type"], |
| }, |
| }, |
| ] |
|
|
|
|
| class ToolRegistry: |
| """Registry of all available tools, mapping names to executors.""" |
|
|
| def __init__(self, world: WorldState): |
| self.world = world |
| self._tools: dict[str, Callable] = self._register_tools() |
|
|
| def _register_tools(self) -> dict[str, Callable]: |
| return { |
| "hr_create_employee": self._hr_create_employee, |
| "hr_read_employee": self._hr_read_employee, |
| "hr_update_employee": self._hr_update_employee, |
| "hr_search_employees": self._hr_search_employees, |
| "hr_get_org_chart": self._hr_get_org_chart, |
| "onboarding_create_request": self._onboarding_create_request, |
| "onboarding_get_status": self._onboarding_get_status, |
| "onboarding_complete_step": self._onboarding_complete_step, |
| "offboarding_create_request": self._offboarding_create_request, |
| "offboarding_get_status": self._offboarding_get_status, |
| "offboarding_complete_step": self._offboarding_complete_step, |
| "it_assign_asset": self._it_assign_asset, |
| "it_get_available_assets": self._it_get_available_assets, |
| "it_create_account": self._it_create_account, |
| "it_revoke_access": self._it_revoke_access, |
| "it_get_software_licenses": self._it_get_software_licenses, |
| "access_assign_role": self._access_assign_role, |
| "access_create_badge": self._access_create_badge, |
| "access_revoke_role": self._access_revoke_role, |
| "access_get_security_groups": self._access_get_security_groups, |
| "email_send": self._email_send, |
| "slack_send_message": self._slack_send_message, |
| "meeting_schedule": self._meeting_schedule, |
| "policy_lookup": self._policy_lookup, |
| "approval_request": self._approval_request, |
| } |
|
|
| @property |
| def tool_definitions(self) -> list[dict]: |
| return TOOL_DEFINITIONS |
|
|
| @property |
| def tool_names(self) -> list[str]: |
| return list(self._tools.keys()) |
|
|
| def execute(self, tool_name: str, params: dict) -> dict: |
| """Execute a tool by name with given parameters. Returns result dict.""" |
| if tool_name not in self._tools: |
| return {"success": False, "error": f"Unknown tool: {tool_name}. Available tools: {self.tool_names}"} |
| try: |
| result = self._tools[tool_name](params) |
| self.world.log_action(tool_name, params, result) |
| return result |
| except Exception as e: |
| error_result = {"success": False, "error": f"Tool execution error: {str(e)}"} |
| self.world.log_action(tool_name, params, error_result) |
| return error_result |
|
|
| |
|
|
| def _hr_create_employee(self, params: dict) -> dict: |
| return self.world.create_employee(params) |
|
|
| def _hr_read_employee(self, params: dict) -> dict: |
| emp = None |
| if "emp_id" in params: |
| emp = self.world.get_employee(params["emp_id"]) |
| elif "email" in params: |
| emp = self.world.get_employee_by_email(params["email"]) |
| if emp: |
| return {"success": True, "employee": emp} |
| return {"success": False, "error": "Employee not found"} |
|
|
| def _hr_update_employee(self, params: dict) -> dict: |
| return self.world.update_employee(params["emp_id"], params["updates"]) |
|
|
| def _hr_search_employees(self, params: dict) -> dict: |
| results = self.world.search_employees(**params) |
| return {"success": True, "count": len(results), "employees": results} |
|
|
| def _hr_get_org_chart(self, params: dict) -> dict: |
| chart = self.world.get_org_chart(params["department"]) |
| if chart: |
| return {"success": True, "org_chart": chart} |
| return {"success": False, "error": f"No employees found in department '{params['department']}'"} |
|
|
| def _onboarding_create_request(self, params: dict) -> dict: |
| return self.world.create_onboarding_request(params["employee_id"]) |
|
|
| def _onboarding_get_status(self, params: dict) -> dict: |
| status = self.world.get_onboarding_status( |
| request_id=params.get("request_id"), |
| emp_id=params.get("employee_id"), |
| ) |
| if status: |
| return {"success": True, "onboarding_status": status} |
| return {"success": False, "error": "Onboarding request not found"} |
|
|
| def _onboarding_complete_step(self, params: dict) -> dict: |
| return self.world.complete_onboarding_step(params["request_id"], params["step"]) |
|
|
| def _offboarding_create_request(self, params: dict) -> dict: |
| return self.world.create_offboarding_request( |
| params["employee_id"], |
| reason=params.get("reason", "resignation"), |
| exit_date=params.get("exit_date"), |
| ) |
|
|
| def _offboarding_get_status(self, params: dict) -> dict: |
| status = self.world.get_offboarding_status( |
| request_id=params.get("request_id"), |
| emp_id=params.get("employee_id"), |
| ) |
| if status: |
| return {"success": True, "offboarding_status": status} |
| return {"success": False, "error": "Offboarding request not found"} |
|
|
| def _offboarding_complete_step(self, params: dict) -> dict: |
| return self.world.complete_offboarding_step(params["request_id"], params["step"]) |
|
|
| def _it_assign_asset(self, params: dict) -> dict: |
| return self.world.assign_asset(params["asset_id"], params["employee_id"]) |
|
|
| def _it_get_available_assets(self, params: dict) -> dict: |
| assets = self.world.get_available_assets(params.get("asset_type")) |
| return {"success": True, "count": len(assets), "assets": assets} |
|
|
| def _it_create_account(self, params: dict) -> dict: |
| return self.world.create_it_account( |
| params["employee_id"], |
| account_types=params.get("account_types"), |
| ) |
|
|
| def _it_revoke_access(self, params: dict) -> dict: |
| return self.world.revoke_it_access(params["employee_id"]) |
|
|
| def _it_get_software_licenses(self, params: dict) -> dict: |
| licenses = self.world.get_software_licenses(params.get("software_name")) |
| return {"success": True, "licenses": licenses} |
|
|
| def _access_assign_role(self, params: dict) -> dict: |
| return self.world.assign_role(params["employee_id"], params["role_id"]) |
|
|
| def _access_create_badge(self, params: dict) -> dict: |
| return self.world.create_badge( |
| params["employee_id"], |
| access_zones=params.get("access_zones"), |
| ) |
|
|
| def _access_revoke_role(self, params: dict) -> dict: |
| return self.world.revoke_role(params["employee_id"], params["role_id"]) |
|
|
| def _access_get_security_groups(self, params: dict) -> dict: |
| return {"success": True, "security_groups": self.world.state["security_groups"]} |
|
|
| def _email_send(self, params: dict) -> dict: |
| return self.world.send_email( |
| params["from_address"], params["to_address"], |
| params["subject"], params["body"], |
| ) |
|
|
| def _slack_send_message(self, params: dict) -> dict: |
| return self.world.send_slack_message( |
| params["channel"], params["sender"], params["text"], |
| ) |
|
|
| def _meeting_schedule(self, params: dict) -> dict: |
| return self.world.schedule_meeting( |
| params["title"], params["attendees"], |
| params["datetime"], params.get("meeting_type", "general"), |
| ) |
|
|
| def _policy_lookup(self, params: dict) -> dict: |
| policies = self.world.lookup_policy( |
| topic=params.get("topic"), |
| department=params.get("department"), |
| policy_id=params.get("policy_id"), |
| ) |
| return {"success": True, "count": len(policies), "policies": policies} |
|
|
| def _approval_request(self, params: dict) -> dict: |
| return self.world.create_approval( |
| params["request_id"], params["approver_id"], params["approval_type"], |
| ) |
|
|