AI candidate scoring via MCP. Score resumes against job descriptions with Claude — returns dimension scores, strengths, and gaps.

Created By
Spaceghost992 months ago
hrmcp-server is an MCP-native server for HR and recruiting workflows. Send a resume and job description, get back structured scores across four dimensions (skills match, experience, industry background, education), plus specific strengths and gaps grounded in the actual content. Customizable scoring weights. Hosted API available at recruitapi.app — $5 per 100 scores. Self-hostable on Railway in under 15 minutes.
Overview

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
}
FieldTypeRequiredDefault
resume_textstringyes
job_descriptionstringyes
weightsobjectno{skills_match: 0.40, experience: 0.30, industry_background: 0.20, education: 0.10}
recency_window_yearsinteger > 0no10

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.

LimitDefault
Per minute30 requests
Per day500 requests
Concurrent5 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.

StatusCodeMeaning
402credits_exhaustedBalance is zero
402credits_expiredCredits 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"] }
  }
}
CodeStatusDescription
unauthorized401Missing, invalid, or revoked API key
rate_limit_exceeded429Rolling window limit hit; see Retry-After header
credits_exhausted402No credits remaining
credits_expired402Credits have passed their expiry date
missing_required_field400resume_text or job_description absent
resume_too_short400Resume under 50 words
payload_too_large400Input exceeds 15,000 characters
weights_invalid_sum400Weights do not sum to 1.0
weights_missing_keys400One or more weight keys absent
weights_negative_value400Weight value outside 0.0–1.0
recency_window_invalid400recency_window_years is not a positive integer
idempotency_key_invalid400Idempotency-Key header value is invalid
model_unavailable503Anthropic API timeout or outage
response_parse_failure500Model returned unparseable output

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

CodeTrigger
non_english_detectedNon-Latin characters in resume or JD
job_description_thinJD 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.

VariableRequiredDefaultDescription
ANTHROPIC_API_KEYyesAnthropic API key
DATABASE_URLprod onlyPostgreSQL connection string (Railway provides this)
STRIPE_SECRET_KEYprod onlyStripe secret key (sk_test_... or sk_live_...)
STRIPE_WEBHOOK_SECRETprod onlyStripe webhook signing secret (whsec_...)
PORTno3000Railway sets this automatically
NODE_ENVnodevelopmentSet to production on Railway
ANTHROPIC_MODELnoclaude-sonnet-4-20250514Model for scoring
ANTHROPIC_TIMEOUT_MSno25000Anthropic API timeout in ms
BCRYPT_ROUNDSno10bcrypt cost factor for key hashing
RATE_LIMIT_ENABLEDnotrueSet false to disable rate limiting
RATE_LIMIT_PER_MINUTEno30Rolling per-minute limit per key
RATE_LIMIT_PER_DAYno500Rolling per-day limit per key
RATE_LIMIT_CONCURRENTno5Max in-flight requests per key
MAX_RESUME_CHARSno15000Resume character limit
MAX_JD_CHARSno15000Job description character limit
STRIPE_PRICE_LOOKUP_KEYnocredits_100Stripe price lookup key
CREDITS_BUNDLE_SIZEno100Credits per purchase
CREDITS_EXPIRY_DAYSno180Days before credits expire
LOG_LEVELnoinfoinfo or error
IDEMPOTENCY_TTL_SECONDSno86400Idempotency cache TTL in seconds
APP_URLnohttp://localhost:3000Public 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.

Project Info
Created At
2 months ago
Updated At
2 months ago
Author Name
Spaceghost99
Star
-
Language
-
License
-
Category

Recommend Servers

View All
Tavily Mcp
@tavily-ai

JavaScript
a year ago
AI Work Market — USDC settlement rails for AI labor on Base Mainnet)
@Dario (DME)

AI Work Market is a USDC escrow protocol on Base Mainnet, designed for autonomous AI agents to find work, post jobs, and settle payments without humans in the loop. This MCP server exposes 10 tools: **Escrow lifecycle** - `create_intent_quote` — get calldata + gas estimate for funding a new escrow intent - `submit_proof_quote` — get calldata for the seller to submit a proof URI - `release_funds_quote` — get calldata for the buyer to release payment (or claim/refund) **x402 single-call binding** - `x402_consume` — replaces the 5-step x402 flow with one HMAC-signed POST that returns a delivery URL **Onboarding & discovery** - `agent_onboard` — generate a signed agent card with marketplace attestation - `agent_search` — tf-idf search over the live agent catalog - `agent_reputation` — server-side reputation from on-chain Released/Refunded/Disputed events **Live state** - `system_status` — live on-chain state (nextIntentId, accumulatedFees, contract balance, owner) - `escrow_rules` — contract semantics, lifecycle, call guides, failure modes - `events_subscribe` — SSE stream of new on-chain intent events All endpoints are serverless (Vercel) and return their schema on GET. No browser, no wallet UI required for an agent to integrate. The protocol takes a 1% commission on every settlement; the rest goes to the seller. The full AgentCard is at `/.well-known/agent-card.json` (A2A-compatible). The OpenAPI 3.0.3 spec is at `/.well-known/openapi.json` with `components.securitySchemes` (none, hmacX402). `robots.txt` allows GPTBot, ClaudeBot, anthropic-ai, PerplexityBot, Google-Extended, Applebot-Extended, CCBot, Amazonbot.

17 hours ago
Voyei

7 hours ago