mcp-project-helper
mcp-project-helper
Servidor MCP (Model Context Protocol) mínimo que proporciona al asistente de IA para programación —en particular, Claude Code— un conjunto pequeño y seguro de herramientas (tools) para trabajar con una única directorio concreto del proyecto: búsqueda en sus archivos, lectura de archivos, búsqueda en la documentación local y ejecución de una verificación previamente aprobada (tests).
El proyecto se ha implementado por etapas (Stage 0 → Stage 3, el historial de prompts está en PROMPTS.md); la etapa actual es Stage 3: finalización. Las cuatro tools están implementadas y cubiertas por tests (Stage 1), el servidor está conectado a Claude Code y verificado manualmente con solicitudes reales a través de Claude Code CLI (Stage 2–3, evidencia en evidence/).
Sobre el proyecto
En lugar de dar al asistente acceso directo al shell o acceso ilimitado al sistema de archivos, el proyecto proporciona una superficie estrecha y fácilmente auditable de cuatro tools:
search_project_files— búsqueda de texto, limitada a la raíz del proyecto.read_project_file— lectura de un único archivo, limitada a la raíz del proyecto.get_docs— búsqueda en la documentación local endocs/de este repositorio.run_project_check— ejecución de una verificación de la lista blanca (actualmentetests), pero nunca un comando de shell arbitrario.
Es un proyecto educativo (tarea) — cuyo objetivo no es cubrir todos los posibles casos de uso, sino mostrar un ejemplo de extremo a extremo, honestamente documentado, de un servidor MCP: desde el esqueleto y los primitivos de seguridad (Stage 0), pasando por la implementación real de las tools (Stage 1), hasta la integración con el agente del IDE y evidencia reproducible de llamadas reales (Stage 2–3).
Related MCP server: GPT Commander
Qué es MCP y cómo funciona la conexión del agente
MCP (Model Context Protocol) — un protocolo abierto basado en JSON-RPC que describe cómo un asistente de IA (cliente/host, por ejemplo Claude Code) descubre e invoca herramientas externas (tools) proporcionadas por un proceso separado (servidor MCP), sin que el asistente tenga acceso directo al shell, la red o el sistema de archivos del host.
En este proyecto se utiliza el transporte stdio — la forma más simple y más común para herramientas locales:
El host (Claude Code) lee su configuración MCP (
.mcp.json) y lanza el servidor como un subproceso local normal, con el comando/argumentos especificados y las variables de entorno.El host y el servidor intercambian mensajes JSON-RPC a través de stdin/stdout de ese subproceso (de ahí el requisito de que stdout está reservado solo para el protocolo — ver la sección "Registro y depuración").
El host llama a
initialize()— el servidor responde con su nombre/versión (mcp-project-helper 0.1.0) y sus capacidades.El host llama a
list_tools()— el servidor devuelve la lista de tools registradas con su nombre, descripción y JSON Schema de los parámetros de entrada (inputSchema), generada por el MCP SDK a partir de la firma de la función.Cuando el usuario (o el propio modelo) decide invocar una de las tools, el host envía
call_tool(name, arguments); el servidor ejecuta la función Python correspondiente y devuelve un resultado estructurado (ver "Contrato de salida de las tools" más abajo) o un error a nivel de tool.No se abre ningún puerto de red: el ciclo de vida del servidor está completamente vinculado al subproceso lanzado por el host — si el host cierra la conexión, el subproceso termina.
Aquí no hay llamadas a ninguna API de LLM/IA (OpenAI, Anthropic, etc.): este
servidor solo proporciona tools que invoca el cliente (Claude Code);
la "búsqueda" en get_docs es una simple coincidencia determinista de
subcadenas sobre secciones de Markdown, sin embeddings/base de datos vectorial.
Para ejecutar el servidor no se necesita ninguna clave de API.
Qué se considera tool en este servidor
Tool — es una función Python normal, decorada con @mcp.tool(),
que acepta argumentos serializables a JSON y devuelve dict[str, Any]. El MCP
SDK automáticamente:
genera
inputSchema(JSON Schema) a partir de la firma y las anotaciones de tipos de los argumentos de la función — no es necesario describir ese esquema manualmente en ningún sitio;convierte la anotación del valor de retorno
-> dict[str, Any]en una salida estructurada de la tool (outputSchema/structuredContent), ver "Contrato de salida de las tools" más abajo;convierte una excepción Python no manejada dentro de la función de la tool en un resultado estructurado con error a nivel de tool (
CallToolResult.is_error = True), sin derribar la propia sesión MCP.
Las cuatro registraciones están juntas en
server.py:37-58; cada una es un
envoltorio fino orientado a MCP (cuyo docstring se convierte en la descripción
de la tool visible para el modelo) que delega la llamada a la implementación
real en tools/*.py, separando la firma a nivel de protocolo de la lógica.
Stack
Python 3.14 (
requires-python = ">=3.10"enpyproject.toml— este es el límite inferior real del MCP SDK utilizado, no una afirmación de que solo funciona con 3.14).MCP Python SDK oficial (paquete
mcp, versión instalada2.0.0) — proporciona el framework del servidor (mcp.server.MCPServer), el registro de tools (@mcp.tool()) y el transporte stdio (mcp.run(transport="stdio")).pytest — única dependencia de desarrollo, para el conjunto de tests.
No hay integración con API de LLM/IA ni transporte de red (HTTP/SSE no está configurado) — ver la sección anterior.
Arquitectura
src/mcp_project_helper/
server.py точка входа: создаёт MCPServer, регистрирует tools, запускает stdio
config.py корень проекта / корень docs / настройки логирования / whitelist проверок / лимиты
security.py resolve_within_root() — единый шлюз ограничения путей
logging_setup.py логирование в stderr (+ опционально файл), не затрагивая stdout
tools/
search_project_files.py поиск текста в пределах корня проекта
read_project_file.py чтение одного файла в пределах корня проекта
get_docs.py поиск по секциям markdown в docs/
run_project_check.py запуск подпроцесса из белого спискаCada tool que trabaja con archivos pasa por
security.resolve_within_root(root, relative_path) antes de abrir cualquier
ruta. config.py define la raíz del proyecto a partir de la variable de
entorno MCP_PROJECT_HELPER_ROOT (por defecto ./demo_project), por lo que
el servidor puede apuntarse a cualquier proyecto sin cambiar el código.
Tools MCP implementadas
search_project_files(query, path=".", max_results=50)
Busca recursivamente en los archivos de texto bajo path (relativo a la raíz
del proyecto; por defecto — toda la raíz) la coincidencia exacta de la
subcadena query. Omite los directorios de config.IGNORED_DIR_NAMES (.git,
.venv, __pycache__, node_modules, ...) y cualquier directorio
*.egg-info. Los archivos se comprueban por contenido binario (byte NUL o
UTF-8 no válido en los primeros 4 KB) y se omiten silenciosamente, en lugar de
provocar un error. Nunca sigue enlaces simbólicos a directorios o archivos fuera
de la raíz — cada ruta candidata se comprueba adicionalmente mediante
resolve_within_root, además del comportamiento estándar de os.walk, que no
sigue enlaces simbólicos a directorios.
max_results está limitado superiormente por config.SEARCH_RESULTS_CAP (200);
las líneas coincidentes más largas que config.SEARCH_MAX_LINE_CHARS (300) se
truncan; los archivos mayores que config.SEARCH_MAX_FILE_BYTES (2 MB) se
omiten, en lugar de escanearse.
Implementación: tools/search_project_files.py:41-130.
read_project_file(path)
Lee un único archivo de texto en la ruta path (relativa a la raíz del
proyecto). Rechaza directorios, archivos inexistentes y contenido binario (byte
NUL o UTF-8 no válido). El contenido está limitado por
config.READ_MAX_FILE_BYTES (200 KB) — los archivos de mayor tamaño se
devuelven truncados, en lugar de rechazarse.
Implementación: tools/read_project_file.py:25-69.
get_docs(query=None, max_results=10)
Busca en docs/*.md (recursivamente), divididos en secciones por los
encabezados de Markdown. Con query presente, devuelve las secciones cuyo
encabezado o cuerpo contienen la subcadena buscada (sin distinguir mayúsculas),
cada una con indicación del archivo de origen y el encabezado. Sin query,
devuelve una lista de una sección por archivo — un inventario de qué
documentación existe. Limitado solo por config.get_docs_root() — nunca por la
raíz del proyecto.
max_results está limitado superiormente por config.DOCS_RESULTS_CAP (50);
los fragmentos (snippets) están limitados por config.DOCS_MAX_SNIPPET_CHARS
(800 caracteres).
Implementación: tools/get_docs.py:58-114.
run_project_check(check_name)
Ejecuta una verificación de la lista blanca. check_name se busca en
config.ALLOWED_CHECKS antes de que se ejecute nada — un nombre desconocido
provoca inmediatamente un error, y el subproceso nunca se lanza. El argv de la
lista blanca se ejecuta mediante
subprocess.run(argv, shell=False, cwd=<raíz del proyecto>, timeout=...): sin
shell, con directorio de trabajo fijo, y nada de la parte que llama se añade a
la línea de comandos.
Implementación: tools/run_project_check.py:32-90.
Lista blanca
ALLOWED_CHECKS = {
"tests": [sys.executable, "-m", "pytest", "-q"],
}Definida en config.py:55-57.
Se usa sys.executable (y no simplemente la cadena "pytest") para que la
verificación se ejecute siempre con el mismo intérprete/entorno que el propio
servidor, independientemente de lo que esté primero en PATH. Aquí
deliberadamente no hay una entrada lint: en este repositorio no hay
dependencia ni configuración de ruff, por lo que conectar una verificación
"lint" sería o una ficción o un engaño. Se puede añadir más adelante
(config.ALLOWED_CHECKS["lint"] = [sys.executable, "-m", "ruff", "check", "."]),
cuando ruff se convierta en una dependencia real del proyecto con configuración
real — el mecanismo de lista blanca ya lo soporta sin ningún otro cambio de
código.
El tiempo de espera (config.CHECK_TIMEOUT_SECONDS, por defecto 60 s) y el
límite de volumen de salida (config.CHECK_MAX_OUTPUT_CHARS, por defecto
20 000 caracteres por flujo) se aplican a cada ejecución de verificación.
Contrato de salida de las tools
Cada tool devuelve un dict Python normal desde una función con anotación
-> dict[str, Any]; el MCP SDK reconoce automáticamente esto como salida
estructurada de la tool (rellena CallToolResult.structured_content y emite
outputSchema) — aquí no se serializan manualmente los resultados a una cadena
JSON en ningún sitio. Las situaciones de error (entrada incorrecta, salida
fuera de la ruta, verificación desconocida, archivo no encontrado, contenido
binario, etc.) lanzan una excepción Python, en lugar de devolver un dict; el SDK
convierte automáticamente esto en un resultado con error a nivel de tool
(CallToolResult.is_error = True). La única excepción es el tiempo de espera de
la verificación: es un resultado legítimo de la ejecución de una verificación
lanzada con éxito, no un error de datos de entrada, por lo que se devuelve como
un dict estructurado {"status": "error", ...}, en lugar de lanzar una
excepción.
search_project_files
{
"status": "success",
"query": "apply_discount",
"path": ".",
"matches": [
{"file": "demo_app/services.py", "line": 12, "text": "def apply_discount(order: Order, percent: float) -> float:"}
],
"count": 4,
"truncated": false
}read_project_file
{
"status": "success",
"file": "demo_app/models.py",
"content": "...",
"size": 397,
"truncated": false
}get_docs
{
"status": "success",
"query": "whitelist",
"results": [
{"file": "architecture.md", "heading": "Whitelist", "snippet": "..."}
],
"count": 1,
"truncated": false
}run_project_check
{
"status": "success",
"check_name": "tests",
"exit_code": 0,
"stdout": "...",
"stderr": "",
"truncated": false
}En caso de tiempo de espera: {"status": "error", "check_name": ..., "error": "check timed out after 60s", "exit_code": null, "stdout": "...", "stderr": "...", "truncated": ...}.
Los nombres de los campos y las convenciones status/count/truncated
anteriores se consideran un contrato estable para el futuro, no un detalle de
implementación.
Limitaciones de seguridad
Limitación de rutas:
security.resolve_within_root(security.py:19-50) rechaza rutas absolutas, el ascenso mediante..(a cualquier profundidad), los bytes NUL y los enlaces simbólicos que apunten fuera de la raíz configurada. Se usa enread_project_fileysearch_project_filesrelativo a la raíz del proyecto, y de nuevo ensearch_project_filespara cada archivo candidato durante el recorrido. Está cubierto por unit tests entests/test_security.pyy confirmado manualmente con una prueba negativa real mediante Claude Code (ver "Resultados de la verificación" más abajo, prueba 6).Sin salida de la raíz mediante enlaces simbólicos durante el recorrido:
search_project_filesyget_docsnunca siguen enlaces simbólicos a directorios (comportamiento predeterminado deos.walk) y omiten por completo los enlaces simbólicos a archivos.Sin comandos shell arbitrarios:
run_project_checkcomprueba el nombre de verificación solicitado contraconfig.ALLOWED_CHECKS(config.py:55-57) antes de que se ejecute nada; los nombres desconocidos se rechazan de inmediato, y la propia verificación se ejecuta mediantesubprocess.run(argv, shell=False, ...)con uncwdfijo y sin ningún argumento añadido por la parte que invoca.Salida limitada en todas partes: cada tool limita el volumen de datos devueltos:
max_results+ límites estrictos para búsqueda y docs, límite de bytes para lectura de archivos, límite de caracteres + tiempo de espera para la salida de la verificación — de modo que ninguna llamada puede devolver un volumen ilimitado de datos ni ejecutarse indefinidamente.stdout permanece limpio: todo el registro va a través de
logging_setup.pya stderr (y opcionalmente a un archivo de log); nada en el servidor escribe a stdout, que está reservado para el enmarcado JSON-RPC del protocolo MCP.Sin secretos en los logs: el servidor no acepta en absoluto claves API ni credenciales. Cada llamada real a un tool registra el nombre del tool, sus parámetros de entrada seguros (cadenas de consulta, rutas, nombres de verificación, cantidad/tamaño de resultados — pero nunca el contenido de archivos) y el
status=success/status=errorfinal.
Registro y depuración
Cada llamada real a un tool registra una línea a través del logger común
mcp_project_helper (stderr, más un archivo opcional mediante
MCP_PROJECT_HELPER_LOG_FILE), por ejemplo (líneas reales de
evidence/tool-calls.log):
INFO mcp_project_helper: tool=search_project_files query='apply_discount' path='.' max_results=50 matches=4 truncated=False status=success
INFO mcp_project_helper: tool=read_project_file path='demo_app/models.py' size=397 truncated=False status=success
INFO mcp_project_helper: tool=run_project_check check_name='tests' exit_code=0 status=success
INFO mcp_project_helper: tool=read_project_file path='../../../../etc/passwd' status=errorEl contenido de los archivos nunca se registra — solo metadatos de la llamada (rutas, cadenas de consulta, tamaños, cantidades, códigos de salida). La configuración del registro es logging_setup.py:20-42.
Para depurar:
El nivel de registro se ajusta con
MCP_PROJECT_HELPER_LOG_LEVEL(DEBUG,INFO,WARNING,ERROR,CRITICAL; por defectoINFO).El archivo de log se define con
MCP_PROJECT_HELPER_LOG_FILE; por defecto (sin esta variable) se escribe solo a stderr. Al iniciarse desde Claude Code (.mcp.json) apunta aevidence/tool-calls.log.Nunca use
print()en el código del servidor — stdout está reservado para el protocolo JSON-RPC; cualquier salida extra a stdout rompe el transporte stdio.Para ver qué llamadas ocurrieron realmente en la sesión actual de Claude Code, abra el archivo al que apunta
MCP_PROJECT_HELPER_LOG_FILE(evidence/tool-calls.log), o ejecute el servidor manualmente (python -m mcp_project_helper.server) y observe stderr.
Instalación
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"La única dependencia en tiempo de ejecución es el paquete mcp; pytest es una dependencia
solo para desarrollo/pruebas (ambas fijadas en pyproject.toml).
Configuración del entorno
La configuración se define mediante variables de entorno — copie
.env.example a .env y modifique los
valores si es necesario:
Variable | Propósito | Valor predeterminado |
| El único directorio al que tienen acceso las herramientas de archivos ( |
|
| Ruta al archivo de log (ver "Registro y depuración"). Los logs siempre van también a stderr. | no definido (solo stderr) |
| Uno de |
|
El servidor no necesita secretos (claves API, tokens) — .env.example contiene
solo ejemplos seguros de rutas y nivel de registro, y .env es ignorado
por git (ver "Estructura del proyecto" más abajo).
Ejecución del servidor MCP
Ejecutar el servidor directamente (permanecerá esperando al cliente en stdin — esto es normal para servidores MCP con transporte stdio; salir con Ctrl+C):
python -m mcp_project_helper.serverEjecutar la suite de pruebas:
pytest -qEjecutar directamente las pruebas del propio demo-proyecto (lo que por defecto
ejecuta run_project_check("tests"), ya que MCP_PROJECT_HELPER_ROOT por
defecto apunta a demo_project):
cd demo_project && pytest -qIntegración con Claude Code
Este repositorio contiene un archivo project-scoped
.mcp.json en la raíz del repositorio: la configuración específicamente para
Claude Code (a diferencia de .vscode/mcp.json, una
configuración separada del host MCP nativo VS Code; ver la comparación
detallada más abajo).
Claude Code detecta .mcp.json al abrir la carpeta del proyecto, inicia el
servidor como proceso hijo y se comunica con él mediante JSON-RPC a través de stdio — el
mismo transporte utilizado en todas las pruebas automatizadas de este
proyecto, solo que iniciado por el propio Claude Code, no por un harness de pruebas.
Escenario end-to-end confirmado: Claude Code CLI → MCP server → custom
tools. Las 6 solicitudes de verificación (ver "Resultados de la verificación" más abajo) se
ejecutaron realmente a través de Claude Code CLI con este servidor conectado mediante
.mcp.json — no solo configuradas, sino realmente invocadas, con capturas de pantalla
reales y registros en el log del lado del servidor.
Configuración para Claude Code
{
"mcpServers": {
"mcp-project-helper": {
"command": "${CLAUDE_PROJECT_DIR:-.}/.venv/bin/python",
"args": ["-m", "mcp_project_helper.server"],
"env": {
"MCP_PROJECT_HELPER_ROOT": "${CLAUDE_PROJECT_DIR:-.}/demo_project",
"MCP_PROJECT_HELPER_LOG_FILE": "${CLAUDE_PROJECT_DIR:-.}/evidence/tool-calls.log"
}
}
}
}${CLAUDE_PROJECT_DIR} es expandido por el propio Claude Code a la ruta absoluta
del directorio en el que se clonó el repositorio, por lo que el archivo no
contiene rutas específicas de una máquina concreta y no requiere ediciones después de
git clone. Se utiliza precisamente la forma con valor de respaldo
${CLAUDE_PROJECT_DIR:-.}, y no el ${CLAUDE_PROJECT_DIR} a secas: sin :-.
la variable no se expandía y Claude Code intentaba ejecutar literalmente
${CLAUDE_PROJECT_DIR}/.venv/bin/python como ruta al ejecutable (este
error se observó realmente en la primera versión de la configuración de Stage 2, ver
REPORT.md). MCP_PROJECT_HELPER_ROOT está definido explícitamente como
${CLAUDE_PROJECT_DIR:-.}/demo_project, para que la raíz del proyecto pasada al
servidor no sea ambigua, independientemente del valor predeterminado propio
en config.py.
Nota sobre plataformas: .venv/bin/python es la estructura de venv para
Unix (macOS/Linux), utilizada en todo este proyecto. En Windows
la ruta equivalente es .venv\Scripts\python.exe; para admitir también esa
plataforma, .mcp.json habría requerido una segunda entrada específica para Windows
(o un script envoltorio) — no se ha hecho, porque el proyecto
se desarrolló y verificó solo en macOS.
Configuración para VS Code
Este repositorio también contiene .vscode/mcp.json, una
configuración separada de espacio de trabajo para el host MCP integrado de VS
Code (utilizado por el modo agéntico de GitHub Copilot Chat):
{
"servers": {
"mcp-project-helper": {
"type": "stdio",
"command": "${workspaceFolder}/.venv/bin/python",
"args": ["-m", "mcp_project_helper.server"],
"env": {
"MCP_PROJECT_HELPER_ROOT": "${workspaceFolder}/demo_project",
"MCP_PROJECT_HELPER_LOG_FILE": "${workspaceFolder}/evidence/tool-calls.log"
}
}
}
}El mismo servidor stdio mcp-project-helper, con MCP_PROJECT_HELPER_ROOT
definido como ${workspaceFolder}/demo_project, y
MCP_PROJECT_HELPER_LOG_FILE definido como
${workspaceFolder}/evidence/tool-calls.log.
Por qué dos archivos y no uno: .mcp.json y .vscode/mcp.json siguen
esquemas diferentes e incompatibles, y sus variables de sustitución de rutas no
son intercambiables entre hosts:
.mcp.json(configuración de Claude Code) utiliza la clave de nivel superiormcpServersy expande${CLAUDE_PROJECT_DIR:-.}a la raíz del repositorio..vscode/mcp.json(configuración del host MCP nativo de VS Code) utiliza la clave de nivel superiorservers, el campo explícito"type": "stdio"y expande en su lugar${workspaceFolder}a la ruta de la carpeta abierta. El host MCP de VS Code no entiende${CLAUDE_PROJECT_DIR}: al intentar abrir.mcp.jsondirectamente desde VS Code, la variable se pasa literalmente y el servidor no puede iniciarse (spawn ${CLAUDE_PROJECT_DIR}/.venv/bin/python ENOENT) — este es un error realmente observado, que dio origen al.vscode/mcp.jsonseparado. Almacenar la configuración de cada host en su propio archivo, con su propia variable, evita este error y permite utilizar ambas herramientas con el mismo clon sin que una configuración comprometa la sintaxis de la otra.
.vscode/mcp.json es la única excepción a la regla general
de ignorar .vscode/* en .gitignore; el resto del estado local de VS
Code (settings.local.json, etc.) no se rastrea.
Estado de verificación de VS Code: .vscode/mcp.json es sintáctica y semánticamente
correcto (el mismo servidor, el mismo comando/variables de entorno que la configuración
de trabajo de Claude Code) y fue validado como JSON. Además,
la captura de pantalla real
evidence/vscode_mcp_server_connected.png
confirma que el host MCP nativo de VS Code realmente inicia el servidor con
esta configuración: Starting server mcp-project-helper → Connection state: Running → Discovered 4 tools, con una línea de confirmación del propio
registro de stderr del proceso mcp_project_helper en esa misma salida. Esto no es lo
mismo que la confirmación de invocación de custom tools a través de la interfaz de VS Code: ningún
escenario de usuario (search_project_files, etc.) se ejecutó a través de esa
interfaz ni se afirma como verificado. La única
integración con IDE confirmada hasta las invocaciones reales de tools por el usuario
(capturas de pantalla + logs del lado del servidor para los 6 escenarios) es Claude Code CLI,
ver "Resultados de la verificación" más abajo. De forma independiente a ambos: la integración
mediante Claude Code Desktop / extensión de Claude Code dentro de VS Code no se probó en
esta sesión en absoluto — no debe confundirse ni con el host MCP nativo de VS Code
(esta sección), ni con Claude Code CLI.
Cómo habilitar MCP
Brevemente (los detalles — en las subsecciones anteriores):
Claude Code:
Cree un venv e instale las dependencias (sección "Instalación").
Abra la raíz del repositorio en Claude Code (
claudedesde la raíz del repositorio).Claude Code detecta
.mcp.jsony ofrece una vez confirmar la confianza del espacio de trabajo para el servidormcp-project-helper: confírmelo.Ejecute
/mcp(oclaude mcp listen la terminal) y compruebe quemcp-project-helperestá conectado con 4 tools.
VS Code (host MCP nativo, modo agéntico de Copilot Chat):
Cree un venv igual que para Claude Code —
.vscode/mcp.jsonespera el mismo.venv/bin/python.Abra la raíz del repositorio como carpeta en VS Code.
VS Code detecta
.vscode/mcp.jsony ofrece iniciar el servidor — inícielo/confirme la confianza.Compruebe el estado mediante
MCP: List Servers.
Ambas opciones suponen una estructura Unix de venv (.venv/bin/python); en Windows — .venv\Scripts\python.exe (no configurado, ver arriba).
Consultas de verificación
Seis escenarios ejecutados realmente a través de Claude Code CLI para confirmar la integración (tabla completa con resultados en evidence/README.md):
Busca a través de MCP todos los lugares donde se usa la función
apply_discountendemo_project→ se esperasearch_project_files.Lee a través de MCP el archivo
demo_app/models.pyy explica brevemente qué modelos están definidos allí → se esperaread_project_file.Usando la documentación MCP del proyecto, cuenta qué limitaciones de seguridad tiene el servidor MCP → se espera
get_docs.Comprueba a través de la herramienta MCP si pasan los tests de
demo_project→ se esperarun_project_check.Usando solo las herramientas MCP, encuentra en
demo_projectla implementación deapply_discount, luego lee el archivo donde está definida y explica sus parámetros/retorno/cálculo del descuento → se espera una cadena de dos tools:search_project_filesy luegoread_project_file.(prueba negativa / de seguridad) Intenta leer a través de MCP el archivo
../../../../etc/passwd→ se espera denegación deread_project_filecon un error estructurado (la ruta excede la raíz permitida).
Resultados de la verificación
Las 6 de 6 consultas se completaron con éxito (en la prueba 5, ambas tools esperadas, en el orden correcto; en la prueba 6, el éxito es la denegación esperada). Cada línea está confirmada tanto con una captura de pantalla real como con una línea independiente en evidence/tool-calls.log. La tabla completa está en evidence/README.md; el análisis detallado con enlaces al código y los registros está en REPORT.md.
№ | Tool | Resultado |
1 |
| Éxito, 4 coincidencias |
2 |
| Éxito, |
3 |
| Éxito, se encontró la sección «Seguridad» |
4 |
| Éxito, |
5 |
| Éxito, cadena de dos tools |
6 |
| Denegación exitosa (path traversal bloqueado) |
Comprobaciones automatizadas (no sustituyen, sino que complementan las pruebas manuales de IDE anteriores):
pytest -qdesde la raíz del repositorio — 44 passed.pytest -qdentro dedemo_project/— 2 passed.Handshake stdio programático (
initialize()+list_tools()) — el servidor informamcp-project-helper 0.1.0y exactamente 4 tools:get_docs,read_project_file,run_project_check,search_project_files.
Estructura del proyecto
mcp-project-helper/
.mcp.json конфигурация MCP для Claude Code (project-scoped)
.vscode/mcp.json конфигурация MCP для native MCP host VS Code
.env.example безопасные примеры переменных окружения (без секретов)
pyproject.toml зависимости, entry point, конфигурация pytest
README.md этот файл
REPORT.md итоговый отчёт по всем стадиям, со ссылками файл:строки
PROMPTS.md история фактически использованных промптов (Этапы 0-3)
docs/
architecture.md документация, которую обслуживает get_docs
src/mcp_project_helper/
server.py точка входа: MCPServer, регистрация tools, stdio
config.py корень проекта/docs, лимиты, whitelist проверок
security.py resolve_within_root() — ограничение путей
logging_setup.py логирование в stderr (+ опционально файл)
tools/
search_project_files.py
read_project_file.py
get_docs.py
run_project_check.py
tests/ unit- и интеграционные тесты mcp_project_helper (44 теста)
demo_project/ демонстрационный проект — цель для файловых tools
demo_app/
models.py Product, Order
services.py apply_discount, OrderBuilder
tests/test_services.py 2 теста, запускаемые run_project_check("tests")
evidence/ реальные доказательства ручного тестирования через Claude Code и VS Code
README.md реестр всех 6 тестов с результатами + доп. evidence по VS Code
tool-calls.log реальный server-side лог всех 6 тестов (закоммичен)
tool-calls.log.example формат строки лога (шаблон)
test1_search_project_files.png … test6_path_traversal.png скриншоты 6 тестов Claude Code CLI (закоммичены)
vscode_mcp_server_connected.png доп. скриншот: native MCP host VS Code подключился, 4 tools (закоммичен)This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceAgent-safe code retrieval MCP server that indexes repositories and provides semantic search, file navigation, call graph analysis, and bounded file reading tools for coding agents.3,977,9623AGPL 3.0
- FlicenseCqualityCmaintenanceA security-first MCP server that provides LLMs with structured tools for filesystem, process, search, build/test/lint, IDE integration, and more.402
- AlicenseNot gradedqualityAmaintenanceLocal-first MCP server that provides project context, verification gates, and structured tools for coding agents to discover knowledge, run diagnostics, and execute allowlisted commands within a repository.43MIT
- AlicenseAqualityCmaintenanceZero-config MCP server that connects local codebases to AI assistants, providing secure project tree, regex search, file reading, and tech stack tools locally.433MIT
Related MCP Connectors
Agent-native MCP server over the public saagarpatel.dev corpus. Read-only, stateless.
MCP server for generating rough-draft project plans from natural-language prompts.
An MCP server that gives your AI access to the source code and docs of all public github repos
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/pw5rhn4tnn-dotcom/mcp-project-helper'
If you have feedback or need assistance with the MCP directory API, please join our Discord server