Podcast Title

Author Name

0:00
0:00
Album Art

Build an AI HR Agent: Your First MCP Server Explained in 10 Minutes

By 10xdev team August 17, 2025

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. To interact with our server, we'll use a generic MCP client. While a custom internal chatbot would be ideal, for this tutorial, we will use the Claude Desktop client to keep things simple. This client will make calls to the MCP server we are building.

Getting Started: Prerequisites and Installation

Before we begin, you'll need to install a couple of things.

  1. MCP Client: Install an MCP-compatible client. We'll use Claude Desktop for this guide. You can find the installer for your operating system with a quick web search.
  2. MCP Python SDK: Install the official Python SDK by running the following command in your terminal: bash pip install mcp
  3. UV (Python Package Manager): We will use UV to set up our project. Install it via pip: bash pip install uv On Windows, you can also use this command in the command prompt: powershell powershell -c "irm https://github.com/astral-sh/uv/releases/latest/download/uv-installer.ps1 | iex"

Setting Up Your Project with UV

Once UV is installed, navigate to your development directory and initialize the project.

uv init my-first-mcp-server

This command creates a new directory named my-first-mcp-server with a basic project skeleton. If you open this directory in your code editor, you will see the following structure:

  • main.py
  • pyproject.toml
  • README.md

Crafting the HR Agent Server

The core of our project is the MCP server logic. While you can find basic examples on the official MCP project page, we can accelerate development by using an AI assistant like Chat GPT to generate the code for our specific leave management use case.

After some prompting and refinement, here is the complete server code. Copy and paste this into your main.py file.

from fastmcp import FastMCP

# Mock database for employee leave information
mock_employee_data = {
    "E001": {
        "balance": 18,
        "history": [
            {"date": "2024-12-25", "reason": "Christmas Day"},
            {"date": "2025-01-01", "reason": "New Year's Day"},
        ],
    },
    "E002": {"balance": 20, "history": []},
}

# Initialize the MCP server
server = FastMCP(
    "leave-manager",
    title="Leave Management Server",
    description="A server for managing 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').
    :return: A string stating the employee's remaining leave balance.
    """
    employee = mock_employee_data.get(employee_id)
    if employee:
        return f"Employee {employee_id} has {employee['balance']} days of leave left."
    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 period in 'YYYY-MM-DD' format.
    :param reason: The reason for the leave request.
    :return: A confirmation message indicating the leave has been applied.
    """
    employee = mock_employee_data.get(employee_id)
    if not employee:
        return f"Employee {employee_id} not found."

    num_leave_days = len(leave_dates)
    if employee["balance"] >= num_leave_days:
        employee["balance"] -= num_leave_days
        for date in leave_dates:
            employee["history"].append({"date": date, "reason": reason})
        return f"Successfully applied for {num_leave_days} day(s) of leave for employee {employee_id}."
    else:
        return f"Error: Insufficient leave balance for employee {employee_id}."

@server.tool()
def get_leave_history(employee_id: str) -> list:
    """
    Retrieves the leave history for a given employee.

    :param employee_id: The unique identifier for the employee.
    :return: A list of dictionaries, each containing leave date and reason.
    """
    employee = mock_employee_data.get(employee_id)
    if employee:
        return employee["history"]
    return []

@server.resource()
def greeting() -> str:
    """A simple greeting resource."""
    return "Hello! I am the HR Leave Assistant. How can I help you today?"

Note on Docstrings: The docstrings for each tool are critical. They guide the MCP client's LLM, helping it understand what each function does and how to call it correctly with the right parameters.

Connecting the Server to Your Client

With the server code ready, run the following command in your project directory to register it with your MCP client:

uv mcp install main.py

This command installs the leave-manager server into your Claude Desktop configuration.

To ensure the client can see your local server, you may need to enable Developer Mode. This option is usually found in the client's settings. Once enabled, you can navigate to File > Settings > Developer. You should see a leave-manager tab. Clicking "Edit Config" will open a JSON file containing the server's configuration, which was added by the uv mcp install command.

The configuration tells the client that a server named leave-manager exists and can be started using the uv command.

A Note on Potential Issues If you encounter a TypeError related to the typer library during installation, running an upgrade should resolve it: bash pip install --upgrade typer After a successful installation, the tools (get_leave_balance, apply_for_leave, get_leave_history) will be visible in your client's interface.

Putting Your HR Agent to the Test

Now, let's interact with our new HR agent.

Query 1: Check Leave Balance You can ask a natural language question:

You: How many leaves are available for employee E001?

The client's LLM is smart enough to map this question to the get_leave_balance tool and supply E001 as the employee_id.

Agent: Employee E001 has 18 days of leave left.

Query 2: Check Leave History The agent maintains context. You can ask a follow-up question:

You: For the same person, let me know the exact dates when they took the leave.

Agent: They took a leave on Christmas Day (2024-12-25) and New Year's Day (2025-01-01).

Query 3: Apply for Leave Let's try applying for leave. The LLM can parse complex requests, including dates.

You: Employee ID E002 would like to apply for the 4th of July holiday. Please apply for this leave.

The agent correctly identifies the apply_for_leave function. It parses "4th of July" into the required YYYY-MM-DD format specified in the docstring.

Agent: Successfully applied for 1 day(s) of leave for employee E002.

Query 4: Verify the Change Finally, let's confirm the leave was deducted.

You: How many leave days are remaining for E002?

Agent: It has 19 days leave.

That's it! You have successfully built and tested your first MCP server. Feel free to experiment further with this code.

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.

Recommended For You

Up Next