Skip to main content
Glama
GAVTIN

filesystem-mcp-server

by GAVTIN

이력서 매처 — MCP 에디션

이력서 매칭 에이전트의 직접 파일시스템 도구를 독립형 MCP 서버로 대체하고, LangGraph 에이전트를 로컬 함수 호출 대신 실제 MCP 클라이언트를 통해 해당 서버(및 두 번째 MCP 서버)와 통신하도록 리팩터링한 프로젝트입니다.

학습 목표 → 이 저장소의 구성

목표

위치

Model Context Protocol 이해

filesystem_mcp_server.py는 도구 리소스를 구현하며, tests/에서 실제 JSON-RPC 2.0 와이어 프로토콜에 대해 테스트됨(모킹 아님)

커스텀 도구를 MCP 서버로 대체

Milestone 1의 모든 파일시스템 작업이 이제 @mcp.tool()로 구현됨. matching_agent.py에는 파일시스템 코드를 직접 임포트하는 부분이 없음

표준화된 도구 인터페이스 구현

모든 도구에 일관된 {"success": bool, ...} 봉투(envelope) 형식, 구조화된 JSON-RPC 스타일 오류 코드(아래 참조)

프로덕션 준비 시스템 배포

환경 변수 기반 설정, 제한된 동시성, 부분 실패 처리, 테스트된 환경 변수 전달 수정, 단위 + 프로토콜 계층에 걸친 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 note

check_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.py

Windows 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.pyServerConfig.from_env() 참조:

변수

기본값

RESUME_DIRECTORY

./sample_data/resumes

RESULTS_DIRECTORY

./results

ALLOWED_EXTENSIONS

.txt,.pdf,.docx

MAX_BATCH_CONCURRENCY

5

NOTIFY_SCORE_THRESHOLD

70 (matching_agent.py)

MATCHING_AGENT_MODEL

anthropic:claude-sonnet-5

테스트

pytest tests/ -v

14개의 테스트, 두 계층:

  • 단위(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 사양 개정과 함께 출시되었으며 FastMCPMCPServer로 이름을 바꿉니다(현재 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)

Maintenance

ActivityMaintained
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables file system operations (read, write, list, search, watch, batch process) via MCP over JSON-RPC 2.0, used by a resume matching agent.
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables AI agents to interact with a sandboxed filesystem via MCP tools for reading, writing, searching, and monitoring files, including batch processing and resource discovery for resume management.
  • F
    license
    Not graded
    quality
    C
    maintenance
    Provides file system tools for resume matching agents, enabling reading, writing, searching, listing, watching, and batch processing of files via the Model Context Protocol.
  • F
    license
    Not graded
    quality
    C
    maintenance
    Provides MCP tools for reading, listing, writing, searching, watching, and batch-processing files, enabling automated file management and resume matching workflows.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/GAVTIN/Resume-Matcher-MCP-Edition'

If you have feedback or need assistance with the MCP directory API, please join our Discord server