Skip to main content
Glama
README.md
# HR System MCP Server

An unofficial prototype MCP server providing HR system functionality with **Okta token validation**. For evaluation and testing purposes only.

## šŸ“š Documentation

**Complete documentation available in the [`docs/`](docs/) folder:**

- **[docs/RAILWAY_README.md](docs/RAILWAY_README.md)** - Deploy to Railway.com (3 steps) šŸš€
- **[docs/DOCKER_QUICK_START.md](docs/DOCKER_QUICK_START.md)** - Run locally with Docker 🐳
- **[docs/README_INTEGRATION.md](docs/README_INTEGRATION.md)** - Use the deployed server šŸ”Œ
- **[docs/CLAUDE.md](docs/CLAUDE.md)** - Developer guide & architecture šŸ’»
- **[docs/INDEX.md](docs/INDEX.md)** - Complete documentation index šŸ“–

## Overview

The HR System MCP Server provides:

- āœ… Employee information lookup
- āœ… Employee directory listing
- āœ… Payroll information access
- āœ… Time-off request management
- āœ… **Okta OAuth 2.0 token validation** for all tool calls
- āœ… HTTP/NDJSON streaming support (FastMCP)
- āœ… **Ready for Railway deployment** šŸš€

## Authentication

This server validates Okta access tokens for all tool calls (except `initialize`):

- **Token Source**: Okta authorization server
- **Validation**: JWT signature, expiration, audience claims
- **Authorization Header**: `Authorization: Bearer <access_token>`

## Quick Start

```bash
# Setup
cp env.example .env
# Edit .env with your Okta credentials

# Install dependencies
pip install -r requirements.txt

# Run in HTTP mode (for Okta MCP Adapter)
python main.py --http 8001
```

## Configuration

### .env (Environment Variables)

```bash
OKTA_DOMAIN=ijtestcustom.oktapreview.com
OKTA_AUTHORIZATION_SERVER_ID=auss2fth0mcIXHzVO1d7
OKTA_AUDIENCE=
OKTA_REQUIRED_SCOPES=
# When true (default), tools/list without auth returns 401. When false, allows unauthenticated tools/list (e.g. for gateway registration).
# PROTECTED_DISCOVERY=true
```

### Available Tools

| Tool                    | Description           | Parameters                    |
| ----------------------- | --------------------- | ----------------------------- |
| `get_employee`          | Get employee by ID    | `employee_id: str`            |
| `list_employees`        | List all employees    | None                          |
| `get_employee_payroll`  | Get payroll info      | `employee_id: str`            |
| `get_time_off_requests` | Get time-off requests | `employee_id: str (optional)` |

## Usage Examples

### Direct via VS Code/Copilot

```bash
# Endpoint
http://localhost:8001/mcp

# Authorization
Authorization: Bearer <okta_access_token>
```

### Via Okta MCP Adapter Gateway

```bash
# Gateway will:
# 1. Receive request from client
# 2. Validate Okta token
# 3. Forward to HR System MCP
# 4. Attach authorization header
```

## Implementation Details

- **Framework**: FastMCP 3.0.0b1
- **Server**: Uvicorn (async HTTP)
- **Protocol**: MCP (Model Context Protocol) with NDJSON streaming
- **Token Validation**: JWKS-based JWT validation with signature verification
- **Caching**: JWKS keys cached with TTL

## Request Flow

```
Client Request
    ↓
Authorization Header (Okta token)
    ↓
Initialize (no token needed)
    ↓
tools/list (validate token)
    ↓
tools/call (validate token)
    ↓
Response
```

## šŸš€ Deployment Options

### Vercel (Serverless) ⚔
Deploy as serverless function - automatic scaling, pay-per-use
- āœ… **Best for**: Sporadic usage, automatic scale-to-zero
- āœ… **Free tier**: 100GB bandwidth/month
- āš ļø **Constraint**: 10-second timeout (free), 5-min (Pro)
- šŸ“– **Guide**: **[docs/VERCEL_README.md](docs/VERCEL_README.md)**

### Railway.com (Traditional Server) šŸš‚
Deploy as long-running server - always-on, unlimited timeout
- āœ… **Best for**: Constant traffic, persistent connections
- āœ… **Free tier**: 500 hours/month ($5/month after)
- āœ… **No timeout**: Unlimited request duration
- šŸ“– **Guide**: **[docs/RAILWAY_README.md](docs/RAILWAY_README.md)**

### Docker (Local Development) 🐳
Run locally with Docker - full control, testing
- šŸ“– **Guide**: **[docs/DOCKER_QUICK_START.md](docs/DOCKER_QUICK_START.md)**

```bash
docker-compose up -d
```

**Recommendation**:
- Use **Vercel** for sporadic/unpredictable usage (cheaper, auto-scales)
- Use **Railway** for constant traffic or if you need long timeouts

## Troubleshooting

See **[docs/RAILWAY_DEPLOYMENT.md](docs/RAILWAY_DEPLOYMENT.md#troubleshooting)** for complete troubleshooting guide.

**Quick fixes:**
- **Token validation fails**: Verify `OKTA_DOMAIN` and `OKTA_AUTHORIZATION_SERVER_ID` in `.env`
- **Port already in use**: Change port in startup command: `python main.py --http 8002`
- **Missing environment variables**: Copy `.env` example and fill in values
- **JWKS fetch error**: Verify Okta domain and authorization server ID are correct

## Project Structure

```
hr-mcp-server/
ā”œā”€ā”€ main.py                    # FastMCP server with HTTP handler
ā”œā”€ā”€ requirements.txt           # Python dependencies
ā”œā”€ā”€ Dockerfile                 # Docker container definition
ā”œā”€ā”€ docker-compose.yml         # Docker Compose configuration
ā”œā”€ā”€ railway.json               # Railway deployment config
ā”œā”€ā”€ deploy-railway.sh          # Deployment helper script
ā”œā”€ā”€ test_server.sh            # Server test script
ā”œā”€ā”€ auth/                      # Authentication module
│   ā”œā”€ā”€ __init__.py
│   └── okta_validator.py     # Okta token validation
└── docs/                      # Documentation
    ā”œā”€ā”€ INDEX.md              # Documentation index
    ā”œā”€ā”€ RAILWAY_README.md     # Railway quick start
    ā”œā”€ā”€ RAILWAY_DEPLOYMENT.md # Complete deployment guide
    ā”œā”€ā”€ DOCKER_QUICK_START.md # Docker reference
    ā”œā”€ā”€ README_INTEGRATION.md # Usage guide
    ā”œā”€ā”€ CLAUDE_CODE_SETUP.md  # Claude Code setup
    ā”œā”€ā”€ CLAUDE.md             # Developer documentation
    └── ...more docs
```

See **[docs/INDEX.md](docs/INDEX.md)** for complete documentation guide.

## Testing

```bash
# Using curl with Okta token
curl -X POST http://localhost:8001/mcp \
  -H "Authorization: Bearer <your_okta_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/list",
    "params": {}
  }'
```

## šŸ“– Documentation

For complete documentation, see the **[docs/](docs/)** folder:

- **[Getting Started](docs/INDEX.md)** - Documentation index
- **[Deploy to Railway](docs/RAILWAY_README.md)** - Cloud deployment guide
- **[Run with Docker](docs/DOCKER_QUICK_START.md)** - Local development
- **[Integration Guide](docs/README_INTEGRATION.md)** - How to use the server
- **[Developer Guide](docs/CLAUDE.md)** - Architecture & development

## References

- [MCP Specification](https://modelcontextprotocol.io/)
- [FastMCP Documentation](https://gofastmcp.com/)
- [Okta Developer Docs](https://developer.okta.com/)
- [Railway Documentation](https://docs.railway.app/)

## Status

āš ļø **Unofficial Prototype** - For evaluation and testing only. Not for production use.

License: Apache 2.0