filesystem-mcp-server
이력서 매처 — MCP 에디션
이력서 매칭 에이전트의 직접 파일시스템 도구를 독립형 MCP 서버로 대체하고, LangGraph 에이전트를 로컬 함수 호출 대신 실제 MCP 클라이언트를 통해 해당 서버(및 두 번째 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")]각각 별도의 OS 프로세스로 실행되는 두 개의 독립적인 MCP 서버가 있으며, 서로나 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 호출을 소모하지 않고 바로 [*]로 단락(short-circuit)되며, --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개의 테스트, 두 계층:
단위(
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 키가 필요 없습니다. 그래프 연결, 다중 서버 도구 발견, 새 파일 없음 시 단락 경로, 그리고 두 번째--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. 보호할 네트워크 표면이 없고, 연결할 인증이 없으며, 로컬 "command" 서버에 대해 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 도구는 요청/응답 방식이므로 이는 폴링입니다(파일 이름→mtime의 JSON 상태 파일을 각 호출 시 diff). 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.-