LinkedIn Job Search MCP Server
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@LinkedIn Job Search MCP Serversearch for remote data analyst jobs in New York"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
LinkedIn Job Search MCP Server
A Model Context Protocol (MCP) server that enables AI assistants (Claude, ChatGPT, etc.) to search LinkedIn jobs with built-in rate limiting to prevent IP bans.
Features
✅ LinkedIn-Only Job Search — Real-time job data from LinkedIn via JobSpy
✅ Request Throttling — Configurable delays (default: 2 seconds) between API calls
✅ Rate Limit Handling — Graceful error messages when LinkedIn limits requests
✅ 5 MCP Tools — Search, filter, get details, company profiles, discover categories
✅ Type-Safe — Pydantic models for all data structures
✅ Production Ready — Comprehensive logging and error handling
Related MCP server: LinkedIn Jobs MCP Server
Project Structure
mcp-server/
├── src/
│ ├── index.py # MCP server with tool definitions & handlers
│ └── linkedin_client.py # JobSpy wrapper with rate limiting
├── examples/
│ └── (future usage examples)
├── requirements.txt # Python dependencies
├── pyproject.toml # Project metadata
├── README.md # This file
├── .gitignore
└── .vscode/
└── linkedin-mcp.json # VS Code MCP configurationInstallation
Prerequisites
Python 3.10+
pip package manager
Virtual environment (recommended)
Setup
Clone or navigate to the project:
cd /Users/tarunkumaruppu/AI/mcp-serverCreate and activate a virtual environment:
python3 -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activateInstall dependencies:
pip install -r requirements.txtVerify installation:
python -c "from src.linkedin_client import LinkedInJobClient; print('✅ Installation successful!')"
Configuration
Rate Limiting
Control how frequently the server calls LinkedIn to prevent IP bans.
Default behavior: 2 seconds between requests
To customize:
# Via environment variable (override default)
export LINKEDIN_REQUEST_DELAY=3.0 # 3 seconds between requests
python src/index.py
# Or set in code (src/index.py, line ~35):
linkedin_client = LinkedInJobClient(request_delay=3.0)Recommended values:
2.0— Balanced (default)3.0-5.0— Conservative (safer)1.0— Aggressive (risk of bans)
VS Code Integration
Open VS Code settings (
Cmd+,on macOS)Search for
"MCP Servers"The server is pre-configured in
.vscode/linkedin-mcp.jsonRestart VS Code to enable
Or manually add to .vscode/settings.json:
{
"mcpServers": {
"linkedin-job-search": {
"type": "stdio",
"command": "python",
"args": ["src/index.py"],
"cwd": "/path/to/mcp-server"
}
}
}Available Tools
1. search_jobs
Search for jobs on LinkedIn with optional filters.
Parameters:
keywords(required) — Job search keywords (e.g., "Python Developer")location(optional) — Job location (default: "United States")job_type(optional) — Filter by type (e.g., "full-time", "part-time")experience_level(optional) — Filter by level (e.g., "entry-level", "senior")hours_old(optional) — Jobs posted within last N hours (e.g., 24, 168)limit(optional) — Max results (default: 25, max recommended: 50)
Example:
search_jobs(
keywords="Data Scientist",
location="San Francisco, CA",
job_type="full-time",
limit=20
)Response:
Found 20 jobs for 'Data Scientist' in San Francisco, CA
1. Senior Data Scientist at Google (San Francisco, CA) [$150,000 - $200,000]
Job ID: a1b2c3d4e5f6
URL: https://www.linkedin.com/jobs/view/...
Type: Full-time
Posted: 2 days ago2. get_job_details
Get detailed information about a specific job.
Parameters:
job_id(required) — Job ID from search resultsjob_url(required) — Job URL from search results
Example:
get_job_details(
job_id="a1b2c3d4e5f6",
job_url="https://www.linkedin.com/jobs/view/..."
)Response:
Job Details (ID: a1b2c3d4e5f6)
job_id: a1b2c3d4e5f6
job_url: https://www.linkedin.com/jobs/view/...
message: Full job details are available by visiting the LinkedIn URL provided.
note: For complete job descriptions, visit the job_url directly on LinkedIn.3. filter_jobs
Filter job results by salary, type, or keywords (local operation, no API call).
Parameters:
salary_min(optional) — Minimum annual salarysalary_max(optional) — Maximum annual salaryjob_type(optional) — Filter by job typekeywords_filter(optional) — Filter by keywords in title/company
Example:
filter_jobs(
salary_min=120000,
salary_max=200000,
job_type="full-time",
keywords_filter="remote"
)4. fetch_company_profile
Get company information from LinkedIn.
Parameters:
company_name(required) — Company name (e.g., "Google")
Example:
fetch_company_profile(company_name="Google")Response:
Company Profile: Google
LinkedIn URL: https://www.linkedin.com/search/results/companies/?keywords=Google
Open Jobs: 1425. list_job_categories
Discover supported job types and experience levels (no API call).
Example:
list_job_categories()Response:
Supported Job Categories
Job Types:
- Full-time
- Part-time
- Contract
- Temporary
- Internship
Experience Levels:
- Entry-level
- Mid-level
- Senior
- Executive
Note: Not all filters may be available for all searches on LinkedIn.Rate Limiting & Error Handling
How Rate Limiting Works
Request Throttle — Server waits
LINKEDIN_REQUEST_DELAYseconds between API callsTimestamp Tracking — Each request timestamp is logged for debugging
Sleep Before Request — If requests come too fast, the server sleeps to enforce delay
Common Errors & Solutions
❌ "LinkedIn rate limit reached"
Error: LinkedIn rate limit reached. Please wait 5-10 minutes before retrying.Solution: Increase LINKEDIN_REQUEST_DELAY to 3-5 seconds, or wait and retry.
❌ "LinkedIn blocked the request (HTTP 403)"
Error: LinkedIn blocked the request (HTTP 403). Your IP may be temporarily banned.
Wait 24-48 hours before retrying.Solution: Your IP is temporarily blocked by LinkedIn. Wait 24-48 hours, then retry with higher delay.
❌ "Failed to search jobs"
Error: Failed to search jobs: [detailed error message]Solution: Check your internet connection, keywords, and location. Review logs for details.
Logging
All requests and errors are logged to stdout with timestamps.
Log format:
2026-06-10 14:30:45,123 - src.linkedin_client - INFO - Searching LinkedIn for: Python Developer in San Francisco
2026-06-10 14:30:47,456 - src.linkedin_client - INFO - Found 25 jobs
2026-06-10 14:30:48,789 - src.index - INFO - Tool called: search_jobs with arguments: {...}To adjust log level:
# In src/index.py, line ~20
logging.basicConfig(level=logging.DEBUG) # For verbose outputUsage Examples
Example 1: Simple Job Search
Claude: "Find me Python developer jobs in San Francisco"
→ Tool Call: search_jobs(
keywords="Python Developer",
location="San Francisco, CA",
limit=25
)
→ Result: [25 job listings with titles, companies, salaries]Example 2: Search with Filters
Claude: "Find senior-level data scientist jobs in NYC, full-time, posted in the last 7 days"
→ Tool Call: search_jobs(
keywords="Data Scientist",
location="New York, NY",
job_type="full-time",
experience_level="senior",
hours_old=168,
limit=20
)
→ Result: [20 filtered job listings]Example 3: Company Research
Claude: "How many open positions does Google have on LinkedIn?"
→ Tool Call: fetch_company_profile(company_name="Google")
→ Result:
LinkedIn URL: https://www.linkedin.com/search/results/companies/?keywords=Google
Open Jobs: 142Example 4: Multi-Step Job Hunt
Turn 1: Claude searches for jobs
→ search_jobs(keywords="ML Engineer", location="Remote", limit=30)
Turn 2: Claude asks for company info on top candidates
→ fetch_company_profile(company_name="Anthropic")
Turn 3: Claude filters results by salary
→ filter_jobs(salary_min=150000, salary_max=250000)Performance & Limitations
Performance
Operation | Latency | API Calls |
| 2-10 seconds | 1 |
| 2-5 seconds | 1 |
| <1 second | 0 (local) |
| 2-10 seconds | 1 |
| <1 second | 0 (local) |
Limitations
⚠️ JobSpy Limitations:
Limited job description text extraction (full details require visiting LinkedIn URL)
Company profile data is minimal (name, URL, job count only)
Salary data may be incomplete on LinkedIn
⚠️ Rate Limiting:
Default 2-second throttle means max ~30 jobs per minute
LinkedIn may impose additional limits if too many requests from same IP
No guaranteed uptime—LinkedIn can block access at any time
⚠️ Data Freshness:
Job listings are real-time from LinkedIn
Salaries and benefits may not be up-to-date
Closed jobs may still appear briefly in results
Development
Project Dependencies
mcp — Model Context Protocol SDK
jobspy — LinkedIn job scraper
pydantic — Data validation & type hints
python-dotenv — Environment variable support
Code Structure
src/linkedin_client.py:
LinkedInJobClientclass — Main client with rate limitingJobListingPydantic model — Job data structureCompanyProfilePydantic model — Company data structure
src/index.py:
MCP server setup and tool definitions
Tool handlers (search, details, filter, company, categories)
Error handling and formatting
Extending the Server
To add a new tool:
Define the tool schema in
get_tools()(src/index.py)Implement handler in
linkedin_client.pyAdd MCP handler in
handle_call_tool()(src/index.py)Document in this README
Example:
# 1. In linkedin_client.py
def my_new_feature(self, param: str) -> dict:
"""Implementation"""
pass
# 2. In index.py, add to get_tools():
Tool(
name="my_tool",
description="...",
inputSchema={...}
)
# 3. In handle_call_tool():
elif name == "my_tool":
return await handle_my_tool(arguments)
# 4. Create handler:
async def handle_my_tool(arguments: dict):
...Troubleshooting
Issue: ModuleNotFoundError: No module named 'mcp'
Solution:
pip install -r requirements.txtIssue: Connection timeout to LinkedIn
Solution:
Check internet connection
Verify LinkedIn is accessible from your IP (not blocked)
Increase
LINKEDIN_REQUEST_DELAYto reduce request frequency
Issue: Empty search results
Solution:
Try different keywords (LinkedIn may have strict matching)
Expand location (try "United States" instead of specific city)
Check if jobs exist on LinkedIn directly
Issue: Server won't start
Solution:
# Verify Python version
python --version # Should be 3.10+
# Check dependencies
python -c "import mcp; import jobspy; print('OK')"
# Run with verbose logging
PYTHONUNBUFFERED=1 python src/index.pySecurity Considerations
Current Implementation
✅ Parameterized inputs (no SQL injection risk)
✅ Request throttling (prevents IP bans)
✅ Graceful error handling (no sensitive info leakage)
✅ Local-only operation (no cloud storage)
For Production Use
⚠️ Consider adding:
IP rotation for high-volume searches
Request caching (SQLite) to reduce API calls
User rate limiting (per-user request quotas)
Audit logging (track who searches what)
API key authentication (if exposing over network)
FAQ
Q: Will LinkedIn ban my IP?
A: Unlikely with the default 2-second throttle. LinkedIn allows scraping via JobSpy. Higher request rates or aggressive filtering may trigger temporary blocks (24-48 hours).
Q: Can I search all job boards at once?
A: No, this server is LinkedIn-only. Use JobSpy directly for multi-source searches.
Q: How many jobs can I search per day?
A: Unlimited theoretically, but LinkedIn may rate-limit or block after 1000+ requests/hour.
Q: Can I save job listings locally?
A: Not in this version. Extend with SQLite caching if needed.
Q: Does this tool post on LinkedIn?
A: No, it's read-only. Cannot apply to jobs, message recruiters, or modify profiles.
References
License
MIT License — See LICENSE file for details.
Support
For issues, questions, or feature requests:
Check the Troubleshooting section above
Review Logs for detailed error messages
Verify your Configuration (request delay, credentials, internet)
Last Updated: June 10, 2026
Version: 1.0.0
Status: Production Ready
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Tarunuppu/linkedIn-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server