Connect SmartRecruiters to Claude: Track Applications and Offers
Learn how to connect SmartRecruiters to Claude using a managed MCP server. This guide covers bypassing API quirks, handling status transitions, and automating hiring workflows.
If your talent acquisition team needs to connect SmartRecruiters to Claude to track candidate pipelines, audit job offers, or automate application status updates, you need a Model Context Protocol (MCP) server. This server acts as the translation layer between Claude's LLM function calls and SmartRecruiters' REST API. You can either build and maintain this integration layer from scratch, or use a managed platform like Truto to dynamically generate a secure, authenticated MCP server URL.
If your team uses ChatGPT, check out our guide on /connect-smartrecruiters-to-chatgpt-manage-jobs-and-candidates/ or explore our broader architectural overview on /connect-smartrecruiters-to-ai-agents-automate-your-hiring-funnel/.
Giving an AI agent read and write access to an enterprise applicant tracking system (ATS) is an engineering challenge. You have to handle OAuth 2.0 token lifecycles, map deeply nested candidate data schemas to MCP tool definitions, and deal with strict state-transition logic. Every time the API changes, you have to update your server code and redeploy.
This guide breaks down exactly how to use Truto to generate a secure, managed MCP server for SmartRecruiters, connect it natively to Claude Desktop, and execute complex hiring workflows using natural language.
The Engineering Reality of the SmartRecruiters API
A custom MCP server is a self-hosted integration layer. While the open MCP standard provides a predictable way for models to discover tools, the reality of implementing it against specialized B2B APIs is painful. SmartRecruiters is built to manage complex global hiring workflows, GDPR compliance, and strict candidate state transitions. Its API reflects that domain complexity.
If you decide to build a custom SmartRecruiters MCP server, here are the specific integration challenges you will face:
Strict Status Transition Logic
Moving a candidate through a hiring pipeline in SmartRecruiters is not a simple CRUD operation. If you want to reject a candidate or mark them as withdrawn, you cannot just pass { status: "REJECTED" } to the API. SmartRecruiters enforces strict sub-status requirements tied to the company's specific configuration. If your LLM attempts to skip a required reason, the API will throw a REQUIRED_SUB_STATUS_OMITTED error. If the LLM invents a reason, you get a REASON_NOT_FOUND error. You must architect your tools so the LLM knows to query the valid rejection reasons first before attempting the state change.
Binary Attachment Handling Applicant tracking heavily involves resumes, cover letters, and portfolios. The SmartRecruiters API treats attachment metadata and raw binary files separately. An LLM cannot natively process raw binary streams. Your MCP server must provide distinct tools - one to list attachment metadata, and a separate mechanism to download or parse the binary payload into text the LLM can actually read. Managing this abstraction within a custom MCP server requires careful memory and stream handling.
Separated Consent Models (GDPR) SmartRecruiters handles data privacy meticulously. Accounts can be configured for "single consent" or "separated consent" (e.g., distinct consents for SmartRecruit vs SmartCRM). An LLM querying a candidate's profile might need to parse completely different consent payload structures depending on how the specific customer instance is configured. Exposing this via MCP requires schemas that can accommodate polymorphic responses without breaking the LLM's understanding of the data.
Rate Limiting and Quotas
SmartRecruiters enforces strict API quotas. When building an MCP server, you cannot assume every tool call will succeed. Truto handles this by passing the HTTP 429 errors directly back to the caller, while normalizing the upstream rate limit information into standardized IETF headers (ratelimit-limit, ratelimit-remaining, ratelimit-reset). Truto does not retry or apply backoff automatically - the AI agent framework is responsible for handling the backoff logic.
How Truto Solves This With Managed MCP
Instead of writing custom Node.js or Python code to handle SmartRecruiters' quirks, Truto derives MCP tools dynamically from the API's OpenAPI specifications and documentation records.
When you connect a SmartRecruiters account to Truto, the system maps the underlying resources to a unified JSON-RPC 2.0 endpoint. The schemas are automatically injected with instructions that guide the LLM. For example, pagination cursors are injected with explicit system prompts telling the LLM to pass the cursor value back unchanged. The data passes directly from SmartRecruiters to the client - Truto operates as a zero-data-retention proxy, meaning no candidate PII is ever cached or stored in the integration layer.
flowchart TD
A["Claude Desktop<br>Client"] -->|"JSON-RPC over HTTP"| B["Truto MCP Router<br>(/mcp/:token)"]
B -->|"Dynamic Tool Generation"| C["Integration Documentation<br>Records"]
B -->|"Tool Execution"| D["Proxy API Handler"]
D -->|"Authenticated REST Call"| E["SmartRecruiters API"]
E -->|"Raw JSON"| D
D -->|"Formatted Tool Result"| B
B -->|"MCP Response"| AGenerating the SmartRecruiters MCP Server
To give Claude access to SmartRecruiters, you first need to generate a secure MCP server URL scoped to your specific integrated account.
Method 1: Via the Truto UI
This is the fastest method for internal tooling and testing.
- Log into your Truto dashboard and navigate to the Integrated Accounts section.
- Select your connected SmartRecruiters account.
- Click the MCP Servers tab.
- Click Create MCP Server.
- Select your configuration. You can optionally restrict the server to only
readmethods to ensure Claude cannot accidentally delete or modify candidate data. - Click Generate and copy the resulting URL (e.g.,
https://api.truto.one/mcp/abc123def456).
Method 2: Via the Truto API
For production use cases where you are provisioning AI agents programmatically, you can generate the MCP server via a REST call. This provisions the server and returns the secure token URL.
// POST /integrated-account/:id/mcp
const response = await fetch('https://api.truto.one/integrated-account/YOUR_ACCOUNT_ID/mcp', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_TRUTO_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: "SmartRecruiters Hiring Agent",
config: {
methods: ["read", "write"] // Restrict operation types if needed
},
expires_at: "2026-12-31T23:59:59Z" // Optional TTL for the server
})
});
const mcpServer = await response.json();
console.log(mcpServer.url);
// "https://api.truto.one/mcp/a1b2c3d4e5f6..."Connecting the MCP Server to Claude
Because Truto provides a remote, hosted MCP server, you do not need to run local Node.js processes. The connection happens via Server-Sent Events (SSE).
Connecting to Claude Desktop (Configuration File)
To connect the SmartRecruiters MCP server to Claude Desktop, you modify your claude_desktop_config.json file. We use the @modelcontextprotocol/server-sse package to handle the remote connection.
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"smartrecruiters": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-sse",
"https://api.truto.one/mcp/YOUR_GENERATED_TOKEN_HERE"
]
}
}
}Restart Claude Desktop. The "hammer" icon will appear, indicating that the SmartRecruiters tools are loaded and ready to use.
Connecting to ChatGPT (UI Method)
If you are testing across multiple models, you can also add this server to ChatGPT.
- Open ChatGPT and navigate to Settings -> Apps -> Advanced settings.
- Enable Developer mode.
- Under MCP servers / Custom connectors, click Add new server.
- Name the connection (e.g., "SmartRecruiters").
- Paste the Truto MCP URL into the Server URL field and save.
SmartRecruiters Hero Tools for AI Agents
Truto automatically generates dozens of tools for SmartRecruiters. Here are the most powerful operations to expose to your AI agents.
List All Jobs
list_all_smart_recruiters_jobs
Searches SmartRecruiters jobs by title keyword, department, status, or hiring team member. This is the entry point for almost any hiring workflow, returning the core metadata (ID, title, status) needed for subsequent operations.
"Find all active engineering roles located in London and list their internal reference numbers."
List All Candidates
list_all_smart_recruiters_candidates
Queries candidates who have at least one job application. You can filter by job ID, location, specific tags, and status. It returns high-level candidate records, which is useful for building target lists before drilling into specific profiles.
"Get a list of all candidates currently in the 'Interview' stage for the Senior Frontend Developer role."
Get Application Details
smart_recruiters_candidates_get_application
Retrieves the specific context of a candidate's application to a specific job. Because a single candidate can apply to multiple jobs, this tool is required to understand their exact status and sub-status for a given role.
"Check the current application status for candidate ID 98765 on the Data Scientist job opening."
Update Candidate Status
smart_recruiters_candidates_update_status
Moves a candidate through the hiring pipeline. As mentioned, moving a candidate to REJECTED or WITHDRAWN requires a valid sub-status reason ID. The agent must be prompted carefully to handle this multi-step validation.
"Move candidate 12345 to the Offer stage for job ID 999. If rejecting them instead, first query the valid rejection reasons and use the one labeled 'Not a culture fit'."
Download Candidate Attachment
smart_recruiters_candidates_download_attachment
Fetches a raw binary file (like a PDF resume) using an attachment ID. In an agentic workflow, you typically pipe this binary output through a secondary tool or parser before feeding the text back into Claude's context window.
"Retrieve the resume file for attachment ID 555444 and summarize their previous work experience."
List Job Offers
smart_recruiters_candidates_job_offers
Retrieves the offer data extended to a candidate for a specific job. This is critical for auditing compensation bands, tracking offer acceptance rates, and syncing recruitment data to downstream HRIS platforms.
"List the job offers extended for the Product Manager role and verify if the compensation fields match our standard bands."
For the complete tool inventory and detailed JSON schemas, visit the SmartRecruiters integration page.
Workflows in Action
Here is how an AI agent actually utilizes these tools to automate real-world talent acquisition tasks.
Scenario 1: Candidate Screening and Status Advancement
Recruiters spend hours manually reviewing top-of-funnel applicants and moving them to the initial screening stage. Claude can automate this triage process.
"Find all new applicants for the 'DevOps Engineer' role. If they have the tag 'referred', automatically move their application status to the 'Phone Screen' stage."
- Claude calls
list_all_smart_recruiters_jobswith the keyword "DevOps Engineer" to find the specificjob_id. - Claude calls
list_all_smart_recruiters_candidatesusing thejob_idand filtering by the 'referred' tag. - For each candidate returned, Claude calls
smart_recruiters_candidates_update_status, passing thecandidate_id,job_id, and the payload to update the status to the initial screening phase.
The recruiter gets an updated pipeline without having to manually drag and drop cards in the ATS UI.
Scenario 2: Job Offer Generation and Audit
Tracking the status of outstanding job offers across a large hiring team is tedious. You can ask Claude to run a diagnostic on current offers.
"Audit all active job offers for the Sales department. List the candidate names, the role they are offered, and the current status of the offer."
- Claude calls
list_all_smart_recruiters_jobsfiltered by the Sales department to get the active job IDs. - Claude iterates through the jobs, calling
smart_recruiters_candidates_job_offersfor eachjob_id. - Claude compiles the returned data (candidate details, compensation, offer status) and formats it into a clean markdown table for the user.
Scenario 3: Bulk Rejection with Reason Mapping
Handling rejections properly ensures clean reporting and compliance.
"Reject all candidates currently sitting in the 'Reviewed' stage for the closed Marketing Manager role. Use the rejection reason 'Position Closed'."
- Claude calls
list_all_smart_recruiters_reject_reasonsto find the exact system ID corresponding to the "Position Closed" label. - Claude calls
list_all_smart_recruiters_candidatesfor the Marketing Manager role, filtering for those in the "Reviewed" status. - Claude iterates through the list, calling
smart_recruiters_candidates_update_status, passing the rejection status and the specific sub-status ID retrieved in step 1.
sequenceDiagram
participant Claude as Claude Desktop
participant MCP as Truto MCP Server
participant API as SmartRecruiters API
Claude->>MCP: Call list_all_smart_recruiters_reject_reasons
MCP->>API: GET /rejection-reasons
API-->>MCP: [ { id: "req123", label: "Position Closed" } ]
MCP-->>Claude: JSON Array of reasons
Claude->>MCP: Call list_all_smart_recruiters_candidates (status: Reviewed)
MCP->>API: GET /candidates?status=Reviewed
API-->>MCP: [ { id: "cand999", ... } ]
MCP-->>Claude: Candidate Data
Claude->>MCP: Call update_status (cand999, REJECTED, req123)
MCP->>API: POST /candidates/cand999/status
API-->>MCP: 204 No Content
MCP-->>Claude: SuccessSecurity and Access Control
Exposing an enterprise ATS to an LLM introduces obvious security risks. Truto provides several mechanisms to lock down the MCP server environment:
- Method Filtering: Configure the server with
methods: ["read"]to entirely exclude operations likecreate,update, anddelete. This guarantees the agent is strictly read-only. - Tag Filtering: Restrict the generated tools to specific resource tags. For example, you can allow access to
jobsandcandidatesbut excludeusersordepartments. - Extra Authentication (
require_api_token_auth): By default, possessing the MCP URL is enough to access the tools. Setting this flag requires the caller to also pass a valid Truto API token in theAuthorizationheader, preventing leaked URLs from being abused. - Expiration (
expires_at): Issue temporary MCP servers for one-off tasks or contractors. Once the timestamp passes, the server and its KV storage are automatically purged.
Final Thoughts
Building a custom MCP server for SmartRecruiters means taking ownership of API pagination, strict status transition logic, binary attachment parsing, and OAuth token management. By utilizing Truto's managed MCP architecture, you offload the entire integration lifecycle. Tools are generated dynamically from API documentation, rate limits are passed through transparently via standard headers, and no candidate PII is ever retained.
Your engineering team can focus on orchestrating intelligent agentic workflows, rather than reading ATS API documentation.
FAQ
- How does Claude handle SmartRecruiters candidate status updates?
- Claude uses the smart_recruiters_candidates_update_status tool. Because SmartRecruiters requires specific sub-statuses for rejections, the AI must first query the valid rejection reasons before executing the state change.
- Can I filter which SmartRecruiters tools my AI agent can access?
- Yes. When generating the MCP server in Truto, you can pass method and tag filters. For example, restricting the server to 'read' methods ensures the LLM can only query data, not modify candidates or jobs.
- Does Truto handle SmartRecruiters rate limits automatically?
- No. Truto acts as a pass-through proxy. If SmartRecruiters returns an HTTP 429 error, Truto passes it to the client while normalizing the rate limit headers to the IETF standard (ratelimit-limit, ratelimit-remaining, ratelimit-reset). The client is responsible for retries and backoff.
- How are MCP tools generated for SmartRecruiters?
- Tools are dynamically generated from the SmartRecruiters API documentation and resource schemas. This ensures the LLM always receives up-to-date query and body definitions without you needing to maintain custom integration code.