Skip to main content
Glama
Shrushti8

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.