Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
prescryb — MCP server for CVE/config remediation orchestration: SSH inventory, OSV/NVD lookups, CIS/DISA STIG-mapped Ansible playbook suggestions. | Kitploit
Tools/GitHubGitHub/konstruktoid/prescryb
Defensive ToolsVulnerability AnalysisConfiguration AuditingInformation GatheringDevSecOpsThreat IntelligenceAI Security
GitHubkonstruktoid/prescryb

prescryb

MCP server for CVE/config remediation orchestration: SSH inventory, OSV/NVD lookups, CIS/DISA STIG-mapped Ansible playbook suggestions.

View Repository
1171 day agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

prescryb - A remediation orchestrator

See OVERVIEW.md for a high-level description of the repository's purpose, components, and scope before making behavioral changes.

A remediation orchestrator, exposed as an MCP server. Connect an MCP client (Claude Desktop, Claude Code, or similar) and submit a natural-language request, for example:

Log into host a.b.c, check installed packages, find CVEs, and suggest a fix - Ansible if possible, and tell me what compliance controls it maps to.

prescryb supplies the primitives (SSH inventory, CVE matching, live advisory lookups, compliance-topic mapping, Ansible playbook rendering). The connected model does the reasoning: which findings matter, which CVEs to dig into, which playbook to generate. prescryb never applies anything to the target host - every tool is read-only against it, or pure text/data generation.

How it works

ToolWhat it does
inventory_host(host, user="", port=22, hostname="", identity_file="", trust_unknown_host=False)SSH in, detect the distro, list installed packages with versions.
check_cves(system, packages)Batch-match package versions against OSV.dev using its ecosystem-aware version comparison (not name-only matching). Each match is enriched with an EPSS exploitation-probability score.
fetch_advisory(cve_id)Fetch the current NVD record for one CVE - description, CVSS, CWE, references - live, not from training data.
fetch_epss(cve_ids)Batch-fetch EPSS exploitation-probability scores for CVE IDs not already covered by check_cves (e.g. from fetch_advisory or a web search).
map_compliance(area)Map a free-text topic ("ssh", "sudo", "kernel modules", ...) to CIS/DISA STIG topic areas and, if present in the konstruktoid.hardening GitHub repo, the matching role - plus the MITRE ATT&CK techniques and mitigations that area addresses.
lookup_cce(target, keyword, cce_id)Look up NIST CCE (Common Configuration Enumeration) entries for a platform (e.g. "rhel8"), sourced from the community JSON conversion at konstruktoid/cce-web.
list_cce_targets()List every platform lookup_cce can query.
list_local_docs()List documents (Markdown/text/PDF) found under the local, gitignored LOCAL_DOCS_DIR.
search_local_docs(query, top_k=5)RAG-style semantic search over those local documents, embedded entirely on-machine.
generate_playbook(system, cve_matches, compliance_areas, hosts_alias)Render a suggest-only Ansible playbook: CVE fixes become package-upgrade tasks, compliance areas become roles: references.

Typical flow: inventory_host, then check_cves on the returned packages, then optionally fetch_advisory on interesting CVEs, then map_compliance (and lookup_cce) for any insecure-config areas noticed, then optionally search_local_docs for relevant internal runbook/policy context, then generate_playbook to produce something to review.

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

Only the tool boxes are prescryb: inventory_host, check_cves, fetch_advisory, map_compliance/lookup_cce, search_local_docs, and generate_playbook - each a read-only lookup or pure text/data generation call. The operator and connected model are not part of prescryb, and nothing in this chain touches the target host beyond inventory_host's read-only SSH session - applying the generated playbook is a deliberate, separate step the operator takes outside prescryb.

Install

uv sync

Register with an MCP client

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

SSH auth model

inventory_host never accepts a password argument. MCP tool-call arguments can be logged by clients and are visible to the connected model, so credentials must never flow through them. Auth works exactly like running ssh host yourself:

  • Host/user/port/identity files are resolved from ~/.ssh/config.
  • Keys come from an SSH agent or the default identity files.
  • inventory_host's hostname/identity_file arguments override the resolved address/key path directly, for hosts you do not want to add to ~/.ssh/config (only a path is passed, never key contents).
  • Unknown host keys are rejected unless you pass trust_unknown_host=True
    • prefer running ssh host manually once to pin the key instead.

Example: running claude against the repository QEMU VMs

qemu/vm.sh boots a cloud image (almalinux10, trixie, resolute) under QEMU with a cloud-init seed and an SSH port forward on 127.0.0.1 (2201, 2202, 2203). It needs qemu-system-x86_64, qemu-img, cloud-localds (cloud-image-utils), curl and ssh; KVM is used when /dev/kvm is writable. Images are checksum-verified and cached in 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

Example: checking a regular host

For a host already reachable via ssh (resolved through ~/.ssh/config, an agent key, or the default identity file), specify the hostname directly; no port or identity-file configuration is required:

Inventory prod-web-01, check installed packages, find CVEs, and suggest a fix - Ansible if possible, and tell me what compliance controls it maps to.

If the host is not in ~/.ssh/config yet, either add a Host block or pass user/port/hostname/identity_file straight to inventory_host for a one-off connection - same as the molecule example below.

Example: inspecting a molecule test instance

molecule converge -s default

Find the ssh_port/ssh_user from that scenario's molecule.yml platform entry (e.g. ssh_port: 22201, ssh_user: almalinux for the almalinux10 platform) and the private key molecule login uses to connect - either add a Host block to ~/.ssh/config, or skip the file entirely and pass them straight to inventory_host for a one-off, ephemeral connection:

Inventory 127.0.0.1, port 22201, user almalinux, identity_file /path/to/molecule's/generated/key, check installed packages, find CVEs, and suggest a fix - Ansible if possible, and tell me what compliance controls it maps to.

Run molecule destroy -s default when finished; prescryb will not do it for you, and will not touch the instance beyond reading it.

Compliance mapping

Download Tool