Skip to main content
Glama
developer-ashish31

Leave Manager MCP Server

README.md
# Leave Manager MCP Server

A custom **Model Context Protocol (MCP) server** built with **TypeScript** for managing employee leave-related operations through AI clients such as **Claude Desktop**.

This project is currently designed for **internal development and testing** and uses a **dummy/in-memory database** instead of a production database.

The architecture is designed so that the dummy database can later be replaced with a real database or internal Leave Management API without changing the MCP tool interface.

---

## Table of Contents

* [Overview](#overview)
* [Features](#features)
* [Architecture](#architecture)
* [Technology Stack](#technology-stack)
* [Prerequisites](#prerequisites)
* [Installation](#installation)
* [Project Structure](#project-structure)
* [Configuration](#configuration)
* [Available MCP Tools](#available-mcp-tools)
* [Run the MCP Server](#run-the-mcp-server)
* [Build the Project](#build-the-project)
* [Run the Production Build](#run-the-production-build)
* [Test with MCP Inspector](#test-with-mcp-inspector)
* [Connect with Claude Desktop](#connect-with-claude-desktop)
* [Test Leave Manager with Claude](#test-leave-manager-with-claude)
* [Dummy Database](#dummy-database)
* [Development Workflow](#development-workflow)
* [Troubleshooting](#troubleshooting)
* [Future Enhancements](#future-enhancements)
* [Production Considerations](#production-considerations)
* [License](#license)

---

# Overview

The Leave Manager MCP Server exposes leave-management functionality as MCP tools that can be used by AI clients.

For example, instead of manually calling an API, a user can ask Claude:

> How many casual leaves do I have?

Claude can identify the appropriate MCP tool and invoke:

```text
get_leave_balance
```

The MCP server processes the request and returns structured information that Claude can use to generate a natural-language response.

### Example

```text
User
 │
 │ "How many leaves do I have?"
 ▼
Claude Desktop
 │
 │ MCP Tool Call
 ▼
Leave Manager MCP Server
 │
 ▼
Dummy Database
 │
 ▼
Leave Balance
 │
 ▼
Claude Desktop
 │
 ▼
Natural Language Response
```

---

# Features

The current version provides the following MCP tools:

* Get employee leave balance
* Get employee leave history
* Get available leave types
* Apply for leave
* Cancel leave
* Input validation using Zod
* Dummy/in-memory database
* TypeScript implementation
* stdio-based MCP transport
* MCP Inspector support
* Claude Desktop integration

---

# Architecture

The current architecture is:

```text
                    ┌──────────────────────┐
                    │    Claude Desktop    │
                    │                      │
                    │   User Interaction   │
                    └──────────┬───────────┘
                               │
                               │ MCP / stdio
                               ▼
                    ┌──────────────────────┐
                    │ Leave Manager MCP    │
                    │      Server          │
                    │                      │
                    │ MCP Tool Layer       │
                    └──────────┬───────────┘
                               │
                               ▼
                    ┌──────────────────────┐
                    │    Leave Service     │
                    │    / Repository      │
                    └──────────┬───────────┘
                               │
                               ▼
                    ┌──────────────────────┐
                    │     Dummy DB         │
                    │                      │
                    │ employees[]          │
                    │ leaveBalances[]      │
                    │ leaveRequests[]      │
                    └──────────────────────┘
```

The server uses **stdio** because Claude Desktop can launch the MCP server as a local process and communicate with it through standard input/output. The MCP TypeScript SDK provides `serveStdio()` for this use case.

---

# Technology Stack

| Technology         | Purpose                   |
| ------------------ | ------------------------- |
| TypeScript         | Application development   |
| Node.js            | Runtime                   |
| npm                | Dependency management     |
| MCP TypeScript SDK | MCP server implementation |
| Zod                | Input validation          |
| Claude Desktop     | MCP client                |
| MCP Inspector      | Local MCP testing         |
| Dummy DB           | Temporary data storage    |

The current MCP TypeScript SDK v2 is the stable SDK line and uses `@modelcontextprotocol/server`.

---

# Prerequisites

Before starting, make sure the following are installed.

## Node.js

Node.js **20 or later** is required.

Check the installed version:

```bash
node --version
```

Example:

```text
v22.9.0
```

Check npm:

```bash
npm --version
```

---

## Claude Desktop

Install Claude Desktop on your machine.

Claude Desktop will act as the MCP client and will launch the Leave Manager MCP server locally.

---

# Installation

## 1. Clone the repository

```bash
git clone <YOUR_REPOSITORY_URL>
```

Navigate into the project:

```bash
cd leave-manager-mcp
```

---

## 2. Install dependencies

Run:

```bash
npm install
```

The project uses the MCP TypeScript server package:

```bash
npm install @modelcontextprotocol/server
```

Zod is used for validating tool input:

```bash
npm install zod
```

For TypeScript development:

```bash
npm install -D typescript tsx @types/node
```

The official MCP server setup currently uses Node.js 20+, ES modules, `@modelcontextprotocol/server`, Zod, and `tsx`.

---

# Project Structure

Recommended project structure:

```text
leave-manager-mcp/
│
├── src/
│   │
│   ├── index.ts
│   │
│   ├── data/
│   │   └── dummy-db.ts
│   │
│   ├── models/
│   │   └── leave.ts
│   │
│   ├── repositories/
│   │   └── leave-repository.ts
│   │
│   └── tools/
│       └── leave-tools.ts
│
├── dist/
│
├── package.json
├── package-lock.json
├── tsconfig.json
└── README.md
```

### Responsibilities

#### `src/index.ts`

Creates and starts the MCP server.

#### `src/models/leave.ts`

Contains TypeScript models/interfaces related to employees and leave.

#### `src/data/dummy-db.ts`

Contains temporary in-memory test data.

#### `src/repositories/leave-repository.ts`

Provides data-access operations.

#### `src/tools/leave-tools.ts`

Registers MCP tools that Claude can invoke.

---

# Configuration

## package.json

A typical configuration:

```json
{
  "name": "leave-manager-mcp",
  "version": "1.0.0",
  "description": "Leave Manager MCP Server",
  "type": "module",
  "scripts": {
    "dev": "tsx src/index.ts",
    "build": "tsc",
    "start": "node dist/index.js"
  },
  "dependencies": {
    "@modelcontextprotocol/server": "^2.0.0",
    "zod": "^4.0.0"
  },
  "devDependencies": {
    "@types/node": "^24.0.0",
    "tsx": "^4.0.0",
    "typescript": "^6.0.0"
  }
}
```

> Dependency versions may differ depending on when `npm install` is executed. Always prefer the versions generated by npm.

---

# TypeScript Configuration

Create `tsconfig.json`:

```json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "types": ["node"],
    "outDir": "dist"
  },
  "include": [
    "src/**/*.ts"
  ]
}
```

The Node types entry is important with current TypeScript versions because the MCP SDK's published type definitions reference Node APIs.

---

# Available MCP Tools

The current Leave Manager MCP server exposes the following tools.

## 1. get_leave_balance

Returns the current leave balance for an employee.

### Input

```json
{
  "employeeId": "EMP001"
}
```

### Example result

```json
{
  "employeeId": "EMP001",
  "casual": 8,
  "sick": 5,
  "earned": 12,
  "unpaid": 0
}
```

---

## 2. get_leave_history

Returns the leave history for an employee.

### Input

```json
{
  "employeeId": "EMP001"
}
```

### Example result

```json
[
  {
    "id": "LR001",
    "employeeId": "EMP001",
    "leaveType": "CASUAL",
    "startDate": "2026-08-20",
    "endDate": "2026-08-21",
    "reason": "Personal work",
    "status": "APPROVED"
  }
]
```

---

## 3. get_leave_types

Returns available leave types.

### Example result

```json
[
  {
    "type": "CASUAL",
    "description": "Casual leave"
  },
  {
    "type": "SICK",
    "description": "Sick leave"
  },
  {
    "type": "EARNED",
    "description": "Earned leave"
  },
  {
    "type": "UNPAID",
    "description": "Unpaid leave"
  }
]
```

---

## 4. apply_leave

Creates a new leave request.

### Input

```json
{
  "employeeId": "EMP001",
  "leaveType": "CASUAL",
  "startDate": "2026-09-10",
  "endDate": "2026-09-11",
  "reason": "Family function"
}
```

### Example result

```json
{
  "id": "LR002",
  "employeeId": "EMP001",
  "leaveType": "CASUAL",
  "startDate": "2026-09-10",
  "endDate": "2026-09-11",
  "reason": "Family function",
  "status": "PENDING"
}
```

---

## 5. cancel_leave

Cancels an existing leave request.

### Input

```json
{
  "leaveId": "LR002"
}
```

### Example result

```json
{
  "id": "LR002",
  "status": "CANCELLED"
}
```

---

# Run the MCP Server

There are two ways to run the server during development.

---

## Option 1: Run directly with tsx

This is recommended during development.

```bash
npm run dev
```

Internally this executes:

```bash
tsx src/index.ts
```

You should see:

```text
Leave Manager MCP server running...
```

The process will continue running because an stdio MCP server waits for a client to communicate with it.

Stop the server using:

```text
Ctrl + C
```

---

# Build the Project

Before using the compiled version, run:

```bash
npm run build
```

This executes:

```bash
tsc
```

The compiled JavaScript files will be generated inside:

```text
dist/
```

Expected structure:

```text
dist/
├── index.js
├── data/
│   └── dummy-db.js
├── models/
│   └── leave.js
├── repositories/
│   └── leave-repository.js
└── tools/
    └── leave-tools.js
```

---

# Run the Production Build

After building:

```bash
npm start
```

This executes:

```bash
node dist/index.js
```

The MCP server will start using the compiled JavaScript.

---

# Test with MCP Inspector

Before connecting the server to Claude Desktop, it is recommended to test it with the MCP Inspector.

The MCP Inspector provides a local UI for connecting to an MCP server and directly invoking its tools.

## Start Inspector

From the project root:

```bash
npx @modelcontextprotocol/inspector npm run dev
```

Alternatively:

```bash
npx @modelcontextprotocol/inspector npx tsx src/index.ts
```

The Inspector will provide a browser URL.

Open that URL in your browser.

---

# Test Tools in MCP Inspector

After connecting the server, open the:

```text
Tools
```

section.

You should see:

```text
get_leave_balance
get_leave_history
get_leave_types
apply_leave
cancel_leave
```

---

## Test `get_leave_balance`

Select:

```text
get_leave_balance
```

Provide:

```json
{
  "employeeId": "EMP001"
}
```

Expected response:

```json
{
  "employeeId": "EMP001",
  "casual": 8,
  "sick": 5,
  "earned": 12,
  "unpaid": 0
}
```

---

## Test `get_leave_history`

Input:

```json
{
  "employeeId": "EMP001"
}
```

---

## Test `get_leave_types`

This tool does not require any input.

---

## Test `apply_leave`

Input:

```json
{
  "employeeId": "EMP001",
  "leaveType": "CASUAL",
  "startDate": "2026-09-10",
  "endDate": "2026-09-11",
  "reason": "Family function"
}
```

---

## Test `cancel_leave`

Input:

```json
{
  "leaveId": "LR002"
}
```

---

# Connect with Claude Desktop

Once the server works correctly in MCP Inspector, connect it to Claude Desktop.

The MCP server should be configured as a local stdio server because Claude Desktop launches the process and communicates through stdin/stdout.

---

## 1. Build the project

First run:

```bash
npm run build
```

Make sure this file exists:

```text
dist/index.js
```

---

## 2. Get the absolute project path

From the project root:

```bash
pwd
```

Example:

```text
/Users/ashish/projects/leave-manager-mcp
```

Your server path will therefore be:

```text
/Users/ashish/projects/leave-manager-mcp/dist/index.js
```

Use an **absolute path** in the Claude Desktop configuration.

---

# Claude Desktop Configuration

Add the Leave Manager MCP server to Claude Desktop's MCP configuration.

Example:

```json
{
  "mcpServers": {
    "leave-manager": {
      "command": "node",
      "args": [
        "/ABSOLUTE/PATH/TO/leave-manager-mcp/dist/index.js"
      ]
    }
  }
}
```

For example, on macOS:

```json
{
  "mcpServers": {
    "leave-manager": {
      "command": "node",
      "args": [
        "/Users/ashish/projects/leave-manager-mcp/dist/index.js"
      ]
    }
  }
}
```

> Replace the path with the actual absolute path on your machine.

---

# Important: Restart Claude Desktop

After changing the MCP configuration:

1. Save the configuration.
2. Completely quit Claude Desktop.
3. Start Claude Desktop again.
4. Open a new conversation.
5. Check the available MCP tools.

You should see the Leave Manager server and its tools.

---

# Test Leave Manager with Claude

Once connected, you don't need to manually invoke the MCP tools.

You can simply ask Claude natural-language questions.

---

## Example 1 — Leave Balance

Ask:

```text
How many leaves does EMP001 have?
```

Claude should use:

```text
get_leave_balance
```

with:

```json
{
  "employeeId": "EMP001"
}
```

---

## Example 2 — Leave History

Ask:

```text
Show me the leave history of EMP001.
```

Claude should use:

```text
get_leave_history
```

---

## Example 3 — Available Leave Types

Ask:

```text
What types of leaves are available?
```

Claude should use:

```text
get_leave_types
```

---

## Example 4 — Apply Leave

Ask:

```text
Apply casual leave for EMP001 from September 10 to September 11 because of a family function.
```

Claude should use:

```text
apply_leave
```

with the appropriate parameters.

---

## Example 5 — Cancel Leave

Ask:

```text
Cancel leave request LR002.
```

Claude should use:

```text
cancel_leave
```

---

# Dummy Database

The current implementation uses an in-memory database.

Example:

```typescript
export const employees = [
  {
    id: "EMP001",
    name: "Ashish Kushwaha",
    email: "ashish@example.com",
    department: "Engineering"
  }
];
```

Leave balance:

```typescript
export const leaveBalances = [
  {
    employeeId: "EMP001",
    casual: 8,
    sick: 5,
    earned: 12,
    unpaid: 0
  }
];
```

Leave requests:

```typescript
export const leaveRequests = [
  {
    id: "LR001",
    employeeId: "EMP001",
    leaveType: "CASUAL",
    startDate: "2026-08-20",
    endDate: "2026-08-21",
    reason: "Personal work",
    status: "APPROVED",
    createdAt: "2026-08-10"
  }
];
```

---

# Important Dummy DB Limitation

The current database is stored in application memory.

Therefore:

```text
Server starts
      ↓
Dummy data loaded
      ↓
Apply leave
      ↓
New request added
      ↓
Server stops
      ↓
Data is lost
```

This is expected.

The dummy database is only intended for development and MCP testing.

---

# Development Workflow

Recommended development workflow:

```text
1. Modify TypeScript
        ↓
2. Run npm run build
        ↓
3. Run MCP Inspector
        ↓
4. Test MCP tools
        ↓
5. Fix issues
        ↓
6. Test with Claude Desktop
        ↓
7. Commit changes
```

During development you can also use:

```bash
npm run dev
```

instead of building after every change.

---

# Logging

Because the server uses stdio, **do not use `console.log()` for normal server logging**.

Avoid:

```typescript
console.log("Server started");
```

Use:

```typescript
console.error("Server started");
```

The reason is that stdout is used by MCP for protocol communication. Writing normal logs to stdout can corrupt the JSON-RPC/MCP communication stream.

---

# Troubleshooting

## Problem: `Cannot find module`

Run:

```bash
rm -rf node_modules
rm -f package-lock.json
npm install
```

Then:

```bash
npm run build
```

---

## Problem: TypeScript build error

Run:

```bash
npx tsc --noEmit
```

This will show TypeScript errors without generating files.

---

## Problem: `dist/index.js` does not exist

Run:

```bash
npm run build
```

Then verify:

```bash
ls dist
```

---

## Problem: Claude Desktop does not show the MCP server

Check:

1. The MCP configuration is valid JSON.
2. The path to `dist/index.js` is absolute.
3. `npm run build` completed successfully.
4. `dist/index.js` exists.
5. Node.js is installed.
6. Claude Desktop was completely restarted.
7. The MCP server works in MCP Inspector.

---

## Problem: MCP Inspector cannot connect

First run:

```bash
npm run dev
```

If the server starts successfully, stop it and then run:

```bash
npx @modelcontextprotocol/inspector npm run dev
```

Check the terminal for errors.

---

## Problem: Server starts but tools are not visible

Check:

```text
src/index.ts
```

and make sure your tools are registered:

```typescript
registerLeaveTools(
  server,
  repository
);
```

Also make sure `serveStdio()` is called:

```typescript
void serveStdio(createServer);
```

---

## Problem: JSON-RPC/MCP protocol errors

Check the code for:

```typescript
console.log(...)
```

Replace normal logging with:

```typescript
console.error(...)
```

stdout must remain available for MCP protocol communication.

---

# Future Enhancements

The current version is a prototype. The following improvements are recommended.

## Database

Replace the dummy database with:

```text
PostgreSQL
MySQL
MongoDB
```

or an existing internal Leave Management API.

---

## Authentication

Add employee authentication so that the user doesn't have to provide:

```text
employeeId
```

manually.

Future architecture:

```text
Claude
   ↓
MCP Server
   ↓
Authentication
   ↓
Employee Context
   ↓
Leave Service
```

---

## Leave Validation

Add business rules:

* Validate leave dates
* Validate leave balance
* Prevent overlapping leave
* Check company holidays
* Check weekends
* Validate minimum/maximum leave duration
* Validate employee status
* Validate leave type
* Prevent cancellation after approval, if applicable

---

## Manager Approval

Add tools such as:

```text
get_pending_leave_requests
approve_leave
reject_leave
```

---

## Team Calendar

Add:

```text
get_team_leave_calendar
```

Example user request:

```text
Who from my team is on leave next week?
```

---

## Notifications

Integrate with:

```text
Email
Slack
Microsoft Teams
```

to notify employees and managers.

---

# Recommended Production Architecture

The long-term architecture should separate MCP from business logic:

```text
                    Claude Desktop
                          │
                          │ MCP
                          ▼
                ┌───────────────────┐
                │    MCP Server     │
                │                   │
                │ Tool Definitions  │
                │ Input Validation  │
                └─────────┬─────────┘
                          │
                          ▼
                ┌───────────────────┐
                │   Leave Service   │
                │                   │
                │ Business Rules    │
                │ Validation        │
                │ Authorization     │
                └─────────┬─────────┘
                          │
                          ▼
                ┌───────────────────┐
                │ Leave Repository  │
                └─────────┬─────────┘
                          │
                 ┌────────┴────────┐
                 ▼                 ▼
          Internal Leave API    Database
```

This makes it possible to replace the dummy database without changing the tools exposed to Claude.

---

# Security Considerations

The current project is intended for development/testing only.

Before using it with real employee data:

* Add authentication.
* Add authorization.
* Do not trust `employeeId` supplied by the model.
* Validate all tool inputs.
* Protect employee information.
* Avoid exposing unnecessary employee data.
* Add audit logging.
* Implement role-based access control.
* Protect manager-only operations.
* Add rate limiting where applicable.
* Do not store secrets in source code.
* Use environment variables for credentials.
* Secure connections to internal APIs/databases.

The MCP server should enforce business permissions rather than relying on Claude to make security decisions.

---

# Environment Variables

When connecting to real services, use environment variables.

Example `.env`:

```text
LEAVE_API_URL=https://internal.example.com/api
LEAVE_API_KEY=your-api-key
```

Do not commit `.env` to Git.

Add:

```text
.env
```

to `.gitignore`.

---

# Git Ignore

Recommended `.gitignore`:

```text
node_modules/
dist/
.env
.DS_Store
*.log
```

---

# Useful Commands

## Install dependencies

```bash
npm install
```

## Development

```bash
npm run dev
```

## Build

```bash
npm run build
```

## Run compiled server

```bash
npm start
```

## Type check

```bash
npx tsc --noEmit
```

## Run MCP Inspector

```bash
npx @modelcontextprotocol/inspector npm run dev
```

## Check Node version

```bash
node --version
```

## Check npm version

```bash
npm --version
```

---

# MCP Development Checklist

Before considering the MCP server ready for internal testing:

* [ ] Node.js 20+ installed
* [ ] Dependencies installed
* [ ] TypeScript build succeeds
* [ ] Dummy database configured
* [ ] MCP server starts successfully
* [ ] MCP Inspector connects successfully
* [ ] `get_leave_balance` tested
* [ ] `get_leave_history` tested
* [ ] `get_leave_types` tested
* [ ] `apply_leave` tested
* [ ] `cancel_leave` tested
* [ ] Claude Desktop configuration added
* [ ] Claude Desktop restarted
* [ ] Leave Manager tools visible in Claude
* [ ] Natural-language requests tested
* [ ] Error scenarios tested

---

# Example User Queries

Once connected to Claude Desktop, users should be able to ask questions such as:

```text
How many casual leaves do I have?
```

```text
Show my leave history.
```

```text
What leave types are available?
```

```text
Apply casual leave from September 10 to September 11.
```

```text
Cancel my leave request LR002.
```

Future examples:

```text
Do I have enough leave for next Monday?
```

```text
Who from my team is on leave next week?
```

```text
Show all pending leave requests.
```

```text
Approve Rahul's leave request.
```

---

# MCP Resources

Official MCP TypeScript SDK:

https://ts.sdk.modelcontextprotocol.io/v2/

Official first-server guide:

https://ts.sdk.modelcontextprotocol.io/v2/get-started/first-server

Official server API:

https://ts.sdk.modelcontextprotocol.io/v2/api/@modelcontextprotocol/server/

The project currently follows the MCP TypeScript SDK v2 architecture and the modern 2026-07-28 protocol line.

---

# License

This project is intended for internal development and testing.

Add your organization's license and usage policy here.

---

# Maintainer

**Ashish Kushwaha**

Leave Manager MCP Server
TypeScript + MCP + Claude Desktop

---

## Quick Start

For experienced developers, the complete setup can be summarized as:

```bash
# Clone
git clone <YOUR_REPOSITORY_URL>

# Enter project
cd leave-manager-mcp

# Install
npm install

# Build
npm run build

# Run
npm start

# Development
npm run dev

# MCP Inspector
npx @modelcontextprotocol/inspector npm run dev
```

Then configure Claude Desktop to launch:

```text
dist/index.js
```

using:

```json
{
  "mcpServers": {
    "leave-manager": {
      "command": "node",
      "args": [
        "/ABSOLUTE/PATH/TO/leave-manager-mcp/dist/index.js"
      ]
    }
  }
}
```

Restart Claude Desktop and start testing the Leave Manager MCP tools.

TDQS

B3.1/5.0

Scored across 6 tools

Disambiguation4/5

The tools are mostly distinct: balance, history, types, apply, cancel, and employee details each target a clear purpose. The only mild overlap is between leave balance and leave history, but their intent is sufficiently separated.

Naming Consistency4/5

Most tools follow a get_/apply_/cancel_ pattern with snake_case. The outlier is get_employee_details_by_employeeId which mixes an 'employeeId' camelCase segment into an otherwise snake_case name, causing a minor inconsistency.

Tool Count5/5

Six tools is well-scoped for a leave management server. Each tool covers an essential function without unnecessary bloat or significant redundancy.

Completeness3/5

The core employee self-service workflow is covered: view balance, history, types, apply, and cancel. Missing tools for approval/rejection or checking pending leave requests create notable gaps for a 'manager' context.

Maintenance

ActivitySlowing
ResponsivenessNo issues