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/ folder:
- docs/RAILWAY_README.md - Deploy to Railway.com (3 steps) 🚀
- docs/DOCKER_QUICK_START.md - Run locally with Docker 🐳
- docs/README_INTEGRATION.md - Use the deployed server 🔌
- docs/CLAUDE.md - Developer guide & architecture 💻
- 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
# 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)
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
# Endpoint
http://localhost:8001/mcp
# Authorization
Authorization: Bearer <okta_access_token>
Via Okta MCP Adapter Gateway
# 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
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
Docker (Local Development) 🐳
Run locally with Docker - full control, testing
- 📖 Guide: docs/DOCKER_QUICK_START.md
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 for complete troubleshooting guide.
Quick fixes:
- Token validation fails: Verify
OKTA_DOMAINandOKTA_AUTHORIZATION_SERVER_IDin.env - Port already in use: Change port in startup command:
python main.py --http 8002 - Missing environment variables: Copy
.envexample 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 for complete documentation guide.
Testing
# 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/ folder:
- Getting Started - Documentation index
- Deploy to Railway - Cloud deployment guide
- Run with Docker - Local development
- Integration Guide - How to use the server
- Developer Guide - Architecture & development
References
Status
⚠️ Unofficial Prototype - For evaluation and testing only. Not for production use.
License: Apache 2.0