filesystem-mcp-server
Resume Matcher — MCP Edition
履歴書マッチングエージェントの直接的なファイルシステムツールを、スタンドアロンのMCPサーバーに置き換え、さらにLangGraphエージェントを、ローカル関数呼び出しの代わりに実際のMCPクライアントを通じて(そして2つ目のMCPサーバーとも)通信するようにリファクタリングしたものです。
学習目標 → このリポジトリの内容
目標 | 場所 |
Model Context Protocolを理解する |
|
カスタムツールをMCPサーバーに置き換える | Milestone 1のすべてのファイルシステム操作は現在 |
標準化されたツールインターフェースを実装する | すべてのツールで一貫した |
本番対応システムをデプロイする | 環境変数ベースの設定、制限付き並行性、部分失敗の処理、テスト済みの環境変数転送修正、ユニット+プロトコル層にわたる14の合格テスト |
Related MCP server: Filesystem MCP Server
アーキテクチャ
flowchart LR
subgraph "Agent process (matching_agent.py)"
A["LangGraph StateGraph"] --> B["MultiServerMCPClient"]
A --> L["Claude (LLM)\nstructured scoring"]
end
B <-->|"JSON-RPC 2.0 / stdio"| C["filesystem_mcp_server.py"]
B <-->|"JSON-RPC 2.0 / stdio"| D["notifications_mcp_server.py"]
C --> E[("sample_data/resumes/\nresults/")]
D --> F[("results/notifications.log")]2つの独立したMCPサーバーは、それぞれ別のOSプロセスであり、互いやLangGraphについての知識はありません。エージェントは起動時にそれらのツールを発見し(client.get_tools())、名前で呼び出します。これがリファクタリングの要点です。filesystem_mcp_server.py が明日新しいツールを追加しても、matching_agent.py はコード変更を必要としません。
ステートマシン(エージェント ↔ MCP インタラクション)
stateDiagram-v2
[*] --> check_new_resumes
check_new_resumes --> batch_extract: new files found
check_new_resumes --> [*]: nothing new — short-circuit
batch_extract --> match: text extracted
match --> rank_and_save: LLM structured scoring
rank_and_save --> notify: results persisted
notify --> [*]: done
note right of check_new_resumes
filesystem server
tool: watch_directory
end note
note right of batch_extract
filesystem server
tool: batch_process
end note
note right of rank_and_save
filesystem server
tool: save_match_result (per match)
end note
note right of notify
notifications server
tool: send_match_notification
(only matches scoring >= 70)
end notecheck_new_resumes が最初に watch_directory を呼ぶのは(他の何かに触れる前に)意図的です。新しいものが何もない実行は、LLM呼び出しを費やさずに直接 [*] にショートサーキットし、--watch モード(下記参照)は毎回ディレクトリ全体ではなく、実際に変更されたものだけを再処理します。
ローカルでの実行
リポジトリのルートから、仮想環境を作成し、依存関係をインストールします。
Bash / Git Bash / Linux / macOS
cd [Path To Files]
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt
export ANTHROPIC_API_KEY="<your-anthropic-api-key>"
python matching_agent.pyWindows PowerShell
cd [Path To Files]
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install -r requirements.txt
$env:ANTHROPIC_API_KEY = "<your-anthropic-api-key>"
python .\matching_agent.py受信トレイを最初から再スキャンしたい場合
ウォッチャーは小さな状態ファイルを保持し、新しく追加された履歴書のみをスコアリングします。現在のフォルダを再度処理したい場合は、まずウォッチャーの状態をクリアしてください:
python matching_agent.py --reset-watch一般的な使用パターン
# one pass over the bundled sample data
python matching_agent.py
# run against your own job description and resume folder
python matching_agent.py --job-description path/to/jd.txt --resume-dir path/to/resumes
# keep polling for newly added resumes every 15s (Ctrl+C to stop)
python matching_agent.py --watch --interval 15エージェントを実行するときは、システムのPythonではなく、プロジェクトのvenvのPythonを使用してください。このリポジトリでは、Windowsでは通常
./.venv/Scripts/python.exe matching_agent.py、Unix系シェルではsource .venv/bin/activate && python matching_agent.pyが動作するコマンドです。
どちらかのサーバーをスタンドアロンで実行して直接触ってみてください(MCP Inspector と一緒に使うと便利です):
python filesystem_mcp_server.py
python notifications_mcp_server.py設定は環境変数で駆動されます — filesystem_mcp_server.py の ServerConfig.from_env() を参照してください:
変数 | デフォルト |
|
|
|
|
|
|
|
|
|
|
|
|
テスト
pytest tests/ -v14のテスト、2つのレイヤー:
ユニット (
test_filesystem_mcp_server.py、大部分): ツール関数をtmp_pathフィクスチャに対して直接呼び出します — 高速で、サブプロセスはありません。成功パス、RESUME_NOT_FOUND/INVALID_PARAMSエラーコード、batch_processの部分失敗レポートをカバーします。プロトコル (
test_server_speaks_mcp_protocol_over_stdio): 実際のサーバーをサブプロセスとして起動し、公式のmcpクライアントSDK —tools/list、tools/call、resources/read— を実際のJSON-RPC 2.0上で駆動します。つまり、プロトコル層を証明しており、その下のPythonだけではありません。エージェント (
test_matching_agent.py): LLM呼び出しは決定論的なフェイク (FakeStructuredModel) に置き換えられているため、APIキーは不要です。グラフの配線、マルチサーバーのツール発見、新規ファイルなしのショートサーキットパス、そして2回目の--watchスタイルのパスがディレクトリ全体ではなく新しく到着したファイルだけを再処理することを確認しています。
設計上の決定
MCP SDKは mcp>=1.28,<2.0 に固定されています。 Python SDKのv2系は2026-07-28のMCP仕様改訂とともにリリースされ、FastMCP を MCPServer(現在は mcp.server.mcpserver の下)に改名しました。v1.xは現在のLangChain/LangGraph MCPエコシステムが構築され、文書化されているバージョンであるため、このプロジェクトは偶然ではなく意図的にv1.xに固定しています。langchain-mcp-adapters とより広いチュートリアル基盤がv2に対応したら再検討する価値があります。
HTTPではなくstdio。 保護すべきネットワーク面がなく、認証を配線する必要もなく、ローカルの「コマンド」サーバーに対して MultiServerMCPClient が期待するものです。これを構築中に確認したトレードオフ:各ツール呼び出しは再利用ではなく新しいサブプロセスセッションを開きます — デモ/CLIエージェントには問題ありませんが、レイテンシに敏感な本番バージョンが代わりに長寿命の streamable-http サーバーに移行する正直な理由です。
エラーは散文ではなく構造化されたJSONです。 すべての失敗は、JSON-RPCの「サーバーエラー」範囲(-32000..-32099)の code と、機械可読な error ラベル(RESUME_NOT_FOUND、DIRECTORY_NOT_FOUND、UNSUPPORTED_FILE_TYPE、EXTRACTION_FAILED、INVALID_PARAMS)を運ぶJSONペイロードを持つ ToolError を発生させます。ライブクライアントセッションに対してエンドツーエンドで確認済み:CallToolResult(isError=True, ...) として表面化し、matching_agent.py の _call_tool() は、呼び出し側がメッセージを文字列マッチングする代わりに、コードをそのまま保持した MCPToolCallError として再発生させます。
watch_directory はポーリングであり、プッシュではありません。 MCPツールはリクエスト/レスポンスなので、これはinotify/watchdogリスナーではなくポーリング(ファイル名→mtimeのJSON状態ファイルを各呼び出しで差分比較)です。matching_agent.py の --watch モードがそれをライブ感のあるものに変えています — MCPリソースのサブスクリプションを通じてプッシュするバックグラウンドリスナーが自然な次のステップであり、プロトコルでサポートされていますが、ここでは範囲外です。
batch_process はディレクトリだけでなく、明示的なファイルリストを受け取ります。 これにより、check_new_resumes → batch_extract は毎回フォルダ全体ではなく、watch_directory がちょうど報告したものだけを再処理できます — 並行性(asyncio.Semaphore(MAX_BATCH_CONCURRENCY))が、リストが長いときに仕様の「効率的」を実際に真にしているのです。
環境変数の転送は明示的であり、スキップできるデフォルトではありません。 これを構築中に実際に遭遇した落とし穴:mcp のstdioクライアントは親プロセスの環境を継承しません — 子サーバーを最小限のデフォルト(PATH/HOME/TERM のみ)で起動します。これは mcp.client.stdio.get_default_environment() に対して直接確認済みです。matching_agent.py のサーバー設定で env=dict(os.environ) を明示的に渡さないと、RESUME_DIRECTORY などは静かに filesystem_mcp_server.py に届きません — エージェントは実行され、ツールの発見も問題なく、ただ静かに間違ったディレクトリで動作します。デバッグセッションを費やす前に知っておく価値があります。
リポジトリ構造
resume-matcher-mcp/
├── filesystem_mcp_server.py # Part A
├── notifications_mcp_server.py # Part B bonus: 2nd MCP server
├── matching_agent.py # Part B
├── requirements.txt
├── pytest.ini
├── tests/
│ ├── test_filesystem_mcp_server.py
│ └── test_matching_agent.py
├── sample_data/
│ ├── job_description.txt
│ └── resumes/ # 21 resumes, deliberately strong/partial/weak fit
└── results/ # match_results.jsonl + notifications.log (gitignored)This server cannot be deployed
Maintenance
Related MCP Connectors
Document processing over MCP: merge, split and compress PDFs, run OCR, extract document text.
Build, version and render resumes as PDFs from Claude or any MCP client.
Hosted MCP tools for FFmpeg-style video and audio processing through FFMPEG API.
Patents MCP — wraps the USPTO Open Data Portal (ODP) Patent File Wrapper API
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables file system operations (read, write, list, search, watch, batch process) via MCP over JSON-RPC 2.0, used by a resume matching agent.-
- FlicenseNot gradedqualityDmaintenanceProvides file system tools for resume matching agents, enabling reading, writing, searching, listing, watching, and batch processing of files via the Model Context Protocol.-
- FlicenseNot gradedqualityCmaintenanceProvides MCP tools for reading, listing, writing, searching, watching, and batch-processing files, enabling automated file management and resume matching workflows.-
- FlicenseNot gradedqualityCmaintenanceEnables MCP clients to interact with a filesystem by listing, reading, writing, and monitoring files, as well as extracting resume text and batch processing files.-