关于 mcp-job-search
mcp-job-search 是供 AI 编码 Agent 使用的求职 MCP 服务,涵盖职位搜索、页面提取、PDF 渲染、可配置的简历检查和申请记录管理;简历撰写、事实核验与申请提交仍由人或调用它的助手负责。
主要功能
- 01搜索多个来源的职位
- 02按 URL 提取职位信息
- 03将 HTML 简历渲染为 PDF
- 04按 YAML 规则检查简历
- 05记录并更新申请状态
适用场景
- 01搜索支持来源中的职位
- 02按自定义规则检查简历草稿
- 03将 HTML 简历转换为 PDF
- 04记录申请并更新其状态
MCP 相关
向 MCP 客户端提供七种求职及申请管理工具,包括 search_jobs、fetch_job_posting、lint_cv 和申请记录操作。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
7收录的工具列表 · 更新于 1 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| sources | any | 否 | 限制为这些来源名称,例如 ['arbeitnow']。默认:全部。 |
| keywords | string | 是 | 要匹配的关键词,例如 'PHP Magento backend'。 |
| location | any | 否 | 自由文本位置筛选条件,例如 'Poland'。 |
| use_cache | boolean | 否 | 重用缓存结果。False 会强制执行新查询。 |
| remote_only | boolean | 否 | 仅返回标记为远程办公的招聘信息。 |
详细介绍
mcp-job-search
一个 MCP 服务,可借助 AI 编码助手自动处理求职过程中重复繁琐的事务,同时有意不自动处理需要人工参与的部分:撰写简历/求职信、根据你的真实经历核实陈述,以及提交申请。
它回答的是那个总在求职过程中耗费时间的问题:“这份简历草稿看起来不错,但它有没有悄悄编造内容?这个具体的职位信息究竟值不值得看?”
状态:早期阶段。 本项目最初供个人使用;之所以发布,是因为可配置的防编造检查器和申请登记工具不只对一个人的求职有用。七个工具目前均可运行。变更内容和已进行的实时验证,请参阅
CHANGELOG.md。
与其他求职 MCP 服务有何不同
已有一些开源 MCP 服务提供求职搜索和简历定制功能(例如 not-boring-resume-mcp、resume-mcp、Workopia MCP、IAM MCP Server、LinkedIn MCP Server 等)。本项目关注的是它们未覆盖的方面:
- 即使不声张,它也不会突破机器人检测屏障。 NoFluffJobs、JustJoin.it 等波兰 IT 招聘网站没有公开搜索 API——
fetch_job_posting会读取你已找到的单个 URL,而不会索引它们的职位列表;对于已确认有主动 Cloudflare 挑战防护的网站(Pracuj.pl、Indeed),它会明确报错,而不是尝试自动破解挑战。请参阅下方已验证覆盖范围表——这是明确记录的边界,并非未被发现的缺口。 - 防编造检查器是可配置的规则引擎,而非硬编码的文本。 在调研过的替代方案中,没有一个提供强制执行你自己的禁用短语列表、成就权重规则或必需条款的方式——
lint_cv会从你控制的 YAML 文件中读取这些规则,因此尽管所核查事实是个人专属的,整个机制仍可复用(请参阅下文“为什么需要可配置的检查器”)。 - 它不会代你撰写或核实事实,这是有意为之。 简历/求职信的撰写,以及对每项陈述进行对抗式核验、确认其可追溯至真实经历,仍由调用这些工具的 AI 助手负责——本服务是处理流程的工具层(搜索、抓取、渲染、检查、记录),而不是一个较弱的内置大模型调用,去重复执行调用它的助手在完整上下文中本已更擅长的判断。
本服务不会冒充成什么: 它并不覆盖所有招聘网站——只支持拥有真实 API 的网站,或由人工找到的单个职位 URL。它绝不会代你提交任何内容。而一次干净的 lint_cv 检查并不意味着简历诚实,只表示它通过了你编写的特定规则——语义层面的编造(把两个真实事实组合成听起来像假的事实)仍需由人工或独立的对抗式审查来发现。
安装
从 PyPI 安装(发布名称为 mcp-job-search-mp——mcp-job-search 已被另一个无关项目占用;命令仍为 mcp-job-search):
pip install mcp-job-search-mp
# or, for an isolated tool install:
uvx mcp-job-search-mp
从源码安装,用于开发:
git clone https://github.com/michalper/mcp-job-search.git
cd mcp-job-search
python3.12 -m venv .venv
.venv/bin/pip install -e ".[dev]"
连接到 Claude Code
{
"mcpServers": {
"job-search": {
"command": "/absolute/path/to/mcp-job-search/.venv/bin/mcp-job-search",
"env": {
"LINT_RULES_PATH": "/absolute/path/to/your/lint_rules.yaml",
"REGISTRY_CONFIG_PATH": "/absolute/path/to/your/registry.yaml"
}
}
}
}
通过环境变量配置——所有变量均为可选项,未设置时,每个工具都会优雅降级:
| 变量 | 使用方 | 默认值 |
|---|---|---|
ADZUNA_APP_ID、ADZUNA_APP_KEY | search_jobs | 未设置——跳过 Adzuna |
ADZUNA_COUNTRY | search_jobs | pl |
RAPIDAPI_JSEARCH_KEY | search_jobs | 未设置——跳过 JSearch |
JSEARCH_COUNTRY | search_jobs | us(JSearch 自身的 API 默认值) |
LINT_RULES_PATH | lint_cv | 随附的 src/mcp_job_search/examples/lint_rules.example.yaml |
REGISTRY_CONFIG_PATH | log_application | 随附的 src/mcp_job_search/examples/registry.example.yaml |
CHROME_PATH | render_pdf | 自动检测(macOS 应用程序包、Linux $PATH、常见 Windows 安装目录) |
SEARCH_CACHE_DIR | search_jobs | ~/.cache/mcp-job-search/search |
SEARCH_CACHE_TTL_SECONDS | search_jobs | 21600(6 小时) |
Adzuna 和 JSearch 免费套餐限制
Adzuna 的免费套餐提供 25 次一次性测试调用,之后需使用付费套餐(每月 £8,可调用 5,000 次)——测试结束后请合理规划调用次数。JSearch 的免费套餐每月有 200 次请求;search_jobs 会按查询缓存结果(SEARCH_CACHE_DIR/SEARCH_CACHE_TTL_SECONDS,默认 6 小时),专门用于避免重复的相同查询消耗配额——确实需要获取最新结果时,可传入 use_cache=False 强制重新查询。
有主动机器人检测的网站
无论请求多么具体,fetch_job_posting 都不会尝试自动解决任何网站上的 CAPTCHA 或机器人检测挑战——已通过响应标头确认,Pracuj.pl 和 Indeed(pl.indeed.com)都受到主动 Cloudflare 挑战保护(cf-mitigated: challenge/带有 Cloudflare 机器人管理 Cookie 的 401 响应),并非只是缺少 JavaScript 的问题。由真人操作的真实浏览器会正常通过这两种检测——遇到这类页面时,请使用真实浏览器阅读,而不要使用此工具。
示例:查看 lint_cv 如何检查简历

此处的简历草稿(tests/fixtures/sample_cv_with_violations.html)是故意填入问题的;lint_cv 使用的是随附的通用示例规则(src/mcp_job_search/examples/lint_rules.example.yaml),而非真实个人的信息:
{
"clean": false,
"findings": [
{"severity": "error", "message": "generic corporate jargon — replace with a concrete claim"},
{"severity": "error", "message": "unsupported superlative — ground it in a specific result or cut it"},
{"severity": "error", "message": "example: list cloud/K8s here only if you have real production experience"},
{"severity": "error", "message": "a .gitignore edit is hygiene, not an achievement"},
{"severity": "error", "message": "a commit count is not an achievement on its own"},
{"severity": "error", "message": "example: flag a title claim that contradicts your real specialization"},
{"severity": "note", "message": "link rendered as <a href> in body (https://example.com/portfolio) — use plain text"}
]
}
clean 为 false 是因为触发了实际规则,并非猜测——所有提示信息均来自 YAML 文件,而不是来自了解特定个人职业经历的代码。
工具
| 工具 | 状态 | 描述 |
|---|---|---|
search_jobs | 可用 | 可通过 Arbeitnow(免费,无需密钥)、Adzuna 和 JSearch(需要 API 密钥)进行真实搜索——已在波兰 PHP 求职市场上通过两个付费来源进行实时验证(每个来源均有 10 条真实职位,雇主名称可识别);搜索结果会缓存,以保护 JSearch 的免费额度 |
fetch_job_posting | 可用 | 使用 trafilatura 提取单个 URL 的内容——已在 JustJoin.it、NoFluffJobs、Bulldogjob、theprotocol.it、Solid.Jobs、CzyJestEldorado.pl 和 LinkedIn 单个职位页面上实时验证,提取结果干净;已确认其设计上不会绕过 Pracuj.pl/Indeed 的 Cloudflare 机器人检测挑战 |
render_pdf | 可用 | 使用无头 Chrome 将 HTML 转为 PDF,并采用可避免已知卡死/静默失败的精确标志;跨平台自动检测 CHROME_PATH;通过扫描 PDF 原始字节验证页数 |
lint_cv | 可用 | 可配置的机械检查工具——检查禁用短语、仅限技能部分的禁用项、成就权重夸大、职称/GDPR/链接,以及页数限制;所有规则均由你控制的 YAML 文件驱动 |
log_application | 可用 | 在 Markdown 求职申请登记表的正确分区和日期位置追加一行,并支持通过 column_map 映射非英语表头;绝不编造自由文本内容 |
list_applications | 可用 | 只读查询登记表(按求职平台/公司筛选)——调用 log_application 前使用此工具检查是否存在重复记录 |
update_application_status | 可用 | 原位改写一行的状态单元格;如果有多行匹配,则不会猜测 |
已验证的招聘网站覆盖情况(fetch_job_posting,2026-10-19)
| 网站 | 结果 |
|---|---|
| JustJoin.it | ✅ 提取结果干净 |
| NoFluffJobs | ✅ 提取结果干净 |
| Bulldogjob | ✅ 提取结果干净 |
| theprotocol.it | ✅ 提取结果干净 |
| Solid.Jobs | ✅ 提取结果干净 |
| CzyJestEldorado.pl(聚合平台) | ✅ 提取结果干净 |
LinkedIn(/jobs/view/<id>) | ✅ 提取结果干净——单个职位页面是公开的 |
| Jooble | 不适用——会重定向到来源网站(例如 JustJoin.it);没有自有内容可供抓取 |
| Pracuj.pl | ❌ 被拦截——存在有效的 Cloudflare 挑战,未尝试绕过 |
Indeed(pl.indeed.com) | ❌ 被拦截——存在有效的 Cloudflare 挑战,未尝试绕过 |
为什么使用可配置的检查工具,而不是硬编码规则
最初的动机是:有一次,简历草稿把两个分别属实的事实混为一谈,形成了一条听起来像虚假陈述的内容,而且在有人发现之前就已经发出。基于 grep 的机械检查可以发现禁用短语,但无法发现语义混淆——这仍然需要人工或独立的对抗性审查。机械检查工具能够可靠做到的是:每次都一致地执行你自己的禁用短语列表、页数限制和必需条款,让你无需手动反复检查相同内容。lint_cv 就是这样的工具——它是通用的,任何人都可以用它检查自己的事实陈述。
开发
.venv/bin/python -m pytest --cov # tests + coverage
.venv/bin/ruff check . # lint
.venv/bin/mypy src # types
.venv/bin/bandit -c pyproject.toml -r src # security
.venv/bin/pip-audit # dependency vulnerabilities
运行一次 .venv/bin/pre-commit install,即可在每次提交时运行以上所有检查(pip-audit 除外;它需要网络访问,因此仅在 CI 中运行)。
一项手动端到端检查(不在 CI 中运行——需要实时网络和实际安装的 Chrome),也记录在 CHANGELOG.md 中:
- 对照 Arbeitnow 实时 API 运行
search_jobs(keywords="PHP", remote_only=True, sources=["arbeitnow"])。 - 对第 1 步中的 URL 运行
fetch_job_posting(url=...)。 - 对示例简历运行
render_pdf(html_path=...),确认success和page_count。 - 对含有预置违规内容的文件运行
lint_cv(html_path=...),确认违规已报告。 - 针对你自己的登记表运行
log_application(..., dry_run=True),确认预览的行和插入位置正确后,再移除dry_run。
请参阅 CHANGELOG.md,了解各版本的变更内容。
许可证
MIT——请参阅 LICENSE。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。