使用说明
MCP Job Search — LinkedIn tools, Document utilities, and Prompt agents
This workspace includes two MCP servers (LinkedIn and Document tools) plus a set of ready‑to‑use job search prompt agents. It enables live LinkedIn discovery via a thin, dynamic wrapper and local resume/job‑doc utilities like Markdown→PDF and PDF→text.
Warning: The third‑party linkedin-api package uses undocumented LinkedIn endpoints and may violate LinkedIn’s Terms of Service. Prefer official APIs where possible and use at your own risk.
What’s included
src/linkedin_mcp.py— Thin client aroundlinkedin_api.linkedin.Linkedinwith:list_methods(...)to discover callable methods with signatures/docscall_method(...)to invoke any allowed public method dynamically- Convenience wrappers (e.g.,
search_jobs,get_job,get_profile) for backwards compatibility
src/linkedin_tools.py— MCP server exposing dynamic LinkedIn tools:li_build_session()— ensure a LinkedIn session is authenticatedli_methods(include_private=False, prefix=None)— list available methodsli_call(method, args=None, posargs=None)— call any allowed method
src/doc_tools.py— MCP server “doc-tools” for resume/job docs with:check_prereqs()— detectpandoc,xelatex(MiKTeX),wkhtmltopdf,pdftotext; returns{ ok, tools, notes }md_to_pdf(md_path, out_path?, method?, page?, margin_*)— reliable Markdown→PDF viapandoc-xelatex(preferred) orwkhtmltopdfpdf_to_text(pdf_path, out_path?, layout=False)— extract text usingpdfminer.six
.github/prompts/— prompt agents for job search workflows:AI_JobSearch_Aggregator.prompt.md— searches across sources, de‑duplicates, scores fit, and outputs a Job Digest (Markdown)AI_CV_CoverLetter_Tailor.prompt.md— tailors a CV (Markdown) and crafts a customized cover letter from a job digest/JDRecrutting_consultant.prompt.md— end‑to‑end AI Job Search Agent producing Top 5 matches, improvements, strategy, and outreach; prefers LinkedIn MCP when available
Requirements
- Python ≥ 3.13 (per
pyproject.toml) - Python packages (from
requirements.txt):mcp,mcp[cli],requests,linkedin-api,pdfminer.six>=20221105
- Optional native tools for
doc-tools(recommended on Windows):- Pandoc —
winget install --id=JohnMacFarlane.Pandoc -e - MiKTeX (XeLaTeX) —
winget install --id=MiKTeX.MiKTeX -e - wkhtmltopdf —
winget install --id=wkhtmltopdf.wkhtmltopdf -e - Poppler (pdftotext) — optional;
pdf_to_textusespdfminer.sixby default
- Pandoc —
Setup (Windows PowerShell)
You can use the helper src/env.ps1 to set environment variables for the current shell session.
# (Optional) Create and activate a virtual environment
python -m venv .venv
.\.venv\Scripts\Activate.ps1
# Install dependencies
pip install -r requirements.txt
# Configure LinkedIn credentials for this session
$env:LINKEDIN_EMAIL = "your-email@example.com"
$env:LINKEDIN_PASSWORD = "your-password"
# Alternatively, if you have a valid LI_AT cookie token
# $env:LINKEDIN_LI_AT = "<li_at_cookie_value>"
# Or source the helper (adjust values inside as needed)
./src/env.ps1
Notes
- Use either
LINKEDIN_EMAIL+LINKEDIN_PASSWORDorLINKEDIN_LI_AT(cookie). The current code prefers username/password by default.
Running the MCP servers
Both servers are simple FastMCP processes speaking over stdio. Run whichever you need.
# LinkedIn tools server
python .\src\linkedin_tools.py
# Document tools server (Markdown↔PDF, PDF→text)
python .\src\doc_tools.py
Tools exposed (LinkedIn)
li_build_session()— initialize and authenticate- Response:
{ "ok": true, "auth": "username_password" | "LI_AT" }
- Response:
li_methods(include_private: bool = false, prefix?: string)— list callable methodsli_call(method: string, args?: object, posargs?: any[])— dynamic invocation
Example tool requests (shape depends on your MCP client):
{
"tool": "li_build_session",
"params": {}
}
{
"tool": "li_methods",
"params": { "prefix": "search_" }
}
{
"tool": "li_call",
"params": {
"method": "search_jobs",
"args": { "keywords": "AI", "location_name": "Germany", "limit": 10 }
}
}
Notes
- Argument names must match the reported signatures. For example,
search_jobsuseslocation_name(notlocation). - Private methods (names starting with
_) are blocked.
Tools exposed (Document tools)
check_prereqs()- Returns availability of
pandoc,xelatex,wkhtmltopdf,pdftotextand Windows‑friendly install tips. - Shape:
{ ok: boolean, tools: { .. }, notes: string[] }
- Returns availability of
md_to_pdf(md_path, out_path?, method = "pandoc-xelatex" | "wkhtmltopdf", page = "a4", margin_top = "0.7in", margin_bottom = "0.7in", margin_left = "1in", margin_right = "1in")- Prefers Pandoc + XeLaTeX for consistent typography; falls back to Pandoc default engine if XeLaTeX missing; or Pandoc→HTML→wkhtmltopdf.
- Returns
{ ok, path, method, logs }with executed command logs.
pdf_to_text(pdf_path, out_path?, layout = false)- Uses
pdfminer.six(pure Python). If not installed, raises a tool error with install hint. - Returns
{ ok, path, bytes, logs, layout }.
- Uses
Example requests:
{ "tool": "check_prereqs", "params": {} }
{
"tool": "md_to_pdf",
"params": { "md_path": ".\\ATS\\Resume.md", "method": "pandoc-xelatex" }
}
{
"tool": "pdf_to_text",
"params": { "pdf_path": ".\\docs\\job-posting.pdf" }
}
Prompt agents (in .github/prompts/)
Use these with your MCP‑enabled IDE/agent runner to orchestrate the workflow end‑to‑end.
-
AI_JobSearch_Aggregator.prompt.md-
Searches across configured sources (e.g., LinkedIn, Indeed, Xing, StepStone, company sites), applies filters, de‑duplicates, and produces a scored Markdown Job Digest with metadata (tools used, totals, timestamps).
-
Accepts profile and search parameters via variables; prefers platform tools (LinkedIn MCP) when available, falls back to web search.
-
Reads a job digest/JD and a base CV (Markdown) to output a perfectly aligned CV and a 250–300 word customized cover letter.
-
Emphasizes ATS keywords, quantified achievements, and company‑specific tone; keeps formatting export‑ready.
-
-
Recrutting_consultant.prompt.md- Acts as an AI Job Search Agent: returns Top 5 matches with Fit Scores, skill match, company insights, recommendations, tailored outreach and short cover letters per top match, plus a step‑by‑step application strategy.
- If LinkedIn MCP access is provided, it must verify posting dates and open status before recommending.
- Includes an instruction to optionally generate per‑job
.prompt.mdfiles for tailoring and to log non‑sensitive tool usage.
Example slash usage (from the aggregator file):
/AI_JobSearch_Aggregator: name=Hemanth Yadav location=Germany, Remote roles=Embedded Test Engineer,Data Engineer skills=Python,SQL,C++,Automation limit=20 postedWithinDays=21
Using the Python client directly (optional)
from src.linkedin_mcp import LinkedInClient
cli = LinkedInClient()
cli.search_jobs(keywords="AI", location="Germany", limit=5)
# Fully dynamic invocation
jobs = cli.call_method("search_jobs", args={"keywords": "AI", "location_name": "Germany", "limit": 5})
me = cli.call_method("get_profile", args={"public_id": "me"})
Troubleshooting
- LinkedIn auth: Missing
LINKEDIN_EMAIL/LINKEDIN_PASSWORDorLINKEDIN_LI_AT→ set environment variables (see Setup). - LinkedIn auth changes or cookies may break login; try updating
linkedin-apior switching auth mode. - Rate limiting/suspension risks exist; reduce request volume.
- Document tools: If
pandoc/xelatex/wkhtmltopdfare missing, runcheck_prereqs()for Windows‑friendly install tips;pdf_to_textneedspdfminer.six(listed inrequirements.txt).
Legal and ToS
This project is for educational purposes. Interacting with LinkedIn via undocumented endpoints may violate their Terms of Service. You are responsible for compliance with all applicable terms and laws.
Security & Secrets
- Never commit real passwords, OAuth client secrets, or cookie tokens. The file
src/env.ps1contains only placeholder values. - Set sensitive values per‑session (e.g.,
$env:LINKEDIN_EMAIL = "you@example.com") or use a secrets manager. - Rotate any credentials previously stored in plaintext.
- Keep debug output minimal and avoid dumping large payloads.
- Never commit real passwords, OAuth client secrets, or cookie tokens. The file
src/env.ps1contains only placeholder values.