MCP Integration Guide

Connect external tools and automate recruiting workflows via the Model Context Protocol gateway.

1. Gateway Overview

Goal: Understand what the MCP gateway provides, how it communicates, and the limits that apply to every request.

What is MCP?

The Model Context Protocol (MCP) is an open standard that lets AI models call server-side tools over a lightweight HTTP transport. Applyer exposes a Streamable HTTP endpoint that any MCP-compatible client can connect to - including LLM agent frameworks, custom scripts, and ATS platforms.

Base URL

https://mcp.applyer.io/sse

All tool calls are sent as JSON-RPC messages to this single endpoint over Streamable HTTP (server-sent events for responses).

Rate Limits

  • Per-key hourly - each API key is limited to a fixed number of requests per rolling hour. Exceeding the limit returns HTTP 429.
  • Per-tenant daily - the tenant as a whole has a daily request cap across all keys. This prevents runaway automation from consuming the entire budget.
Tip: The gateway also logs every tool call for audit purposes. Tenant super users can review the audit trail from the admin panel.
Screenshot: mcp-gateway-overview.png

2. Available Tools

Goal: Know which tools the gateway exposes, what parameters they accept, and what each one returns.

search_candidates

Search for anonymized candidate profiles by skills, experience, and location. Returns matching candidates without identifying information.

Parameters

skills

Type: string[]

Required: Yes

Skills to search for (e.g. ["React", "TypeScript"])

min_experience

Type: integer

Required: No

Minimum number of positions held (proxy for seniority). Min 0.

location

Type: string

Required: No

Location filter - partial match (e.g. "Tel Aviv")

limit

Type: integer

Required: No

Max results to return (1-50, default 20)

Response shape

Returns a list of anonymized candidates, each containing:

  • anonymous_id - opaque identifier (use with unlock_candidate)
  • skill_list - string[] of matched skills
  • experience_range - seniority bracket
  • education_level - highest education level
  • desired_role - candidate's target role
  • match_score - numeric relevance score
  • match_explanation - human-readable explanation of the match

unlock_candidate

Unlock a candidate's full profile including contact information. Requires an active tenant subscription. Idempotent - re-unlocking the same candidate is free.

Parameters

candidate_anonymous_id

Type: string

Required: Yes

The anonymous ID from search_candidates results

Response shape

Returns the candidate's full profile:

  • name - full name
  • email - contact email
  • phone - phone number
  • linkedin_url - LinkedIn profile URL
  • github_url - GitHub profile URL
  • desired_role - target role
  • skills - string[] of extracted skills
Screenshot: mcp-available-tools.png

3. Authentication

Goal: Generate an API key, configure your client, and follow security best practices to keep your integration safe.

Steps

  1. Generate an API key - Only tenant super users can create MCP API keys. Navigate to your tenant settings and select "API Keys" to generate a new key. Copy it immediately - it will not be shown again.
  2. Set the Authorization header - Every request must include the key in the HTTP header:
Authorization: Bearer YOUR_API_KEY
  1. Rotate keys regularly - Create a new key, update your integration, then revoke the old key. This ensures zero downtime during rotation.
  2. Never expose keys in client-side code - API keys should only be used in server-side code or secure environments. Never embed them in browser JavaScript, mobile apps, or public repositories.
Tip: Store your API key in an environment variable (e.g. APPLYER_MCP_KEY) and reference it from your server-side code. Never hard-code keys in source files.
Screenshot: mcp-authentication.png

4a. Use Case - ATS Integration

Goal: Connect your Applicant Tracking System to search Applyer candidates and import matching profiles directly into your hiring pipeline.

Steps

  1. Search for candidates matching the open role - Call search_candidates with the skills and location from your job requisition.
  2. Review anonymous results - Evaluate match_score and match_explanation to shortlist candidates before unlocking.
  3. Unlock selected candidates - Call unlock_candidate for each shortlisted profile to retrieve contact details.
  4. Import into your ATS - Map the returned fields (name, email, phone, LinkedIn) to your ATS candidate record and create the entry.

Example - TypeScript

import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";

const transport = new StreamableHTTPClientTransport(
  new URL("https://mcp.applyer.io/sse"),
  { headers: { Authorization: "Bearer YOUR_API_KEY" } }
);

const client = new Client({ name: "my-ats", version: "1.0.0" });
await client.connect(transport);

// Step 1: Search for candidates
const searchResult = await client.callTool({
  name: "search_candidates",
  arguments: {
    skills: ["React", "TypeScript", "Node.js"],
    location: "Tel Aviv",
    min_experience: 3,
    limit: 10,
  },
});
console.log("Search results:", searchResult.content);

// Step 2: Unlock a top candidate
const unlockResult = await client.callTool({
  name: "unlock_candidate",
  arguments: {
    candidate_anonymous_id: "ANONYMOUS_ID_FROM_SEARCH",
  },
});
console.log("Unlocked profile:", unlockResult.content);

Example - curl

# Search for React developers in Tel Aviv
curl -X POST https://mcp.applyer.io/sse \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
      "name": "search_candidates",
      "arguments": {
        "skills": ["React", "TypeScript"],
        "location": "Tel Aviv",
        "limit": 5
      }
    }
  }'
Tip: Set up a polling schedule (e.g. daily) to search for new candidates matching your open requisitions. Compare anonymous IDs against previously seen results to detect new matches.
Screenshot: mcp-ats-integration.png

4c. Use Case - Analytics Export

Goal: Pull search impression and candidate unlock statistics from the gateway audit log to feed your internal reporting and dashboards.

Steps

  1. Review audit logs - Every search_candidates and unlock_candidate call is logged with a timestamp, tenant ID, key ID, and result metadata. Tenant super users can access these logs from the admin panel.
  2. Track search impressions - Each search logs a query hash, the number of results returned, and the latency in milliseconds. Use this to measure which skill sets have the deepest candidate pools.
  3. Track unlocks - Each unlock logs the anonymous ID and tenant details. Track unlock volume over time to measure conversion from search to outreach.
  4. Export from the admin panel - Tenant super users can view and export analytics data (JSON or CSV) directly from the admin panel. Navigate to your tenant dashboard and select the MCP analytics section.

Accessing analytics

Analytics are available through the Applyer admin panel - not via a separate REST API. The admin panel displays:

  • Total searches and unique query hashes per period
  • Total unlocks and unique candidates unlocked
  • Top searched skill combinations
  • Per-key usage breakdown
  • Latency percentiles for search calls

Use the export button in the admin panel to download data as JSON or CSV for ingestion into BI tools like Metabase, Looker, or spreadsheets.

Example - client-side tracking

You can also build your own analytics by tracking MCP tool call results in your integration code:

// Track search and unlock metrics in your own system
interface McpMetrics {
  searches: number;
  unlocks: number;
  candidatesSeen: Set<string>;
}

const metrics: McpMetrics = {
  searches: 0,
  unlocks: 0,
  candidatesSeen: new Set(),
};

// After each search call
const searchResult = await client.callTool({
  name: "search_candidates",
  arguments: { skills: ["React", "TypeScript"], limit: 20 },
});
metrics.searches += 1;

// After each unlock call
const unlockResult = await client.callTool({
  name: "unlock_candidate",
  arguments: { candidate_anonymous_id: "ANONYMOUS_ID" },
});
metrics.unlocks += 1;
metrics.candidatesSeen.add("ANONYMOUS_ID");

// Compute conversion rate
const conversionRate = metrics.searches > 0
  ? ((metrics.unlocks / metrics.searches) * 100).toFixed(1) + "%"
  : "0%";

console.log("Searches:", metrics.searches);
console.log("Unlocks:", metrics.unlocks);
console.log("Unique candidates:", metrics.candidatesSeen.size);
console.log("Conversion rate:", conversionRate);
Tip: Schedule a weekly export script to track trends over time. Comparing search volume to unlock volume gives you a clear conversion funnel for your sourcing pipeline.
Screenshot: mcp-analytics-export.png