Build an AI-Powered HR Agent with MCP in Just 10 Minutes
In this article, we are going to build a beginner-friendly first MCP server for a real-life use case: an HR agent that can help manage employee leave.
The server architecture is straightforward. We'll have a mock database containing employee information, such as leave history and balances. We will then build an MCP server to access this database. For the client, instead of building a custom internal chatbot, we will use a generic MCP client called Claude Desktop to interact with our server.
This setup allows the client to make calls to the MCP server we are building, creating a simple yet powerful HR assistant.
Prerequisites and Installation
Before we begin, you'll need to install a couple of things.
- Claude Desktop: Search for and install Claude Desktop for your specific operating system. The process is self-explanatory.
- MCP Python SDK: Open your command prompt or terminal and run the following command to install the necessary Python SDK:
bash pip install mcp
- UV (Python Package Manager): We will use UV to set up our project. Install it by running:
bash pip install uv
Note for Windows users: You can also use the following command in your command prompt to install UV:powershell powershell -c "irm https://github.com/astral-sh/uv/releases/latest/download/uv-installer.ps1 | iex"
Setting Up the Project
Once UV is installed, navigate to your desired project directory and initialize the server.
uv init my-first-mcp-server
This command creates a new directory named my-first-mcp-server
with a basic project skeleton, including a main.py
file, a pyproject.toml
configuration file, and a README.md
.
Crafting the HR Agent Logic
Now, let's add the core logic for our leave management server to the main.py
file. The following code sets up the server, defines a mock database, and creates several tools for managing employee leave.
from fastmcp import FastMCP
# In a real-world scenario, this data would come from a database.
# For this example, we use a mock dictionary.
mock_employee_db = {
"E001": {
"name": "John Doe",
"balance": 18,
"history": [
{"date": "2024-12-25", "reason": "Christmas Day"},
{"date": "2025-01-01", "reason": "New Year's Day"},
],
},
"E002": {
"name": "Jane Smith",
"balance": 20,
"history": [],
},
}
# Create an MCP server instance
server = FastMCP(
"leave-manager",
"HR Leave Management Agent",
"An agent to manage employee leave requests and balances.",
)
@server.tool()
def get_leave_balance(employee_id: str) -> str:
"""
Gets the remaining leave balance for a given employee.
:param employee_id: The unique identifier for the employee (e.g., 'E001').
"""
employee = mock_employee_db.get(employee_id)
if employee:
return f"Employee {employee_id} has {employee['balance']} days of leave remaining."
return f"Employee {employee_id} not found."
@server.tool()
def apply_for_leave(employee_id: str, leave_dates: list[str], reason: str) -> str:
"""
Applies for leave for a given employee on specified dates.
:param employee_id: The unique identifier for the employee.
:param leave_dates: A list of dates for the leave in 'YYYY-MM-DD' format.
:param reason: The reason for the leave request.
"""
employee = mock_employee_db.get(employee_id)
if not employee:
return f"Employee {employee_id} not found."
num_days = len(leave_dates)
if employee['balance'] >= num_days:
employee['balance'] -= num_days
for date in leave_dates:
employee['history'].append({"date": date, "reason": reason})
return f"Successfully applied for {num_days} day(s) of leave for employee {employee_id}. Remaining balance: {employee['balance']} days."
else:
return f"Insufficient leave balance for employee {employee_id}. Requested: {num_days}, Available: {employee['balance']}."
@server.tool()
def get_leave_history(employee_id: str) -> str:
"""
Retrieves the leave history for a given employee.
:param employee_id: The unique identifier for the employee.
"""
employee = mock_employee_db.get(employee_id)
if not employee:
return f"Employee {employee_id} not found."
if not employee['history']:
return f"Employee {employee_id} has no leave history."
history_str = "\n".join([f"- {item['date']}: {item['reason']}" for item in employee['history']])
return f"Leave history for {employee_id}:\n{history_str}"
@server.resource()
def greeting(query: str) -> str:
"""A general greeting resource."""
return "Hello! I am the ATL Leave Management assistant. How can I help you today?"
Code Breakdown
This simple server code is designed to be easy to understand.
- Mock Database: We use a simple Python dictionary
mock_employee_db
to simulate a database with two employees, their leave balances, and their leave history. - FastMCP Instance: We create an instance of the
FastMCP
class, giving our server a name, title, and description. - Tools: We define three primary functions decorated with
@server.tool()
:-
get_leave_balance
: Fetches the current leave balance for an employee. -
apply_for_leave
: Processes a new leave application, updating the balance and history. -
get_leave_history
: Retrieves all past leaves taken by an employee.
-
- Docstrings: Notice the detailed docstrings for each tool. These are critically important as they guide the MCP client (the LLM) on how to call the function and format the arguments correctly.
- Resource: The
@server.resource()
decorator defines a simple greeting.
Connecting the Agent to Claude
With the server code ready, run the following command in your terminal from the project directory:
uv mcp install main.py
This command installs the leave-manager
server into your Claude Desktop's configuration, making it available as a tool.
Next, open the Claude Desktop application. You may need to enable Developer Mode to see the installed tools. Once enabled, you can go to File > Settings > Developer
to see the leave-manager
tab. Clicking Edit Config
will open a JSON file where you can see the entry that the installation command added. This configuration tells Claude Desktop how to start and communicate with your MCP server using UV.
Troubleshooting Tip:
Some users may face an issue with the typer
library. If you encounter a TypeError
related to strings, running the following command should resolve it:
pip install --upgrade typer
After a successful installation, you should see the tools (get_leave_balance
, apply_for_leave
, get_leave_history
) listed in the tools section of the Claude Desktop interface.
Testing the AI HR Agent
Now you can interact with your newly built HR agent directly from Claude.
Query 1: Check Leave Balance Ask a question like:
"How many leaves are available for employee E001?"
The Claude client, powered by a large language model, intelligently maps this question to the get_leave_balance
tool and supplies E001
as the employee_id
. It will return the correct balance.
Response:
"Employee E001 has 18 days of leave remaining."
Query 2: Check Leave History You can ask a follow-up question, and the agent will understand the context.
"For the same person, let me know the exact dates when they took the leave."
Response:
"Leave history for E001: - 2024-12-25: Christmas Day - 2025-01-01: New Year's Day"
Query 3: Apply for Leave Let's try applying for leave.
"Employee ID E002 would like to apply for the 4th of July holiday. Please apply for this leave."
The agent uses the docstring from the apply_for_leave
function to understand that the date needs to be in YYYY-MM-DD
format. It correctly converts "4th of July" to 2025-07-04
and calls the tool.
Response:
"Successfully applied for 1 day(s) of leave for employee E002. Remaining balance: 19 days."
Query 4: Verify Remaining Leave Finally, let's confirm the new balance.
"How many leave days are remaining for E002?"
Response:
"Employee E002 has 19 days of leave remaining."
That's it! You have successfully built and tested your first MCP server. This example demonstrates how quickly you can create powerful, AI-driven agents for various business needs.
Join the 10xdev Community
Subscribe and get 8+ free PDFs that contain detailed roadmaps with recommended learning periods for each programming language or field, along with links to free resources such as books, YouTube tutorials, and courses with certificates.