ctfd-mcp
Servidor MCP para CTFd que permite a usuarios regulares explorar desafíos, gestionar instancias dinámicas y enviar banderas.
GitHub
25
Prueba este MCPPatrocinadoDocumentación
Servidor MCP de CTFd (ámbito de usuario)
Servidor MCP que permite a un usuario regular de CTFd listar desafíos, leer detalles, iniciar/detener instancias dinámicas de docker y enviar banderas.
Requisitos
- Python 3.13 (gestionado por
uv). - Variables de entorno (elige un método de autenticación):
CTFD_URL(p. ej. https://ctfd.example.com)CTFD_TOKEN(token de usuario, no administrador) oCTFD_SESSION(cookie de sesión si los tokens están deshabilitados).CTFD_CSRF_TOKEN(opcional, solo si el servidor/plugin requiere CSRF para ctfd-owl).
Puedes guardarlas en un archivo .env en la raíz del repositorio:
CTFD_URL=https://ctfd.example.com/
CTFD_USERNAME=your_username
CTFD_PASSWORD=your_password
# or, if you prefer to use a token:
# CTFD_TOKEN=your_ctfd_api_token_here
# or, if tokens are disabled:
# CTFD_SESSION=your_session_token_here
# and, if the owl plugin enforces CSRF:
# CTFD_CSRF_TOKEN=your_csrf_token_here
Instalación
- Desde PyPI (recomendado):
uvx ctfd-mcp --help - Desde el código fuente (sin instalación):
uvx --from . ctfd-mcp --help
Ejecutar el servidor MCP (stdio)
# installed from PyPI
uvx ctfd-mcp
# from local checkout
uvx --from . ctfd-mcp
Ejemplo de configuración MCP para Cursor y Claude
{
"mcpServers": {
"ctfd-mcp": {
"command": "uvx",
"args": ["ctfd-mcp"],
"env": {
"CTFD_URL": "https://ctfd.example.com",
"CTFD_TOKEN": "your_user_token"
}
}
}
}
Ejemplo de configuración MCP para Codex
[mcp_servers.ctfd-mcp]
command = "uvx"
args = ["ctfd-mcp"]
[mcp_servers.ctfd-mcp.env]
CTFD_URL = "https://ctfd.example.com"
CTFD_TOKEN = "your_user_token"
Herramientas expuestas
list_challenges(category?, only_unsolved?)— lista los desafíos visibles, con filtro opcional por categoría/no resueltos.challenge_details(challenge_id)— descripción (HTML +description_text), metadatos, URLs de adjuntos, estado de resolución.submit_flag(challenge_id, flag)— intenta una bandera; devuelve estado/mensaje.start_container(challenge_id)— inicio unificado; detecta automáticamente dynamic_docker, ctfd-owl o k8s/api/v1/k8s.stop_container(container_id?, challenge_id?)— detención unificada; whale se puede detener solo concontainer_id, owl/k8s necesitanchallenge_id.
Los adjuntos se devuelven como URLs absolutas en files; el cliente/host puede obtenerlos directamente.
Recursos MCP
resource://ctfd/challenges/{challenge_id}— instantánea en markdown de un desafío (metadatos, descripción, URLs de adjuntos, información de conexión si está presente).
Manejo de errores
- Falta de env/config -> error MCP claro.
- 401/403 -> autenticación fallida, verifica el token o la cookie de sesión.
- 404 -> no encontrado (o API de contenedor dinámico ausente).
- 429 -> límite de velocidad alcanzado (Retry-After si está presente).
- Otros errores HTTP/API -> se muestran como errores MCP con mensaje/estado de CTFd.
Notas y solución de problemas
- Los contenedores dinámicos requieren el plugin ctfd-whale (dynamic_docker) en el CTFd de destino; de lo contrario,
/api/v1/containersdevuelve 404. - Los desafíos Owl (
dynamic_check_docker) usan un endpoint diferente:/plugins/ctfd-owl/container?challenge_id=<id>. Generalmente requieren una cookie de sesión, y algunas configuraciones requieren un token CSRF; estableceCTFD_CSRF_TOKENsi es necesario. - Algunos eventos exponen instancias respaldadas por Kubernetes en
/api/v1/k8s/{get,create,delete}con datos de formulario multipart; el cliente intentará estos cuando el tipo de desafío incluyak8s(o cuando falte un endpoint dynamic_docker). - Si el servidor te redirige a
/login(302) al usar un token, cambia a una cookie de sesión del navegador: estableceCTFD_SESSIONdesde la cookiesessiondespués de iniciar sesión. - El cliente ahora admite iniciar sesión con
CTFD_USERNAMEyCTFD_PASSWORD; estos campos tienen prioridad sobre tokens/sesiones obsoletos. - Prioridad de autenticación: nombre de usuario/contraseña primero, luego token, luego cookie de sesión. Las credenciales de menor prioridad se ignoran cuando hay una opción de mayor prioridad presente.
Soporte / comentarios
Si algo falla o tienes preguntas, contacta:
- Telegram: @ismailgaleev
- Jabber: ismailgaleev@chat.merlok.ru
- Email: umbra2728@gmail.com
Pruebas
- Ejecuta
uv run pytest. - Los tiempos de espera son configurables mediante env:
CTFD_TIMEOUT(total),CTFD_CONNECT_TIMEOUT,CTFD_READ_TIMEOUT(segundos). Los valores predeterminados son 20s total / 10s conexión / 15s lectura.
Desarrollo
- Dependencias de desarrollo:
uv sync --group dev - Lint/formato:
uv run ruff check .yuv run ruff format . - Pruebas:
uv run pytest - Pre-commit:
uv run pre-commit install(verCONTRIBUTING.md)
Licencia
Apache-2.0. Ver LICENSE.