Skip to main content
Glama

hrmcp-server

A source-available MCP server for HR and recruiting workflows. Scores candidates against job descriptions using Claude, returns structured dimension scores, strengths, and gaps. Any agent framework that speaks MCP can call it natively.

Hosted API — use it without running anything: recruitapi.app Self-host — deploy to Railway in under 15 minutes (see below)


Endpoints

POST /score-candidate

Score a candidate's resume against a job description.

Request

{
  "resume_text": "...",
  "job_description": "...",
  "weights": {
    "skills_match": 0.40,
    "experience": 0.30,
    "industry_background": 0.20,
    "education": 0.10
  },
  "recency_window_years": 10
}

Field

Type

Required

Default

resume_text

string

yes

job_description

string

yes

weights

object

no

{skills_match: 0.40, experience: 0.30, industry_background: 0.20, education: 0.10}

recency_window_years

integer > 0

no

10

Weights must sum to 1.0. Each value must be between 0.0 and 1.0. Both text fields max out at 15,000 characters. Resume must be at least 50 words.

Response — 200

{
  "overall_score": 82,
  "dimension_scores": {
    "skills_match": 88,
    "experience": 85,
    "industry_background": 74,
    "education": 70
  },
  "strengths": [
    "Five years of hands-on Python in production ML pipelines",
    "Led cross-functional team during platform migration"
  ],
  "gaps": [
    "No experience with Kubernetes",
    "MBA preferred; candidate holds a BS"
  ],
  "recency_window_used": 10,
  "model": "claude-sonnet-4-20250514",
  "warnings": []
}

All scores are integers 0–100. strengths and gaps are 2–4 strings each, grounded in the resume and job description — not generic observations.

Idempotency

Pass an Idempotency-Key header to cache the response for 24 hours. A retry with the same key returns the cached response without calling the model or deducting a credit.

Idempotency-Key: req_01J8XYZ

GET /health

{ "status": "ok", "model": "claude-sonnet-4-20250514" }

Authentication

Every request to /score-candidate requires an API key. Pass it either way:

X-API-Key: hrmcp_sk_...
Authorization: Bearer hrmcp_sk_...

Keys are issued after a credit purchase. Get one at hrmcp-server-production.up.railway.app/billing.


Rate limits

Limits apply per API key on a rolling window — not a fixed clock boundary.

Limit

Default

Per minute

30 requests

Per day

500 requests

Concurrent

5 in-flight

Every response includes current limit state:

X-RateLimit-Limit-Minute: 30
X-RateLimit-Remaining-Minute: 28
X-RateLimit-Reset-Minute: 1712000060
X-RateLimit-Limit-Day: 500
X-RateLimit-Remaining-Day: 497
X-RateLimit-Reset-Day: 1712041234

Self-hosted deployments can disable rate limiting entirely with RATE_LIMIT_ENABLED=false.


Credits

Each successful call to /score-candidate deducts one credit. Credits are purchased in bundles of 100 for $5 and expire after 180 days.

Status

Code

Meaning

402

credits_exhausted

Balance is zero

402

credits_expired

Credits exist but the bundle has expired


Error format

All errors use the same envelope:

{
  "error": {
    "code": "missing_required_field",
    "message": "One or more required fields are missing.",
    "detail": { "missing_fields": ["resume_text"] }
  }
}

Code

Status

Description

unauthorized

401

Missing, invalid, or revoked API key

rate_limit_exceeded

429

Rolling window limit hit; see Retry-After header

credits_exhausted

402

No credits remaining

credits_expired

402

Credits have passed their expiry date

missing_required_field

400

resume_text or job_description absent

resume_too_short

400

Resume under 50 words

payload_too_large

400

Input exceeds 15,000 characters

weights_invalid_sum

400

Weights do not sum to 1.0

weights_missing_keys

400

One or more weight keys absent

weights_negative_value

400

Weight value outside 0.0–1.0

recency_window_invalid

400

recency_window_years is not a positive integer

idempotency_key_invalid

400

Idempotency-Key header value is invalid

model_unavailable

503

Anthropic API timeout or outage

response_parse_failure

500

Model returned unparseable output

Warnings are non-fatal and appear alongside a 200 response:

Code

Trigger

non_english_detected

Non-Latin characters in resume or JD

job_description_thin

JD under 30 words


Self-hosting

Deploy to Railway

Deploy on Railway

  1. Click the button above — Railway clones the repo and provisions a Postgres service

  2. Add the five required environment variables (see below)

  3. Register POST /webhooks/stripe in your Stripe dashboard; paste the signing secret into STRIPE_WEBHOOK_SECRET

  4. Watch the deploy log for db_migrated and server_started

  5. Hit /health to confirm

Run locally

git clone https://github.com/Spaceghost99/hrmcp-server.git
cd hrmcp-server
npm install
cp .env.example .env
# Fill in ANTHROPIC_API_KEY at minimum
npm run dev

Scoring works without DATABASE_URL. Auth and billing require Postgres.


Environment variables

Five variables are required and will crash the server on startup if missing.

Variable

Required

Default

Description

ANTHROPIC_API_KEY

yes

Anthropic API key

DATABASE_URL

prod only

PostgreSQL connection string (Railway provides this)

STRIPE_SECRET_KEY

prod only

Stripe secret key (sk_test_... or sk_live_...)

STRIPE_WEBHOOK_SECRET

prod only

Stripe webhook signing secret (whsec_...)

PORT

no

3000

Railway sets this automatically

NODE_ENV

no

development

Set to production on Railway

ANTHROPIC_MODEL

no

claude-sonnet-4-20250514

Model for scoring

ANTHROPIC_TIMEOUT_MS

no

25000

Anthropic API timeout in ms

BCRYPT_ROUNDS

no

10

bcrypt cost factor for key hashing

RATE_LIMIT_ENABLED

no

true

Set false to disable rate limiting

RATE_LIMIT_PER_MINUTE

no

30

Rolling per-minute limit per key

RATE_LIMIT_PER_DAY

no

500

Rolling per-day limit per key

RATE_LIMIT_CONCURRENT

no

5

Max in-flight requests per key

MAX_RESUME_CHARS

no

15000

Resume character limit

MAX_JD_CHARS

no

15000

Job description character limit

STRIPE_PRICE_LOOKUP_KEY

no

credits_100

Stripe price lookup key

CREDITS_BUNDLE_SIZE

no

100

Credits per purchase

CREDITS_EXPIRY_DAYS

no

180

Days before credits expire

LOG_LEVEL

no

info

info or error

IDEMPOTENCY_TTL_SECONDS

no

86400

Idempotency cache TTL in seconds

APP_URL

no

http://localhost:3000

Public base URL; used in billing links

See .env.example for descriptions of every variable.


Architecture

src/
  index.ts                  — HTTP server, request routing, middleware wiring
  config.ts                 — Environment variable loading
  middleware/
    auth.ts                 — API key extraction and validation
    rateLimit.ts            — Rolling window rate limiter (in-memory)
    logger.ts               — Structured JSON logging
  billing/
    keys.ts                 — Key generation, hashing, verification (pure functions)
    db.ts                   — PostgreSQL pool, schema migration, all queries
    stripe.ts               — Checkout sessions, webhook handler, credit lifecycle
  tools/
    score-candidate/
      handler.ts            — Input validation, orchestration
      scorer.ts             — Anthropic API call, response parsing
      schema.ts             — Zod schemas and default weights
      prompt.ts             — System prompt and user prompt builder
  errors/
    codes.ts                — Error code constants
    envelope.ts             — createError / createWarning helpers

Request flow for POST /score-candidate:

  1. Auth — extract key, SHA-256 lookup, bcrypt verify

  2. Rate limit — check rolling minute/day/concurrent windows

  3. Parse + validate body

  4. Idempotency — return cached response if key matches

  5. Deduct credit — atomic SELECT FOR UPDATE in Postgres

  6. Score — call Anthropic, parse and validate response

  7. Cache response if idempotency key present

  8. Apply X-RateLimit-* headers, send response

  9. Release concurrent slot, write request log line


Alternatives

Other hosted candidate-scoring options exist. hrmcp-server is source-available, self-hostable, and speaks MCP natively — no wrapper required for agent frameworks that support the protocol.


License

Licensed under the Elastic License 2.0. Free to use, self-host, and modify. You may not offer the software to third parties as a hosted or managed service. For commercial hosting inquiries contact aaron@recruitapi.app.

-
security - not tested
F
license - not found
-
quality - not tested

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Spaceghost99/hrmcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server