Skip to content
Conduit

mcp server

linkedin-job-mcp

GhoshSrinjoy/linkedin-job-mcpcommunitylistedunreviewed

Set up

Runs on your computer. Pick your agent and operating system.

Before you start

  • Node.js 20 or newer
~/Library/Application Support/Claude/claude_desktop_config.json
{
  "mcpServers": {
    "linkedin-job-mcp": {
      "command": "npx",
      "args": [
        "-y",
        "linkedin-jobs-mcp"
      ]
    }
  }
}

same format Cursor, GitHub Copilot CLI, Junie, JetBrains AI Assistant, Augment (Auggie CLI), Factory Droid, Kiro, Devin CLI +12

Values in angle brackets are placeholders. Restart Claude Desktop after editing its config.Claude Desktop docs

README

synced Oct 23, 2026

LinkedIn Jobs MCP

LinkedIn job search and full job details for your AI apps, plus Ghost Job Radar, a dashboard that shows which job postings are likely not really open. A Windows app connects itself to Claude Code, Codex, VS Code and other MCP clients; the same tools also come as an npm package, a REST API and a command line.

npm version npm downloads CI License

The setup menu of the Windows app

Tools

ToolWhat your AI app gets
search_linkedin_jobsJobs by keyword and location, filtered by date, job type, remote work, salary, experience level, verified postings or fewer than 10 applicants
get_linkedin_job_detailsOne job's full description, seniority, employment type, industries, posting age and applicant count
check_ghost_jobGhost Job Radar's grade for one posting: how likely it is a ghost job, your chance against the competition, and the facts behind it. Needs the radar running

It reads LinkedIn's public job pages, so it needs no account and no browser. Requests are spaced out and cached.

Ghost Job Radar

A dashboard on your computer that grades every job it sees for ghost-job risk: postings that stay up far longer than usual for their occupation, reposts with unchanged text, jobs gone from the employer's own site, start dates long past, talent-pool wording, layoff news while still hiring, and what you know about the employer. Every job gets three separate verdicts: ghost-risk, your chance, and whether the employer answers.

Ghost Job Radar: every job as a mark, further out means online longer than usual

linkedin-jobs-mcp radar

With the Windows app, choose 5 in its menu or run .\linkedin-jobs-mcp.exe radar. It needs Python 3.11 or newer. The first start sets up the radar's Python environment; every start also runs the LinkedIn source, so LinkedIn search and job pages work right away. Your data stays on your computer, in %LOCALAPPDATA%\linkedin-jobs-mcp\radar (macOS: ~/Library/Application Support/linkedin-jobs-mcp/radar, Linux: ~/.local/share/linkedin-jobs-mcp/radar). A .env file there switches on more sources, such as the Bundesagentur job board or Google for Jobs; radar/README.md explains every view, signal and source.

Why a posting got its grade

Install

Windows app

  1. Download linkedin-jobs-mcp.exe from the latest release. It is one file with Node.js inside.
  2. Double-click it. The file is not code-signed, so Windows may say "Windows protected your PC": choose More info → Run anyway.
  3. Choose 1 Install and connect the apps found. The app copies itself to %LOCALAPPDATA%\Programs\linkedin-jobs-mcp\ and adds itself to every supported app it finds.
  4. Restart those apps. The app has no window of its own: they start it in the background when they need the tools.

Installing the app and connecting the apps found

npm (Windows, macOS, Linux)

Needs Node.js 18 or newer.

npm install -g linkedin-jobs-mcp
linkedin-jobs-mcp connect

Or add it to an app by hand, through npx:

{
  "mcpServers": {
    "linkedin-jobs": { "command": "npx", "args": ["-y", "linkedin-jobs-mcp"] }
  }
}

On Windows, some apps need "command": "cmd", "args": ["/c", "npx", "-y", "linkedin-jobs-mcp"].

From source

git clone https://github.com/GhoshSrinjoy/linkedin-job-mcp.git
cd linkedin-job-mcp
npm install
npm run app -- connect

Connect your apps

AppName for connectWhere the setting goes
Claude Codeclaude-codeclaude mcp add --scope user
Codexcodex~/.codex/config.toml
VS Codevscode%APPDATA%\Code\User\mcp.json
VS Code Insidersvscode-insiders%APPDATA%\Code - Insiders\User\mcp.json
Claude Desktopclaude-desktop%APPDATA%\Claude\claude_desktop_config.json
Cursorcursor~/.cursor/mcp.json
Windsurfwindsurf~/.codeium/windsurf/mcp_config.json
Gemini CLIgemini-cli~/.gemini/settings.json
LM Studiolm-studio~/.lmstudio/mcp.json
Clinecline%APPDATA%\Code\User\globalStorage\saoudrizwan.claude-dev\settings\cline_mcp_settings.json

connect only adds or replaces the linkedin-jobs entry: other servers and settings stay, and the first change keeps a copy of the file next to it (<file>.linkedin-jobs.bak). A settings file with comments is left unchanged, and the entry to add is printed instead.

The server connected in two apps

Commands

CommandWhat it does
linkedin-jobs-mcpThe setup menu in a console window; the MCP server when an app starts it
linkedin-jobs-mcp installCopy the Windows app to %LOCALAPPDATA%\Programs\linkedin-jobs-mcp\ and connect the apps found
linkedin-jobs-mcp connect [app ...]Connect the apps found, or only the named ones (also when they are not found)
linkedin-jobs-mcp disconnect [app ...]Remove the connection from every app, or only from the named ones
linkedin-jobs-mcp statusWhich apps are found and connected
linkedin-jobs-mcp config [app ...]Print the settings to add by hand
linkedin-jobs-mcp serve [--port 3000] [--host 127.0.0.1]REST API plus MCP over HTTP
linkedin-jobs-mcp mcpMCP over stdio (what the connected apps run)
linkedin-jobs-mcp job <id or URL>One job's details as JSON
linkedin-jobs-mcp search --keyword "data engineer" --location "Berlin, Germany"Search from the command line
linkedin-jobs-mcp radar [--port 8000] [--no-browser]Open Ghost Job Radar
linkedin-jobs-mcp uninstallDisconnect every app and remove the installed Windows app

With the Windows app, run them from its folder, for example .\linkedin-jobs-mcp.exe status.

Add it by hand

Every app needs the same thing: the program, started with the mcp argument. VS Code (mcp.json):

{
  "servers": {
    "linkedin-jobs": {
      "type": "stdio",
      "command": "C:\\Users\\you\\AppData\\Local\\Programs\\linkedin-jobs-mcp\\linkedin-jobs-mcp.exe",
      "args": ["mcp"]
    }
  }
}

Claude Desktop, Cursor, Windsurf, Gemini CLI, LM Studio and Cline take the same entry under "mcpServers", without "type". Codex (config.toml):

[mcp_servers.linkedin-jobs]
command = "C:\\Users\\you\\AppData\\Local\\Programs\\linkedin-jobs-mcp\\linkedin-jobs-mcp.exe"
args = ["mcp"]

Claude Code:

claude mcp add --scope user linkedin-jobs -- "C:\Users\you\AppData\Local\Programs\linkedin-jobs-mcp\linkedin-jobs-mcp.exe" mcp

Ollama, through mcp-client-for-ollama: save the mcpServers entry in a file and start ollmcp -j servers.json.

linkedin-jobs-mcp config prints all of these with the real path.

MCP over HTTP

Apps that connect by URL can use the HTTP server instead. Start linkedin-jobs-mcp serve (or npm run api) and add http://127.0.0.1:3000/mcp:

claude mcp add --transport http linkedin-jobs http://127.0.0.1:3000/mcp
{ "servers": { "linkedin-jobs": { "type": "http", "url": "http://127.0.0.1:3000/mcp" } } }

The server listens on this computer only and refuses requests that name another host, so web pages cannot reach it through DNS rebinding. HOST=0.0.0.0 makes it reachable from other machines, for example from a container; protect it yourself then.

Search options

OptionValues
keywordJob title or keywords, e.g. data engineer
locationCity, region or country, e.g. Berlin, Germany
city, countryNarrow the location
geoIdLinkedIn location id, skips the location lookup
dateSincePostedpast 24 hours, past week, past month
jobTypefull time, part time, contract, temporary, volunteer, internship
remoteFilteron site, remote, hybrid
salaryMinimum: 40000, 60000, 80000, 100000, 120000
experienceLevelinternship, entry level, associate, senior, director, executive
limitNumber of jobs (default 10; 25 in the REST API)
sortByrecent or relevant
pagePage number, from 0
has_verificationVerified jobs only
under_10_applicantsJobs with fewer than 10 applicants

The REST API accepts every option except salary, experienceLevel, has_verification and under_10_applicants.

Responses

A search returns:

{
  "success": true,
  "total_jobs": 1,
  "jobs": [
    {
      "position": "Data Engineer (m/w/d)",
      "company": "Example GmbH",
      "location": "Berlin, Berlin, Germany",
      "date": "2026-10-20",
      "agoTime": "4 days ago",
      "salary": "Not specified",
      "jobUrl": "https://www.linkedin.com/jobs/view/1234567890/",
      "companyLogo": "https://media.licdn.com/…"
    }
  ],
  "search_params": { "keyword": "data engineer", "location": "Berlin, Germany", "limit": "10" }
}

Job details return:

{
  "id": "1234567890",
  "position": "Data Engineer (m/w/d)",
  "company": "Example GmbH",
  "location": "Berlin, Berlin, Germany",
  "postedAgo": "3 weeks ago",
  "applicants": "Over 200 applicants",
  "salary": null,
  "seniority": "Mid-Senior level",
  "employmentType": "Full-time",
  "jobFunction": null,
  "industries": "Software Development",
  "criteria": { "Seniority level": "Mid-Senior level", "Employment type": "Full-time", "Industries": "Software Development" },
  "acceptingApplications": true,
  "description": "We are looking for a data engineer to join our platform team. …",
  "jobUrl": "https://www.linkedin.com/jobs/view/1234567890/"
}

A job LinkedIn no longer has returns { "id": "…", "removed": true }.

REST API

npm run api or linkedin-jobs-mcp serve starts it on http://127.0.0.1:3000.

EndpointWhat it does
POST /searchSearch, with the options above as a JSON body; returns { "cached", "total", "jobs" }
GET /job/:id, GET /job?url=<link>One job's details; 404 when LinkedIn no longer has it, 400 for an invalid id or link
POST /mcpMCP over Streamable HTTP
GET /health{ "ok": true }

Library

const { query, getJobDetails } = require("linkedin-jobs-mcp");

const jobs = await query({ keyword: "data engineer", location: "Berlin, Germany", limit: "10" });
const job = await getJobDetails("https://www.linkedin.com/jobs/view/1234567890/");

Configuration

Set these in the environment or in a .env file in the folder you start it from.

VariableDefaultWhat it sets
PORT3000Port of the REST API and MCP over HTTP
HOST127.0.0.1Address the server listens on
LINKEDIN_REQUEST_TIMEOUT_MS15000Timeout of one request to LinkedIn
LINKEDIN_CACHE_TTL_MS3600000How long search results stay cached
LINKEDIN_DETAIL_MIN_INTERVAL_MS1500Minimum gap between two job-page requests
LINKEDIN_DETAIL_CACHE_TTL_MS21600000How long job details stay cached
LINKEDIN_USER_AGENTUser agent for job-page requests
API_RATE_LIMIT_WINDOW_MS60000Rate-limit window of the REST API
API_RATE_LIMIT_MAX60Requests per window and address

Build the Windows app

On Windows with Node.js 20 or newer:

npm install
npm run build:win     # dist/linkedin-jobs-mcp.exe and its SHA-256

The build bundles the code with esbuild and injects it into a copy of node.exe (a Node.js single executable application). Pushing a tag such as v1.2.0 builds the app on GitHub Actions and attaches it to a release.

Tests

npm test                              # job pages, settings files, the MCP server and the HTTP API
cd radar && python -m pytest          # Ghost Job Radar

Both run offline.

Repository layout

PathWhat it is
index.jsLinkedIn search and job details
server.js, api.jsMCP server (stdio and HTTP) and REST API
app.js, clients.js, radar.jsThe app: commands, client setup, starting the radar
radar/Ghost Job Radar (Python): dashboard, scoring, research report and notes, browser extension
scripts/build-win.jsBuilds the Windows app
test/Tests of the Node part

Responsible use

The tools read public job pages slowly and cache what they read, for personal job searching and research. Automated access can conflict with LinkedIn's User Agreement, so keep the volume low and use it at your own risk.

License

PolyForm Noncommercial 1.0.0: free for personal, research and other non-commercial use. For commercial use, ask for permission.

Srinjoy Ghosh (@GhoshSrinjoy, ghoshsrinjoy97@gmail.com)

↑↓ navigate openesc close