EN
LinkedInLinkedIn Recruiter MCP

LinkedIn Recruiter MCP Server: build candidate search, projects and InMail into your ATS with a coding agent

Give Codex, Cursor, Claude Code or Gemini CLI the LinkedIn Recruiter API routes through the hosted Unipile MCP server. Your coding agent reads the endpoints, writes Recruiter candidate search, hiring projects, pipelines, applicants, job postings and Recruiter InMail into your ATS, and tests them on a Development application, on the Recruiter contract of the account each recruiter connects.
Codex
Cursor
Claude Code
Gemini CLI
Windsurf
Any MCP client
Start with a Development application. 7-day free trial, no credit card.
Your coding agent
Unipile MCP connected
Sarah
Add LinkedIn Recruiter candidate search to the sourcing page of my ATS. Recruiters connect their own LinkedIn account from Settings.
Read endpointPOST /v2/{account_id}/linkedin/recruiter/search/peopleschema loaded
Added searchCandidates(filters) on the backend. It checks the account's contracts first, resolves skills and locations to IDs, then runs the Recruiter search. Tested on the Development app: 40 candidates on the first page.
4 files changed · tested on the Development app
Now a "Save to pipeline" button on each result, for the requisition's hiring project.
Run requestPOST /v2/{account_id}/linkedin/recruiter/projects/{project_id}/pipeline/candidate/save200 OK
Writing the pipeline service
Describe the next feature…
The short answer

Is there an official LinkedIn Recruiter MCP server?

No. LinkedIn does not publish a Model Context Protocol server, for Recruiter or for anything else. The Unipile MCP server is a hosted third-party server generated from the Unipile API, and it exposes the LinkedIn Recruiter API routes: candidate search, hiring projects, pipelines, talent pool, applicants, job postings and Recruiter InMail. Your coding agent reads those endpoints and writes the integration into your product, where each recruiter connects their own LinkedIn account through Hosted Auth and your code acts on behalf of that authenticated user, on the Recruiter contract they hold.

The server URL

LinkedIn Recruiter MCP server URLLive
https://developer.unipile.com/mcp?branch=v2.0
AuthHeader X-API-KEY with a scoped Account API key, over streamable HTTP. The same URL serves LinkedIn Classic, Sales Navigator, Recruiter and eight other channels.
AccountsA test LinkedIn account with a Recruiter contract on your Development application while you build; in production, the account each recruiter connected through Hosted Auth.
Recruiter25 routes under /v2/{account_id}/linkedin/recruiter, plus Recruiter InMail on POST /v2/{account_id}/chats/send.
ClientsCodex, Cursor, Claude Code, Gemini CLI, Windsurf, or any MCP client over streamable HTTP.

How one prompt becomes code in your ATS

1
You describe the featureAdd Recruiter candidate search to the sourcing page, filtered by skills, location and years of experience.
2
The agent reads the Recruiter endpoints
Read endpointPOST /v2/{account_id}/linkedin/recruiter/search/peopleschema loaded
3
It writes the code and tests it on your Development applicationAdded searchCandidates() and a filter form fed by the Recruiter search parameters route, wired to the sourcing page. Ran it on the Development app: 25 candidates, profile opened with the Recruiter variant.
The whole Unipile API, readable by your coding agent
Prompts, not glue code

What your coding agent builds with the LinkedIn Recruiter MCP

Pick a recruiting feature. Each transcript shows the prompt you give the agent, the LinkedIn Recruiter API endpoints it reads and runs through the Unipile MCP server, and what lands in your ATS. Paths are complete, on the API base URL https://api.unipile.com, with a scoped key in the X-API-KEY header.
Codex · sourcing-appDevelopment app
Add LinkedIn Recruiter candidate search to the sourcing page: skills, job title, seniority, a postal code with a radius, years of experience.
Run requestPOST /v2/{account_id}/linkedin/recruiter/search/parametersIDs resolved
Run requestPOST /v2/{account_id}/linkedin/recruiter/search/people40 candidates
Added recruiter-search.ts: the filter form resolves skills, titles and locations to IDs with the search parameters route, then calls people search with skills, title, seniority, postal_code_radius and years_of_experience. Results page with what the API returns. Tested on the Development app: 40 candidates on the first page.4 files changed · tested on the Development app

Recruiter candidate search, with Recruiter's own filters

The people search route takes the Recruiter filter set: skills, titles, seniority, companies, schools, locations, languages, and Recruiter signals such as recently_joined, is_past_applicant or hide_previously_viewed. Results are what the connected recruiter can see on their own contract.
Endpoints the agent uses
POST/v2/{account_id}/linkedin/recruiter/search/parametersPOST/v2/{account_id}/linkedin/recruiter/search/peopleGET/v2/{account_id}/users/{user_id}
Common mistake: Sending a location or a skill as free text. Filters that point to a LinkedIn entity take IDs: resolve them first with POST /v2/{account_id}/linkedin/recruiter/search/parameters. It is a POST, unlike the GET parameters route of Sales Navigator.
Recruiter search API guide
Cursor · ats-appDevelopment app
Let recruiters paste a LinkedIn Recruiter search URL, or pick one of their saved searches, and import the candidates into the ATS.
Read endpointPOST /v2/{account_id}/linkedin/recruiter/searchschema loaded
Run requestPOST /v2/{account_id}/linkedin/recruiter/search/people25 candidates
Added an "Import from Recruiter" dialog. A pasted URL goes to the search-from-URL route; a saved search goes through people search with load_saved_search. Candidates are upserted by their LinkedIn ID, so a second import does not duplicate them.3 files changed · tested on the Development app

Reuse the searches recruiters already built in Recruiter

Recruiters spend time tuning a search. The search-from-URL route runs a Recruiter search URL as it is, and people search can load a saved search or a saved custom filter (load_saved_search, load_custom_filter) or save a new one (save_search, save_custom_filter).
Endpoints the agent uses
POST/v2/{account_id}/linkedin/recruiter/searchPOST/v2/{account_id}/linkedin/recruiter/search/peoplePOST/v2/{account_id}/linkedin/recruiter/search/parameters
Common mistake: Sending a Classic or Sales Navigator URL to the Recruiter route. Each product has its own search-from-URL route; pick the route from where the URL comes from.
LinkedIn API for recruiting software
Claude Code · ats-appDevelopment app
When a recruiter opens a candidate, show the profile as LinkedIn Recruiter shows it, with the recruiting activity section.
Read endpointGET /v2/{account_id}/users/{user_id}schema loaded
Run requestGET /v2/{account_id}/users/{user_id}?variant=linkedin_recruiter&with_sections=linkedin_recruiting_activity200 OK
Added getRecruiterProfile(id) with variant=linkedin_recruiter and the linkedin_recruiting_activity section, and a "Recruiting activity" tab on the candidate page. The call runs only when the recruiter opens the profile.3 files changed · tested on the Development app

The candidate profile as Recruiter shows it

The profile route has three LinkedIn variants: linkedin_classic, linkedin_sales_navigator and linkedin_recruiter. With the Recruiter variant, the agent can request the recruiting activity section, which exists on Recruiter only, next to sections such as experience, education, skills and languages.
Endpoints the agent uses
GET/v2/{account_id}/users/{user_id}POST/v2/{account_id}/linkedin/recruiter/search/peopleGET/v2/{account_id}/linkedin/contracts
Common mistake: Leaving out variant=linkedin_recruiter and expecting Recruiter data. The linkedin_recruiting_activity section is Recruiter only; ask for it with the Recruiter variant.
LinkedIn MCP server: Classic profiles and messaging
Gemini CLI · ats-appDevelopment app
Mirror each ATS requisition as a LinkedIn Recruiter hiring project: create it when the recruiter opens the job, update it when the job changes.
Run requestGET /v2/{account_id}/linkedin/recruiter/projects12 projects
Read endpointPOST /v2/{account_id}/linkedin/recruiter/projectsschema loaded
Added recruiter-projects.ts: the first sync links existing projects to requisitions, "Create in Recruiter" creates a project from the requisition page, and edits go through PATCH on the project. The project ID is stored on the requisition.4 files changed · tested on the Development app

Hiring projects in sync with your requisitions

List, create, read and edit Recruiter hiring projects from your ATS. The project ID then scopes everything else: pipeline, talent pool search, applicants and job postings.
Endpoints the agent uses
GET/v2/{account_id}/linkedin/recruiter/projectsPOST/v2/{account_id}/linkedin/recruiter/projectsPATCH/v2/{account_id}/linkedin/recruiter/projects/{project_id}
Common mistake: Retrying a project creation after a timeout. List the projects first to check whether it was created, then decide; a blind retry can leave two projects.
Features for recruiting software
Claude Code · ats-appDevelopment app
Show the pipeline of each Recruiter project on the requisition page, add a talent pool search, and let recruiters save a candidate to the pipeline.
Run requestPOST /v2/{account_id}/linkedin/recruiter/projects/{project_id}/pipeline34 candidates
Run requestPOST /v2/{account_id}/linkedin/recruiter/projects/{project_id}/talent-pool/search18 matches
Added the pipeline view (candidates upserted on the requisition), a talent pool search box on the project, and a "Save to pipeline" button wired to the save-candidate route. A save runs on the recruiter's click, one candidate at a time.5 files changed · tested on the Development app

Pipelines and talent pools, inside the requisition

The pipeline route lists the candidates of a project and the save route adds one. Talent pool search runs a people search from the project's talent pool, so the requisition page shows the same candidates the recruiter works with in Recruiter.
Endpoints the agent uses
POST/v2/{account_id}/linkedin/recruiter/projects/{project_id}/pipelinePOST/v2/{account_id}/linkedin/recruiter/projects/{project_id}/pipeline/candidate/savePOST/v2/{account_id}/linkedin/recruiter/projects/{project_id}/talent-pool/search
Common mistake: Calling the list routes with GET. Listing pipeline candidates and searching the talent pool are both POST routes that take a request body.
Messaging and workflow features for ATS
Cursor · ats-appDevelopment app
Import the applicants of each project's LinkedIn job posting into the ATS candidate list, with their resumes.
Run requestPOST /v2/{account_id}/linkedin/recruiter/projects/{project_id}/talent-pool/applicants52 applicants
Run requestGET /v2/{account_id}/linkedin/recruiter/projects/{project_id}/talent-pool/applicants/{applicant_profile_id}/resumeresume
Added the applicant import per project (list, then detail with the get-applicant route) and resume retrieval, stored on the candidate file. Resumes are fetched when the recruiter opens an applicant, not for the whole list.4 files changed · tested on the Development app

Job applicants and their resumes, in the ATS

For a project with a job posting, the applicants route lists who applied, the applicant route returns one application, and the resume route returns that applicant's resume. Your ATS gets LinkedIn applicants next to the ones from its own career site.
Endpoints the agent uses
POST/v2/{account_id}/linkedin/recruiter/projects/{project_id}/talent-pool/applicantsGET/v2/{account_id}/linkedin/recruiter/projects/{project_id}/talent-pool/applicants/{applicant_id}GET/v2/{account_id}/linkedin/recruiter/projects/{project_id}/talent-pool/applicants/{applicant_profile_id}/resume
Common mistake: Assuming the resume route takes the same ID as the applicant route. Its path parameter is applicant_profile_id, not applicant_id; the agent reads both schemas before wiring them.
LinkedIn job posting API
Codex · ats-appDevelopment app
Let recruiters send a Recruiter InMail from the candidate page, with a subject and their signature, visible to the project team.
Read endpointPOST /v2/{account_id}/chats/sendspecifics loaded
Run requestGET /v2/{account_id}/linkedin/inmail-creditscredits
Added sendRecruiterInmail() on the start-chat route with specifics.linkedin.recruiter: subject, signature, visibility: PROJECT, intent: HIRE_FOR_OWN_COMPANY, send_as: INMAIL. The composer shows the InMail credits, and a failed send is reported to the recruiter, never retried.3 files changed · tested on the Development app

Recruiter InMail from the candidate page

Recruiter messages go through the start-chat route with specifics.linkedin.recruiter: subject, signature, visibility (PUBLIC, PRIVATE or PROJECT), intent (HIRE_FOR_CLIENT or HIRE_FOR_OWN_COMPANY), send_as (INMAIL, or EMAIL using profile data), a channel_type from the project talent pool, and follow_up to schedule a follow-up message on Recruiter Pro contracts.
Endpoints the agent uses
POST/v2/{account_id}/chats/sendGET/v2/{account_id}/linkedin/inmail-creditsGET/v2/{account_id}/chats/{chat_id}/messages
Common mistake: Keeping the defaults without checking them. intent defaults to HIRE_FOR_CLIENT and visibility to PRIVATE: an in-house team usually wants HIRE_FOR_OWN_COMPANY, and a shared project may want PROJECT.
Send messages on behalf of recruiters
Windsurf · ats-appDevelopment app
Publish ATS jobs to LinkedIn from the requisition page: create the draft, check job slot credits, publish, and close the posting when the job is filled.
Run requestGET /v2/{account_id}/linkedin/recruiter/job-slots-creditscredits
Run requestPOST /v2/{account_id}/linkedin/recruiter/projects/{project_id}/jobs/{job_id}/publishpublished
Added the job posting flow: a draft in the requisition's project (or in a new project), edits with PATCH, the budget of the posting, a job slot credits check before the Publish button is enabled, and Close when the requisition is filled. Each step is a recruiter click.6 files changed · tested on the Development app

Job postings from the requisition, credits checked first

Create a draft in an existing project or in a new one, edit it, publish it, close it. List the postings, read one, read the budget of a posting and the job slot credits of the contract before publishing.
Endpoints the agent uses
POST/v2/{account_id}/linkedin/recruiter/projects/{project_id}/jobsGET/v2/{account_id}/linkedin/recruiter/job-slots-creditsPOST/v2/{account_id}/linkedin/recruiter/projects/{project_id}/jobs/{job_id}/publish
Common mistake: Publishing without reading the credits. Call GET /v2/{account_id}/linkedin/recruiter/job-slots-credits first and show the result to the recruiter; publishing stays their decision.
LinkedIn job posting API
Real routes, complete paths

Every LinkedIn Recruiter API route the MCP server exposes

The server exposes the Unipile API itself, so what your coding agent can build on Recruiter is what the API does. Below are all 25 Recruiter routes, grouped by feature, and the shared LinkedIn routes a Recruiter integration also uses. Paths are complete, on the API base URL https://api.unipile.com, with the scoped key in the X-API-KEY header.
25Recruiter routes under /linkedin/recruiter, on the contract the user connected
3ways to search: filters, a Recruiter URL, a project's talent pool
1send route for Recruiter InMail, with specifics.linkedin.recruiter
0endpoints to guess: the agent reads the exact schema before it writes code
3 routes
Candidate search Recruiter people search with the full filter set, a search from a Recruiter URL, and the parameters route that resolves filter values to IDs.
POST/v2/{account_id}/linkedin/recruiter/search/people
POST/v2/{account_id}/linkedin/recruiter/search
POST/v2/{account_id}/linkedin/recruiter/search/parameters
"Add Recruiter candidate search with skills, location and seniority filters to the sourcing page."
4 routes
Hiring projects List, create, read and edit the hiring projects of the Recruiter contract. The project ID scopes pipeline, talent pool, applicants and jobs.
GET/v2/{account_id}/linkedin/recruiter/projects
POST/v2/{account_id}/linkedin/recruiter/projects
GET/v2/{account_id}/linkedin/recruiter/projects/{project_id}
PATCH/v2/{account_id}/linkedin/recruiter/projects/{project_id}
"Create a Recruiter project from each new requisition and keep its name in sync."
3 routes
Pipeline and talent pool List the candidates of a project pipeline, save a candidate to it, search the project's talent pool.
POST/v2/{account_id}/linkedin/recruiter/projects/{project_id}/pipeline
POST/v2/{account_id}/linkedin/recruiter/projects/{project_id}/pipeline/candidate/save
POST/v2/{account_id}/linkedin/recruiter/projects/{project_id}/talent-pool/search
"Show each project's pipeline on the requisition page, with a Save to pipeline button."
3 routes
Applicants and resumes List the applicants of a project's job posting, read one application, retrieve the applicant's resume.
POST/v2/{account_id}/linkedin/recruiter/projects/{project_id}/talent-pool/applicants
GET/v2/{account_id}/linkedin/recruiter/projects/{project_id}/talent-pool/applicants/{applicant_id}
GET/v2/{account_id}/linkedin/recruiter/projects/{project_id}/talent-pool/applicants/{applicant_profile_id}/resume
"Import LinkedIn applicants and their resumes into the ATS candidate list."
8 routes
Job postings Create a draft in a new or an existing project, edit, publish and close it, list postings and read one.
POST/v2/{account_id}/linkedin/recruiter/jobs
POST/v2/{account_id}/linkedin/recruiter/projects/{project_id}/jobs
GET/v2/{account_id}/linkedin/recruiter/projects/{project_id}/jobs
GET/v2/{account_id}/linkedin/recruiter/jobs
GET/v2/{account_id}/linkedin/recruiter/jobs/{job_id}
PATCH/v2/{account_id}/linkedin/recruiter/projects/{project_id}/jobs/{job_id}
POST/v2/{account_id}/linkedin/recruiter/projects/{project_id}/jobs/{job_id}/publish
POST/v2/{account_id}/linkedin/recruiter/projects/{project_id}/jobs/{job_id}/close
"Publish the requisition as a LinkedIn job and close it when the role is filled."
2 routes
Budget and job slots Read the budget of a job posting and the job slot credits of the contract before your UI offers to publish.
GET/v2/{account_id}/linkedin/recruiter/projects/{project_id}/jobs/{job_id}/budget
GET/v2/{account_id}/linkedin/recruiter/job-slots-credits
"Disable Publish and explain why when the contract has no job slot left."
2 routes
Company member verification Verify the identity of a company member: request the verification email, then submit the one-time code the user receives.
POST/v2/{account_id}/linkedin/recruiter/company/{company_id}/member/verify-email
POST/v2/{account_id}/linkedin/recruiter/company/{company_id}/member/submit-otp
"Add a verification step where the recruiter enters the code they received."
8 shared
Shared LinkedIn routes Recruiter InMail, the Recruiter profile variant, InMail credits, contracts, and the account connection through Hosted Auth.
POST/v2/{account_id}/chats/send
POST/v2/{account_id}/inboxes/{inbox_id}/chats/send
GET/v2/{account_id}/users/{user_id}
GET/v2/{account_id}/linkedin/inmail-credits
GET/v2/{account_id}/linkedin/contracts
POST/v2/{account_id}/linkedin/contracts/{contract_id}/select
POST/v2/auth/link
GET/v2/accounts/
"Check the account's contracts after connection and hide Recruiter features when none is found."
One complete request, exactly as the agent runs it
POSThttps://api.unipile.com/v2/{account_id}/linkedin/recruiter/search/peopleX-API-KEY: your-scoped-api-key200 OK
The server follows every Unipile API release, so a new Recruiter route reaches your agent the day it ships. In production your product calls the same routes on the account each recruiter connected through Hosted Auth, as user actions in your UI. Same routes as the Unipile LinkedIn API, in the code the agent writes or through the official SDKs.·API reference
LinkedInRecruiter search filters

LinkedIn Recruiter MCP search filters: the whole Recruiter set

Recruiter people search is where most ATS and sourcing features start. The route POST /v2/{account_id}/linkedin/recruiter/search/people documents 56 body fields; the agent reads them from the schema and builds the filter form your recruiters expect. The main ones, grouped the way a recruiter thinks.
Skills and experience12 fields
The filters recruiters reach for first: what the candidate does, at what level, for how long. Body fields of the people search
Skills, titles and functionskills, title, job_title, job_function
Seniority and tenureseniority, years_of_experience, years_in_current_company, years_in_current_position
Keywords and nameskeywords, first_name, last_name, occupation
"Find backend engineers with Go and Kubernetes, senior level, 5 to 10 years of experience."
Companies and education9 fields
Where the candidate works or worked, the kind of company, and where they studied. Body fields of the people search
Companiescompany, current_company, past_company
Industry and company sizeindustry, company_size
Educationschool, degree, field_of_study, graduation_year
"Add a past company filter and a graduation year range to the sourcing form."
Location, work type and languages8 fields
Where the candidate is, how they want to work, which languages they speak. Body fields of the people search
Location and radiuslocation, postal_code, postal_code_radius
Workplace and employmentworkplace_type, employment_type
Languagesspoken_language, proficiency, profile_language
"Search within 30 km of a postal code, remote or hybrid, German spoken."
Recruiter signals and your team's work16 fields
Filters that only make sense in Recruiter: activity signals, the team's projects, tags and notes, and saved searches. Body fields of the people search
Signalsrecently_joined, hide_previously_viewed, new_results_only, is_past_applicant, recruiting_activity, spotlights, is_military_veteran, network_distance
Projects, tags and notesproject, project_id, tags, notes
Saved searches and custom filtersload_saved_search, save_search, load_custom_filter, save_custom_filter
"Hide candidates the recruiter already viewed and show only new results since the last run."
Filters that point to a LinkedIn entity (a location, a skill, a company, a school) take IDs. The agent resolves them with POST /v2/{account_id}/linkedin/recruiter/search/parameters before calling the search, then passes the IDs. The schema also documents exclude, group, id, include, max, min, name, preferences, priority, timespan and type; the agent reads their exact shape before it writes the form. Every filter runs on the Recruiter contract of the connected account.
Quick start

Add the LinkedIn Recruiter MCP to your coding agent in one line

There is no separate Recruiter server to install: the hosted Unipile MCP server covers LinkedIn Recruiter under the same URL as LinkedIn Classic, Sales Navigator and every other channel. Point your coding agent at it with a scoped API key, and it reads the Recruiter endpoints and runs requests against your Development application. The snippets below are the ones from the official documentation.
Cursor~/.cursor/mcp.json
Claude Codeclaude mcp add --transport http …
Codex CLI and IDE extension~/.codex/config.toml
Gemini CLI~/.gemini/settings.json
Windsurf~/.codeium/windsurf/mcp_config.json
~/.cursor/mcp.json
# Register the hosted Unipile MCP server in Claude Code claude mcp add --transport http --scope user \ unipile "https://developer.unipile.com/mcp?branch=v2.0" \ --header "X-API-KEY: your-scoped-api-key" # Verify the connection, or type /mcp inside a session claude mcp list
{ "mcpServers": { "unipile": { "url": "https://developer.unipile.com/mcp?branch=v2.0", "headers": { "X-API-KEY": "your-scoped-api-key" } } } }
{ "mcpServers": { "unipile": { "url": "https://developer.unipile.com/mcp?branch=v2.0", "headers": { "X-API-KEY": "your-scoped-api-key" } } } }
# Codex CLI and the Codex IDE extension share this file [mcp_servers.unipile] url = "https://developer.unipile.com/mcp?branch=v2.0" http_headers = { X-API-KEY = "your-scoped-api-key" } # Verify: codex mcp list
{ "mcpServers": { "unipile": { "httpUrl": "https://developer.unipile.com/mcp?branch=v2.0", "headers": { "X-API-KEY": "your-scoped-api-key" } } } } # Verify: /mcp inside Gemini CLI
Server connected. Try: "Add LinkedIn Recruiter candidate search to the sourcing page, then open the selected profile with the Recruiter variant."
1
Start with a Development applicationIn the Unipile dashboard, work in your Development application: connect a test LinkedIn account that holds a Recruiter contract through Hosted Auth, create a Scope with it and a scoped Account API key for that Scope. Production stays untouched, and an MCP client never gets a global or Service key.
2
Add the server to your coding agentPaste the config for your client, with the scoped key in the X-API-KEY header. Restart the client if it does not pick it up right away.
3
Describe the feature, review the codeDescribe the Recruiter feature you need. The agent reads the endpoints, writes the code in your project and runs requests on the Development app. Switch the key to Production when the flow passes.
On behalf of the recruiter

Whose Recruiter contract does your integration act on?

While you build, on the test account of your Development application. In production, on the LinkedIn account each recruiter connected through Hosted Auth, with the Recruiter contract that account holds, inside workflows that recruiter starts and controls.
1 · Your coding agent Codex, Cursor, Claude Code Reads the Recruiter schemas, writes the code
2 · Unipile MCP server Hosted, scoped API key Runs test requests on your Development app
3 · Unipile API The Recruiter routes Scopes the action to one account ID
4 · LinkedIn Recruiter LinkedIn The selected contract LinkedIn's rules, InMail and job slot credits
5 · The recruiter's account The recruiter Connected through Hosted Auth Their projects, their pipeline, their credits
Connected account · ats-appConnected
The recruiterLinkedIn
Sarah MitchellLinkedIn · Recruiter contract · linked by the user through Hosted Auth
Account IDacc_7f3…c91, the only identifier your code stores
ContractListed with GET …/linkedin/contracts, selected with POST …/contracts/{contract_id}/select
SessionHeld by Unipile, never exposed to your app
StatusConnected · status changes arrive by webhook
ReconnectDisconnect
No Recruiter contract, no Recruiter routesThe Recruiter routes answer only when the connected account holds a Recruiter contract. After connection, your code calls GET /v2/{account_id}/linkedin/contracts, hides the Recruiter features when none is found, and selects one with POST /v2/{account_id}/linkedin/contracts/{contract_id}/select when the account has several. Some options depend on the contract: a scheduled InMail follow_up is for Recruiter Pro contracts only.
Data stays in the recruiter's sessionCandidate profiles, projects, pipelines and messages are routed through the authenticated user's own LinkedIn session. Unipile keeps no independent archive, index or database of LinkedIn profiles or conversations: each request runs on a user-initiated action.
An independent technical intermediaryUnipile is an independent technical intermediary, not affiliated with LinkedIn. Each request is relayed to the account one recruiter connected through Hosted Auth, on behalf of that user, bounded by what that user can already do from their own Recruiter seat.
LinkedIn sets the limits, you respect themInMail credits, job slot credits and search volumes are defined by LinkedIn and by the contract. Unipile relays the live signals so your product can pause or inform the recruiter. How often it acts on an account remains a customer-side decision.
Honest limits

What LinkedIn Recruiter limits still apply

The server does not lift LinkedIn's rules and does not add credits to a contract. The API gives your ATS the account's real signals so the feature you ship works inside them, the way the recruiter would.
What LinkedIn and the contract enforce
A Recruiter contract on the connected accountEvery route under /linkedin/recruiter needs one. Without it, the account still works on the Classic LinkedIn routes, but your Recruiter features stay hidden.
InMail creditsRecruiter InMail spends the credits of the contract. Read them with GET /v2/{account_id}/linkedin/inmail-credits and show them before the recruiter sends.
Job slot credits and posting budgetPublishing a job uses what the contract has. Read GET /v2/{account_id}/linkedin/recruiter/job-slots-credits and the budget of the posting before offering Publish.
Search paginationRecruiter searches return pages. Your code pages with what the API returns, within what the contract allows the recruiter to see.
Checkpoints and identity checksLinkedIn may ask the account owner for a code when the account is linked, and a company member identity check uses an email and a one-time code. The user enters the code; your code never sees a password.
What to build into your ATS
Writes are recruiter actionsSend an InMail, save a candidate, create a project, publish or close a job: each one is triggered by the recruiter in your UI, never by a background loop.
Check before you retry a writeAfter an ambiguous failure, list the projects, the pipeline or the jobs to see what happened. A blind retry can create a second project or send a second InMail.
One Scope and one scoped key per tenantA workspace only sees the accounts assigned to its Scope. The global key stays on your backend for administration, and the recruiter can disconnect at any time.
Adapt the UI to the contractHide what the account cannot do: no Recruiter contract, no Recruiter tab; no Recruiter Pro contract, no scheduled follow-up.
Use webhooks for new messagesIf your ATS must react to candidate replies, subscribe to webhooks and let the event bring the message, instead of polling the inbox.
Four ways to connect an ATS to LinkedIn

How the LinkedIn Recruiter MCP options compare

Every LinkedIn Recruiter MCP option is third-party, so the real question for a recruiting product is how each one reaches Recruiter, on whose contract, and what you can ship with it. The four families you will find, side by side.
Unipile MCP server Community open-source servers Public-data marketplaces No-code MCP bridges
How it reaches Recruiter Unipile MCP serverThe LinkedIn account each recruiter connects through Hosted Auth, then the Recruiter API routes on its contract Community open-source serversYour own LinkedIn login on your machine, driven by a browser session Public-data marketplacesPublic pages, no account, no Recruiter access No-code MCP bridgesTheir LinkedIn app connection and a set of predefined actions
Recruiter surfaces Unipile MCP serverSearch, projects, pipelines, talent pool, applicants, job postings, Recruiter InMail Community open-source serversRarely beyond the Classic profile Public-data marketplacesPublic profiles only, no projects or pipelines No-code MCP bridgesFew or no Recruiter actions
Read, or read and act Unipile MCP serverRead and act: save candidates, create projects, publish jobs, send InMail, as features of your ATS Community open-source serversMostly read, a few writes depending on the project Public-data marketplacesRead only No-code MCP bridgesPredefined writes, little reading
Hosting and clients Unipile MCP serverHosted, one URL, any coding agent over HTTP: Codex, Cursor, Claude Code, Gemini CLI, Windsurf Community open-source serversSelf-hosted, local or Docker, usually one client at a time Public-data marketplacesHosted, token per client No-code MCP bridgesHosted, one generated URL per configuration
Other channels on the same server Unipile MCP serverEight: WhatsApp, Instagram, Telegram, Gmail, Outlook, IMAP, Google and Outlook calendars Community open-source serversNone Public-data marketplacesOther public data sources No-code MCP bridgesThousands of apps, each with a shallow action set
Pricing model Unipile MCP serverPer connected account, whatever the request volume, 7-day free trial Community open-source serversFree, you host and maintain it Public-data marketplacesPer credit or per result No-code MCP bridgesPer task or per action
Whose terms your product works under Unipile MCP serverEach recruiter's own account and Recruiter contract, in workflows the recruiter initiates and controls from your product Community open-source serversYour personal account, at your own risk Public-data marketplacesThe marketplace's data collection terms No-code MCP bridgesThe bridge's terms and its LinkedIn app permissions
Categories are described generically on purpose. What sets the Unipile server apart is the account model: your ATS reads and acts as the recruiter who connected the account, on their own Recruiter contract, behind a single server URL shared with eight other channels.

LinkedIn Recruiter MCP FAQ

The questions people actually type: official or not, the server URL, candidate search, projects and pipelines, Recruiter InMail, contracts, and price.
Not from LinkedIn: it does not publish a Model Context Protocol server for Recruiter. The Unipile MCP server is a hosted third-party server generated from the Unipile API, and it exposes the LinkedIn Recruiter API routes: candidate search, hiring projects, pipelines, talent pool, applicants, job postings and Recruiter InMail. Your coding agent reads those endpoints and writes the integration into your product, where each recruiter connects their own account and your code acts on behalf of that authenticated user. Unipile is an independent technical intermediary and is not affiliated with, endorsed by, or sponsored by LinkedIn.
The same URL as the whole Unipile API: https://developer.unipile.com/mcp?branch=v2.0, over streamable HTTP, with a scoped Account API key in the X-API-KEY header. There is no separate Recruiter server. Paste it into Codex, Cursor, Claude Code, Gemini CLI or Windsurf, and the agent finds the Recruiter endpoints under /v2/{account_id}/linkedin/recruiter on its own.
Yes, on an account with a Recruiter contract. The agent reads POST /v2/{account_id}/linkedin/recruiter/search/people and builds the search with Recruiter filters such as skills, title, seniority, company, school, location with a postal code radius, spoken language, or signals like recently_joined and hide_previously_viewed. It resolves filter values to IDs with POST /v2/{account_id}/linkedin/recruiter/search/parameters, can run a search from a Recruiter URL with POST /v2/{account_id}/linkedin/recruiter/search, and tests the result on your Development application. Searches run as actions of the recruiter who connected the account.
Yes. Your ATS can list, create, read and edit hiring projects (GET and POST /v2/{account_id}/linkedin/recruiter/projects, PATCH /v2/{account_id}/linkedin/recruiter/projects/{project_id}), list the candidates of a project pipeline with POST /v2/{account_id}/linkedin/recruiter/projects/{project_id}/pipeline, save a candidate to it, search the project's talent pool, and import applicants with their resumes. Saving a candidate or creating a project stays a recruiter action in your UI.
Yes, through POST /v2/{account_id}/chats/send with specifics.linkedin.recruiter: a subject, a signature, a visibility (PUBLIC, PRIVATE or PROJECT), an intent (HIRE_FOR_CLIENT or HIRE_FOR_OWN_COMPANY), and send_as set to INMAIL or to EMAIL using profile data. A scheduled follow_up is available on Recruiter Pro contracts only. InMail spends the contract's credits, readable with GET /v2/{account_id}/linkedin/inmail-credits, and each message is sent by the recruiter from your UI.
The Recruiter routes require a Recruiter contract on the connected account; without one, the account only works on the Classic LinkedIn routes (messaging, profiles, classic search). What a given account can do depends on the contract it holds, so your code lists its contracts with GET /v2/{account_id}/linkedin/contracts, selects one with POST /v2/{account_id}/linkedin/contracts/{contract_id}/select, and shows only the features that answer. Test with the kind of contract your customers use.
They are the same routes used at two moments. The LinkedIn Recruiter MCP is how your coding agent reads the Recruiter endpoints and tests them while it writes your integration. The LinkedIn Recruiter API is what your product calls in production, over the REST API or the official SDKs, with its own scoped keys, on the accounts your recruiters connected. You build with the MCP and run on the API.
The MCP server is included in every Unipile plan, with no per-message or per-request fee. Billing is per connected account, whatever the channel: from 49 EUR per month for up to 10 accounts, then 5 EUR per additional account, down to 3 EUR at volume. The 7-day free trial needs no credit card. The Recruiter contract itself remains the recruiter's own LinkedIn subscription. Full grid on the pricing page.