linkedin-mcp
by Shrushti8
README.md
# linkedin-mcp
An MCP server that automates LinkedIn job search and Easy Apply using Playwright + Claude Code. Search for jobs matching your skill set, auto-fill application forms from your profile, and track applications in a local database — all from a Claude conversation.
## What it does
| Tool | Description |
|------|-------------|
| `linkedin_login` | Open a browser to log in to LinkedIn. Run once — session is saved. |
| `search_jobs` | Search LinkedIn jobs with smart scoring against your resume skills. |
| `get_job_details` | Fetch the full job description from a LinkedIn job URL. |
| `easy_apply_poc` | Inspect a job's Easy Apply form fields without submitting. |
| `easy_apply_submit` | Navigate all form steps, fill from your profile, and submit. |
| `batch_easy_apply` | Search + apply to multiple jobs in one go, with dry-run safety. |
## Prerequisites
- Python 3.11+
- [Claude Code](https://claude.ai/code) (or any MCP-compatible client)
- A LinkedIn account
## Setup
### 1. Clone and install dependencies
```bash
git clone https://github.com/Shrushti8/linkedin-mcp.git
cd linkedin-mcp
pip install -r requirements.txt
playwright install chromium
```
### 2. Create your credentials file
```bash
cp .env.example .env
# Edit .env and fill in your LinkedIn email, password, and resume path
```
### 3. Create your profile
Run the interactive setup script — it asks you all the questions and generates `profile.json`:
```bash
python setup.py
```
Or copy `profile.template.json` to `profile.json` and fill it in manually.
`profile.json` is gitignored and stays local to your machine.
### 4. Add the MCP server to Claude Code
Add this to your `claude_desktop_config.json` (or Claude Code MCP settings):
```json
{
"mcpServers": {
"linkedin": {
"command": "python",
"args": ["/absolute/path/to/linkedin-mcp/server.py"]
}
}
}
```
### 5. Log in to LinkedIn
In a Claude conversation, call the `linkedin_login` tool. A browser window opens — log in manually (or it auto-fills if you set `LINKEDIN_EMAIL`/`LINKEDIN_PASSWORD` in `.env`). Your session is saved to the `session/` folder for all future calls.
## Usage examples
**Search for jobs:**
```
search_jobs(keywords="Senior Data Engineer", days=1, easy_apply_only=true)
```
**Inspect a form before applying:**
```
easy_apply_poc(url="https://www.linkedin.com/jobs/view/1234567890")
```
**Apply to a single job (dry run first):**
```
easy_apply_submit(url="...", dry_run=true)
easy_apply_submit(url="...", dry_run=false)
```
**Batch apply to top 5 Easy Apply jobs:**
```
batch_easy_apply(limit=5, keywords="Data Engineer", days=1)
```
## How job scoring works
Each job gets a `resume_score` based on how many keywords from your `resume_score_weights` (in `profile.json`) appear in the job title and description. Big-name companies get a +3 bonus. Results are sorted by score descending.
You can tune the weights in `profile.json` to match your own skill set.
## How form filling works
`easy_apply_submit` uses a longest-keyword-match approach against your `profile.json`:
- Text fields are matched by label (e.g. "years of python experience" → your Python YOE)
- Salary/CTC fields use your `current_ctc_lpa` and `expected_ctc_lpa`
- Yes/No questions are reasoned about using your notice period, bond preference, relocation preference, and skills you don't have
- Jobs with questions the tool can't answer are returned in `needs_user_input` — never submitted blind
## Privacy
Your personal data (`profile.json`, `.env`, `session/`, `applications.db`) is gitignored and never committed. See `.gitignore`.
## Troubleshooting
**Tool behavior didn't change after editing a file?**
The MCP server loads Python once at startup. After any code edit, reconnect the server: in Claude Code, go to `/mcp` → linkedin → Reconnect.
**Redirected to login page during search?**
Your session expired. Run `linkedin_login` again to refresh it.
**`profile.json` not found warning?**
Run `python setup.py` to create your profile.
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues