mcpField
M
mcp-job-search

mcp-job-search

ローカル
github.com/michalperビジネス・マーケティング01 週間前に更新

mcp-job-search について

mcp-job-searchは、AIコーディングエージェント向けの求職活動用MCPサーバーです。求人検索や投稿の抽出、PDF化、設定可能な履歴書チェック、応募記録を扱い、文章作成や事実確認、応募送信は人や呼び出し元に委ねます。

主な機能

  1. 01複数ソースの求人検索
  2. 02URLから求人情報を抽出
  3. 03HTML履歴書をPDF化
  4. 04YAMLルールによる履歴書チェック
  5. 05応募記録の追加とステータス更新

活用シーン

  1. 01対応ソースから求人を検索
  2. 02独自ルールで履歴書案を確認
  3. 03HTML履歴書をPDFに変換
  4. 04応募を記録してステータスを更新

MCP 対応

求人検索や応募管理の7つのツールをMCPクライアントに公開します。search_jobs、fetch_job_posting、lint_cv、応募記録の操作などを利用できます。

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

mcp.json · 共通設定
{
"mcpServers": {
"michalper-mcp-job-search": {
"command": "uvx",
"args": [
"mcp-job-search-mp"
]
}
}
}
起動コマンドuvx mcp-job-search-mp

ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。

パッケージ
pypimcp-job-search-mp0.2.0

ツール

7

掲載時のツール一覧 · 1 週間前に更新

パラメーター型必須説明
sourcesanyいいえソース名を指定して絞り込みます。例:['arbeitnow']。デフォルト:すべて。
keywordsstringはい一致させるキーワード。例:'PHP Magento backend'。
locationanyいいえ自由入力の勤務地フィルター。例:'Poland'。
use_cachebooleanいいえキャッシュされた結果を再利用します。False にすると最新の検索を強制します。
remote_onlybooleanいいえリモート勤務の求人情報のみを返します。

詳細

mcp-job-search

CI PyPI michalper/mcp-job-search MCP server License: MIT Python 3.12+ Ruff Last commit

AI コーディングアシスタントを使った就職活動で、繰り返し発生する作業を自動化するMCPサーバーです。ただし、人間が担うべき作業、つまり履歴書やカバーレターの作成、実際の経歴に照らした主張の事実確認、応募の送信は、意図的に自動化しません。

就職活動で時間を奪い続ける疑問に答えます。「この履歴書の草案は問題なさそうだけれど、気づかないうちに何かをでっち上げていないだろうか。それに、この特定の求人情報は読む価値があるのだろうか?」

ステータス:初期段階です。 個人利用向けに開発しましたが、設定可能な捏造防止リンターと応募管理ツールは、個人の就職活動に限らず汎用的に役立つため公開しました。7つのツールはすべて動作します。変更内容と実環境での検証結果については、CHANGELOG.mdをご覧ください。

他の就職活動向けMCPサーバーとの違い

すでに就職先の検索と履歴書の調整を行うオープンソースのMCPサーバーはいくつかあります(not-boring-resume-mcp、resume-mcp、Workopia MCP、IAM MCP Server、LinkedIn MCP Serverなど)。このサーバーは、そうしたツールが対応していない領域を対象にしています。

  1. ボット検出の壁を、ひそかに乗り越えようとはしません。 NoFluffJobs、JustJoin.itなどのポーランドのIT求人サイトには一般公開された検索APIがありません。fetch_job_postingは求人情報をインデックス化するのではなく、すでに見つけたURLを1件読み込みます。また、Cloudflareのチャレンジが有効な状態で設置されていることを確認済みの求人サイト(Pracuj.pl、Indeed)では、チャレンジの自動解決を試みず、明確に失敗します。検証済みの対応状況は以下の表をご覧ください。これは明記された制約であり、知られないままの欠落ではありません。
  2. 捏造防止リンターは、文章をハードコードしたものではなく、設定可能なルールエンジンです。 調査した代替ツールには、独自の禁止フレーズ一覧、実績の重み付けルール、必須条項を適用する方法がありません。lint_cvはユーザーが管理するYAMLファイルからそれらを読み込むため、検証対象となる事実は個人に関するものでも、その仕組み自体は再利用できます(詳しくは以下の「設定可能なリンターを選んだ理由」をご覧ください)。
  3. 意図的に、文章の作成や事実確認を代行しません。 履歴書やカバーレターの文章作成と、すべての主張が事実に基づいているかを敵対的に検証する作業は、これらのツールを呼び出すAIアシスタントに任せます。このサーバーは検索、取得、整形、検査、記録を行う仕組みの層であり、呼び出し元のアシスタントがすでに十分なコンテキストを使って、より適切に行っている判断を、機能の劣るLLM呼び出しとして重複させるものではありません。

このサーバーが装っていないもの: あらゆる求人サイトに対応しているわけではありません。対応するのは、実際にAPIを提供しているサイトか、人間がすでに見つけた単一の求人URLだけです。ユーザーに代わって何かを送信することもありません。また、lint_cvが正常に完了しても、履歴書に虚偽がないことを意味するわけではありません。ユーザーが記述した特定のルールを通過したというだけです(2つの事実を組み合わせて、誤解を招く内容にするような意味上の捏造を検出するには、依然として人間による確認か、独立した敵対的レビューが必要です)。

インストール

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_KEYsearch_jobs未設定 — Adzuna はスキップ
ADZUNA_COUNTRYsearch_jobspl
RAPIDAPI_JSEARCH_KEYsearch_jobs未設定 — JSearch はスキップ
JSEARCH_COUNTRYsearch_jobsus(JSearch 独自の API デフォルト)
LINT_RULES_PATHlint_cv同梱の src/mcp_job_search/examples/lint_rules.example.yaml
REGISTRY_CONFIG_PATHlog_application同梱の src/mcp_job_search/examples/registry.example.yaml
CHROME_PATHrender_pdf自動検出(macOS アプリバンドル、Linux の $PATH、一般的な Windows のインストール先)
SEARCH_CACHE_DIRsearch_jobs~/.cache/mcp-job-search/search
SEARCH_CACHE_TTL_SECONDSsearch_jobs21600(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)の両方が、単なる JavaScript の不足ではなく、有効な Cloudflare チャレンジ(cf-mitigated: challenge/Cloudflare のボット管理 Cookie を伴う 401)の背後にあることを確認しています。人が操作する実際のブラウザーセッションなら、どちらも通常どおり表示できます。このようなページは、このツールではなく実際のブラウザーで読んでください。

例:lint_cv の判定方法で CV をチェックする

用意した CV の下書きに対して lint_cv を実行し、企業用語、根拠のない最上級表現、裏付けのないクラウド関連の主張、.gitignore の編集やコミット数を実績として記載している点、実際の専門分野と矛盾する肩書き、プレーンテキストにすべきリンクの 7 件を報告

ここで使用している 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 の応募記録に、適切なセクションと日付位置で1行追加します。英語以外のヘッダーに対応する column_map を備えています。自由記述の内容を作り出すことはありません
list_applications動作中応募記録に対する読み取り専用のクエリです(求人サイト/会社で絞り込み可能)。重複を確認するため、log_application の前に使用してください
update_application_status動作中1行のステータスセルをその場で書き換えます。複数の行が一致した場合は推測せず、処理を拒否します

検証済みの求人サイト対応状況(fetch_job_posting、2026-10-19)

サイト結果
JustJoin.it✅ クリーンに抽出
NoFluffJobs✅ クリーンに抽出
Bulldogjob✅ クリーンに抽出
theprotocol.it✅ クリーンに抽出
Solid.Jobs✅ クリーンに抽出
CzyJestEldorado.pl(アグリゲーター)✅ クリーンに抽出
LinkedIn(/jobs/view/<id>)✅ クリーンに抽出 — 単一求人の表示ページは公開されています
JoobleN/A — 求人の掲載元サイト(例:JustJoin.it)にリダイレクトされるため、独自に取得できる情報はありません
Pracuj.pl❌ ブロック — Cloudflare のチャレンジが有効なため、試行していません
Indeed(pl.indeed.com)❌ ブロック — Cloudflare のチャレンジが有効なため、試行していません

ハードコードされたリンターではなく、設定可能なリンターを採用する理由

当初の動機は、CV の草案で、別々の正しい事実2つを誤解を招く1つの主張にまとめてしまい、誰も気づかないまま公開されたことでした。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 を一度実行すると、上記すべて(ネットワークアクセスが必要で CI 専用の pip-audit を除く)が、コミットごとに実行されます。

手動のエンドツーエンドチェックを1つ実行します(CI では実行されません — ライブネットワークと実際の Chrome のインストールが必要です)。このチェックは CHANGELOG.md にも記載されています。

  1. ライブの Arbeitnow API に対して search_jobs(keywords="PHP", remote_only=True, sources=["arbeitnow"]) を実行します。
  2. 手順1で取得した URL に対して fetch_job_posting(url=...) を実行します。
  3. サンプル CV に対して render_pdf(html_path=...) を実行し、success と page_count を確認します。
  4. 違反を仕込んだファイルに対して lint_cv(html_path=...) を実行し、違反が報告されることを確認します。
  5. 自分の応募記録に対して log_application(..., dry_run=True) を実行し、dry_run を外す前に、プレビューされた行と挿入位置が正しいことを確認します。

各リリースでの変更内容については、CHANGELOG.md を参照してください。

ライセンス

MIT — LICENSE を参照してください。

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。