
MCP-Server für die Orchestrierung von CVE-/Konfigurationsbehebungen: SSH-Inventarisierung, OSV-/NVD-Abfragen, CIS-/DISA-STIG-zugeordnete Ansible-Playbook-Vorschläge.
Siehe OVERVIEW.md für eine übergeordnete Beschreibung des
Zwecks, der Komponenten und des Umfangs dieses Repositorys, bevor
verhaltensändernde Änderungen vorgenommen werden.
Ein Remediation-Orchestrator, bereitgestellt als MCP-Server. Verbinde einen MCP-Client (Claude Desktop, Claude Code oder ähnlich) und reiche eine Anfrage in natürlicher Sprache ein, zum Beispiel:
Melde dich bei Host a.b.c an, prüfe die installierten Pakete, finde CVEs und schlage eine Lösung vor - Ansible wenn möglich, und sag mir, auf welche Compliance-Kontrollen sie abgebildet werden.
prescryb stellt die Primitive bereit (SSH-Inventar, CVE-Abgleich, Live-Abfragen von
Advisories, Zuordnung zu Compliance-Themen, Rendering von Ansible-Playbooks). Das
verbundene Modell übernimmt die Schlussfolgerungen: welche Befunde relevant sind, welche CVEs
untersucht werden sollen, welches Playbook generiert werden soll. prescryb wendet nie etwas auf dem
Zielhost an - jedes Tool ist ihm gegenüber schreibgeschützt oder reine Text-/Datengenerierung.
| Tool | Was es tut |
|---|---|
inventory_host(host, user="", port=22, hostname="", identity_file="", trust_unknown_host=False) | SSH-Verbindung, Erkennung der Distribution, Auflistung der installierten Pakete mit Versionen. |
check_cves(system, packages) | Stapelweiser Abgleich der Paketversionen gegen OSV.dev unter Verwendung seines ecosystem-bewussten Versionsvergleichs (nicht nur Namensabgleich). Jeder Treffer wird mit einem EPSS-Ausnutzungswahrscheinlichkeits-Score angereichert. |
fetch_advisory(cve_id) | Ruft den aktuellen NVD-Datensatz für eine CVE ab - Beschreibung, CVSS, CWE, Referenzen - live, nicht aus Trainingsdaten. |
fetch_epss(cve_ids) | Stapelweises Abrufen von EPSS-Ausnutzungswahrscheinlichkeits-Scores für CVE-IDs, die nicht bereits von check_cves abgedeckt sind (z. B. aus fetch_advisory oder einer Websuche). |
map_compliance(area) | Ordnet ein Freitext-Thema ("ssh", "sudo", "kernel modules", ...) CIS/DISA-STIG-Themenbereichen zu und, falls im GitHub-Repo konstruktoid.hardening vorhanden, der passenden Rolle - plus den MITRE-ATT&CK-Techniken und -Gegenmaßnahmen, die dieser Bereich adressiert. |
lookup_cce(target, keyword, cce_id) | Schlägt NIST CCE-Einträge (Common Configuration Enumeration) für eine Plattform (z. B. "rhel8") nach, bezogen aus der Community-JSON-Konvertierung unter konstruktoid/cce-web. |
list_cce_targets() | Listet jede Plattform auf, die lookup_cce abfragen kann. |
list_local_docs() | Listet Dokumente (Markdown/Text/PDF) auf, die unter dem lokalen, gitignorierten LOCAL_DOCS_DIR gefunden werden. |
search_local_docs(query, top_k=5) | RAG-artige semantische Suche über diese lokalen Dokumente, vollständig auf dem Rechner eingebettet. |
generate_playbook(system, cve_matches, compliance_areas, hosts_alias) | Rendert ein nur-vorschlagendes Ansible-Playbook: CVE-Fixes werden zu Paket-Upgrade-Tasks, Compliance-Bereiche werden zu roles:-Referenzen. |
Typischer Ablauf: inventory_host, dann check_cves auf den zurückgegebenen Paketen,
dann optional fetch_advisory für interessante CVEs, dann map_compliance
(und lookup_cce) für alle bemerkten Bereiche unsicherer Konfiguration, dann optional
search_local_docs für relevanten internen Runbook-/Richtlinienkontext, dann
generate_playbook, um etwas zur Überprüfung zu erzeugen.
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
Nur die Tool-Boxen sind prescryb: inventory_host, check_cves,
fetch_advisory, map_compliance/lookup_cce, search_local_docs und
generate_playbook – jeweils ein schreibgeschützter Lookup- oder reiner Text-/Datengenerierungs-
Aufruf. Der Operator und das verbundene Modell sind nicht Teil von prescryb, und
nichts in dieser Kette berührt den Zielhost über die schreibgeschützte SSH-Sitzung von inventory_host hinaus – das Anwenden des generierten Playbooks ist ein bewusster,
separater Schritt, den der Operator außerhalb von prescryb vornimmt.
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 akzeptiert niemals ein Passwort-Argument. MCP-Tool-Aufrufargumente
können von Clients protokolliert werden und sind für das verbundene Modell sichtbar, daher
dürfen Anmeldedaten niemals über sie fließen. Die Authentifizierung funktioniert genau wie das Ausführen von
ssh host selbst:
~/.ssh/config aufgelöst.hostname/identity_file von inventory_host überschreiben den
aufgelösten Adress-/Schlüsselpfad direkt, für Hosts, die du nicht zu
~/.ssh/config hinzufügen möchtest (es wird nur ein Pfad übergeben, niemals der Schlüsselinhalt).trust_unknown_host=True
ssh host aus, um den Schlüssel zu pinnen.qemu/vm.sh startet ein Cloud-Image (almalinux10, trixie, resolute) unter
QEMU mit einem cloud-init-Seed und einer SSH-Portweiterleitung auf 127.0.0.1
(2201, 2202, 2203). Es benötigt qemu-system-x86_64, qemu-img, cloud-localds
(cloud-image-utils), curl und ssh; KVM wird verwendet, wenn /dev/kvm beschreibbar ist.
Images werden per Prüfsumme verifiziert und in qemu/.state/ zwischengespeichert.
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
Für einen Host, der bereits über ssh erreichbar ist (aufgelöst über ~/.ssh/config, einen Agent-Schlüssel oder die Standard-Identitätsdatei), geben Sie den Hostnamen direkt an; es ist keine Konfiguration von Port oder Identitätsdatei erforderlich:
Inventarisiere prod-web-01, prüfe installierte Pakete, finde CVEs und schlage eine Lösung vor – Ansible, wenn möglich, und sag mir, welchen Compliance-Kontrollen es zugeordnet wird.
Wenn der Host noch nicht in ~/.ssh/config steht, fügen Sie entweder einen Host-Block hinzu oder übergeben Sie user/port/hostname/identity_file direkt an inventory_host für eine einmalige Verbindung – genau wie im Molecule-Beispiel unten.