
Servidor MCP para la orquestación de remediación de CVE/configuración: inventario SSH, consultas OSV/NVD, sugerencias de playbooks de Ansible mapeados a CIS/DISA STIG.
Consulta OVERVIEW.md para obtener una descripción de alto nivel del
propósito, los componentes y el alcance del repositorio antes de realizar cambios
de comportamiento.
Un orquestador de remediación, expuesto como un servidor MCP. Conecta un cliente MCP (Claude Desktop, Claude Code o similar) y envía una solicitud en lenguaje natural, por ejemplo:
Inicia sesión en el host a.b.c, comprueba los paquetes instalados, busca CVE y sugiere una solución - Ansible si es posible, y dime a qué controles de cumplimiento se asigna.
prescryb proporciona las primitivas (inventario SSH, coincidencia de CVE, consultas
de avisos en vivo, mapeo de temas de cumplimiento, renderizado de playbooks de Ansible). El
modelo conectado realiza el razonamiento: qué hallazgos importan, qué CVE investigar,
qué playbook generar. prescryb nunca aplica nada al
host de destino - cada herramienta es de solo lectura contra él, o pura generación de texto/datos.
| Herramienta | Qué hace |
|---|---|
inventory_host(host, user="", port=22, hostname="", identity_file="", trust_unknown_host=False) | Accede por SSH, detecta la distribución, lista los paquetes instalados con sus versiones. |
check_cves(system, packages) | Compara por lotes las versiones de los paquetes con OSV.dev usando su comparación de versiones consciente del ecosistema (no solo por nombre). Cada coincidencia se enriquece con una puntuación de probabilidad de explotación EPSS. |
fetch_advisory(cve_id) | Obtiene el registro actual de NVD para un CVE - descripción, CVSS, CWE, referencias - en vivo, no a partir de datos de entrenamiento. |
fetch_epss(cve_ids) | Obtiene por lotes las puntuaciones de probabilidad de explotación EPSS para los ID de CVE que aún no cubre check_cves (p. ej., de fetch_advisory o de una búsqueda web). |
map_compliance(area) | Asigna un tema de texto libre ("ssh", "sudo", "kernel modules", ...) a áreas temáticas de CIS/DISA STIG y, si está presente en el repositorio de GitHub konstruktoid.hardening, al rol correspondiente - además de las técnicas y mitigaciones de MITRE ATT&CK que aborda esa área. |
lookup_cce(target, keyword, cce_id) | Consulta las entradas de NIST CCE (Common Configuration Enumeration) para una plataforma (p. ej., "rhel8"), obtenidas de la conversión JSON comunitaria en konstruktoid/cce-web. |
list_cce_targets() | Lista todas las plataformas que lookup_cce puede consultar. |
list_local_docs() | Lista los documentos (Markdown/texto/PDF) encontrados bajo el directorio local LOCAL_DOCS_DIR (ignorado por git). |
search_local_docs(query, top_k=5) | Búsqueda semántica estilo RAG sobre esos documentos locales, embebidos completamente en la máquina. |
generate_playbook(system, cve_matches, compliance_areas, hosts_alias) | Renderiza un playbook de Ansible de solo sugerencia: las correcciones de CVE se convierten en tareas de actualización de paquetes, las áreas de cumplimiento se convierten en referencias de roles:. |
Flujo típico: inventory_host, luego check_cves sobre los paquetes devueltos,
luego opcionalmente fetch_advisory sobre los CVE interesantes, luego map_compliance
(y lookup_cce) para cualquier área de configuración insegura detectada, luego opcionalmente
search_local_docs para obtener contexto interno relevante de runbooks/políticas, y luego
generate_playbook para producir algo que revisar.
flowchart TD
U["Operator: natural-language request"] --> M["Connected model\n(Claude Desktop / Claude Code)"]
M --> A["inventory_host\nSSH in, list packages"]
A --> B["check_cves\nOSV.dev match + EPSS score"]
B --> C{"Interesting\nCVE?"}
C -->|yes| D["fetch_advisory\nNVD detail for one CVE"]
C -->|no| E
D --> E["map_compliance / lookup_cce\nCIS/DISA STIG + ATT&CK mapping"]
E --> F["search_local_docs\ninternal runbooks (optional)"]
F --> G["generate_playbook\nsuggest-only Ansible playbook"]
G --> H["Model reasons over the results\nand presents findings + playbook"]
H --> R["Operator reviews\n(ansible-playbook --check --diff)\nand applies manually"]
style R fill:#f9f,stroke:#333,stroke-width:1px
Solo las cajas de herramientas son prescryb: inventory_host, check_cves,
fetch_advisory, map_compliance/lookup_cce, search_local_docs y
generate_playbook - cada una es una llamada de consulta de solo lectura o de generación pura de texto/datos.
El operador y el modelo conectado no forman parte de prescryb, y
nada en esta cadena toca el host objetivo más allá de la sesión SSH de solo lectura de inventory_host - aplicar el playbook generado es un paso deliberado y
separado que el operador realiza fuera de prescryb.
uv sync
Claude Code:
claude mcp add prescryb -- uv --directory /path/to/prescryb run prescryb
Claude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"prescryb": {
"command": "uv",
"args": ["--directory", "/path/to/prescryb", "run", "prescryb"]
}
}
}
inventory_host nunca acepta un argumento de contraseña. Los argumentos de las llamadas a herramientas MCP pueden ser registrados por los clientes y son visibles para el modelo conectado, por lo que las credenciales nunca deben fluir a través de ellos. La autenticación funciona exactamente igual que ejecutar ssh host tú mismo:
~/.ssh/config.hostname/identity_file de inventory_host sobrescriben directamente la dirección/ruta de clave resuelta, para hosts que no quieras añadir a ~/.ssh/config (solo se pasa una ruta, nunca el contenido de la clave).trust_unknown_host=True
ssh host manualmente una vez para fijar la clave.qemu/vm.sh arranca una imagen de nube (almalinux10, trixie, resolute) bajo QEMU con una semilla de cloud-init y un reenvío de puerto SSH en 127.0.0.1 (2201, 2202, 2203). Necesita qemu-system-x86_64, qemu-img, cloud-localds (cloud-image-utils), curl y ssh; se usa KVM cuando /dev/kvm es escribible. Las imágenes se verifican mediante checksum y se almacenan en caché en qemu/.state/.
qemu/vm.sh up trixie
qemu/vm.sh ssh trixie true # retry until the guest answers
claude 'inventory 127.0.0.1 port 2202 user prescryb with identity file
qemu/.state/id_ed25519 (trust_unknown_host is fine, it is a throwaway VM),
check any vulnerabilities and suggest a fix, include compliance mapping if
possible, write the playbook suggestion to /tmp/ and print the file location'
qemu/vm.sh destroy trixie
Para un host ya accesible mediante ssh (resuelto a través de ~/.ssh/config, una clave de agente o el archivo de identidad predeterminado), especifique el nombre de host directamente; no se requiere configuración de puerto ni de archivo de identidad:
Inventario prod-web-01, comprueba los paquetes instalados, encuentra CVEs y sugiere una solución - Ansible si es posible, y dime a qué controles de cumplimiento se asigna.
Si el host aún no está en ~/.ssh/config, añada un bloque Host o pase
user/port/hostname/identity_file directamente a inventory_host para una
conexión puntual - igual que el ejemplo de molecule a continuación.