Skip to main content
Glama
GAVTIN

filesystem-mcp-server

by GAVTIN

Resume Matcher — MCP Edition

Las herramientas directas del sistema de archivos del agente de coincidencia de currículos, reemplazadas por un servidor MCP independiente, además de un agente LangGraph refactorizado para comunicarse con él (y un segundo servidor MCP) a través de un cliente MCP real en lugar de llamadas a funciones locales.

Objetivos de aprendizaje → qué hay en este repositorio

Objetivo

Dónde

Entender el Protocolo de Contexto de Modelo

filesystem_mcp_server.py implementa herramientas y recursos; probado contra el protocolo de cable JSON-RPC 2.0 real en tests/ (no simulado)

Reemplazar herramientas personalizadas con servidores MCP

Cada operación de sistema de archivos del Hito 1 es ahora un @mcp.tool(); nada en matching_agent.py importa código de sistema de archivos directamente

Implementar interfaces de herramientas estandarizadas

Envoltura consistente {"success": bool, ...} en cada herramienta; códigos de error estructurados estilo JSON-RPC (ver más abajo)

Desplegar sistemas listos para producción

Configuración basada en variables de entorno, concurrencia limitada, manejo de fallos parciales, una corrección probada de reenvío de entorno, 14 pruebas que pasan en capas de unidad y protocolo

Related MCP server: Filesystem MCP Server

Arquitectura

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")]

Dos servidores MCP independientes, cada uno un proceso de sistema operativo separado, cada uno sin conocimiento del otro ni de LangGraph. El agente descubre sus herramientas al inicio (client.get_tools()) y las llama por nombre — ese es el punto central de la refactorización: filesystem_mcp_server.py podría ganar una nueva herramienta mañana y matching_agent.py no necesitaría un cambio de código.

Máquina de estados (interacción agente ↔ 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 llamando a watch_directory primero — antes de tocar cualquier otra cosa — es deliberado: una ejecución sin nada nuevo corta directamente a [*] sin gastar una llamada de LLM, y el modo --watch (ver más abajo) reprocesa solo lo que realmente cambió en lugar de todo el directorio cada vez.

Ejecutar localmente

Desde la raíz del repositorio, crea el entorno virtual e instala las dependencias.

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

Si quieres volver a escanear la bandeja de entrada desde cero

El observador mantiene un pequeño archivo de estado para que solo puntúe currículos recién añadidos. Si quieres procesar la carpeta actual de nuevo, limpia primero el estado del observador:

python matching_agent.py --reset-watch

Patrones de uso comunes

# 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

Usa el Python del venv del proyecto, no el Python del sistema, al ejecutar el agente. En este repositorio, el comando que funciona es típicamente ./.venv/Scripts/python.exe matching_agent.py en Windows o source .venv/bin/activate && python matching_agent.py en shells tipo Unix.

Ejecuta cualquiera de los servidores de forma independiente para probarlo directamente (útil con el MCP Inspector):

python filesystem_mcp_server.py
python notifications_mcp_server.py

La configuración está impulsada por variables de entorno — consulta ServerConfig.from_env() en filesystem_mcp_server.py:

Variable

Predeterminado

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

Pruebas

pytest tests/ -v

14 pruebas, dos capas:

  • Unidad (test_filesystem_mcp_server.py, la mayor parte): llama a las funciones de herramienta directamente contra un fixture tmp_path — rápido, sin subproceso. Cubre rutas de éxito, los códigos de error RESUME_NOT_FOUND / INVALID_PARAMS, y el informe de fallos parciales de batch_process.

  • Protocolo (test_server_speaks_mcp_protocol_over_stdio): lanza el servidor real como subproceso y lo maneja con el SDK oficial de cliente mcptools/list, tools/call, resources/read — sobre JSON-RPC 2.0 real, por lo que demuestra la capa de protocolo, no solo el Python subyacente.

  • Agente (test_matching_agent.py): la llamada al LLM se reemplaza por un simulacro determinista (FakeStructuredModel) para que no necesiten clave API — están comprobando el cableado del grafo, el descubrimiento de herramientas de múltiples servidores, la ruta de cortocircuito cuando no hay archivos nuevos, y que una segunda pasada estilo --watch solo reprocesa el archivo recién llegado, no todo el directorio.

Decisiones de diseño

SDK de MCP fijado a mcp>=1.28,<2.0. La línea v2 del SDK de Python se lanzó junto con la revisión de la especificación MCP del 2026-07-28 y renombra FastMCP a MCPServer (ahora en mcp.server.mcpserver). v1.x es sobre lo que está construido y documentado el ecosistema MCP actual de LangChain/LangGraph, así que este proyecto lo fija a propósito, no por accidente — vale la pena revisarlo una vez que langchain-mcp-adapters y la base de tutoriales más amplia se pongan al día con v2.

stdio sobre HTTP. Sin superficie de red que asegurar, sin autenticación que configurar, y es lo que MultiServerMCPClient espera para un servidor "comando" local. La compensación, confirmada al construir esto: cada llamada de herramienta abre una sesión de subproceso nueva en lugar de reutilizar una — está bien para un agente de demostración/CLI, y es la razón honesta por la que una versión de producción sensible a la latencia se movería a un servidor streamable-http de larga duración.

Los errores son JSON estructurado, no prosa. Cada fallo lanza ToolError con un payload JSON que lleva un code en el rango de "error de servidor" de JSON-RPC (-32000..-32099) más una etiqueta error legible por máquina (RESUME_NOT_FOUND, DIRECTORY_NOT_FOUND, UNSUPPORTED_FILE_TYPE, EXTRACTION_FAILED, INVALID_PARAMS). Confirmado de extremo a extremo contra una sesión de cliente en vivo: aparece como CallToolResult(isError=True, ...), y _call_tool() de matching_agent.py lo relanza como MCPToolCallError con el código intacto en lugar de que un llamador tenga que hacer coincidir cadenas en un mensaje.

watch_directory sondea; no empuja. Las herramientas MCP son de solicitud/respuesta, así que esto es un sondeo (un archivo de estado JSON de nombre de archivo→mtime, comparado en cada llamada) en lugar de un listener inotify/watchdog. El modo --watch de matching_agent.py es lo que convierte eso en algo que se siente en vivo — un listener en segundo plano que empuje a través de suscripciones de recursos MCP sería el siguiente paso natural y está soportado por el protocolo, solo que fuera del alcance aquí.

batch_process toma una lista de archivos explícita, no solo un directorio. Esto es lo que permite que check_new_resumes → batch_extract reprocese solo lo que watch_directory acaba de informar en lugar de toda la carpeta cada vez — la concurrencia (asyncio.Semaphore(MAX_BATCH_CONCURRENCY)) es lo que hace que "eficiente" en la especificación sea realmente cierto cuando esa lista es larga.

El reenvío de entorno es explícito, y no es un valor predeterminado que puedas omitir. Un problema real encontrado al construir esto: el cliente stdio de mcp no hereda el entorno del proceso padre — inicia servidores hijos con un entorno mínimo predeterminado (solo PATH/HOME/TERM), confirmado directamente contra mcp.client.stdio.get_default_environment(). Sin pasar env=dict(os.environ) explícitamente en la configuración del servidor de matching_agent.py, RESUME_DIRECTORY y compañía nunca llegan silenciosamente a filesystem_mcp_server.py — el agente se ejecuta, descubre herramientas correctamente, y simplemente opera en el directorio equivocado. Vale la pena saberlo antes de que te cueste una sesión de depuración.

Estructura del repositorio

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