Skip to main content
Glama
firetix

MCP Vulnerability Checker Server

by firetix

get_exploit_availability

Check for public exploits and proof-of-concepts for a CVE across multiple sources to assess immediate risk and weaponization status.

Instructions

Check for public exploits and PoCs for a CVE

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
cve_idYesCheck for public exploits and proof-of-concepts (PoCs) for a CVE across multiple sources including ExploitDB, Metasploit, GitHub, and NVD references. Provide a CVE ID in the format CVE-YYYY-NNNN (e.g., CVE-2021-44228). Returns threat intelligence about exploit availability, active exploitation indicators, and weaponization status to assess immediate risk.

Implementation Reference

  • The main asynchronous handler function that implements the 'get_exploit_availability' tool logic. It validates the CVE ID, queries NVD API for references, checks MITRE page, and provides links and guidance for manual checks on ExploitDB, GitHub, Metasploit, etc. Generates a formatted risk assessment report.
    async def get_exploit_availability(
        cve_id: str,
    ) -> List[types.TextContent | types.ImageContent | types.EmbeddedResource]:
        """
        Check for the availability of public exploits for a CVE.
        Searches multiple databases and sources including ExploitDB, Metasploit, and others.
    
        Args:
            cve_id: CVE identifier in format CVE-YYYY-NNNN
    
        Returns:
            List of content containing exploit availability information or error messages
        """
        # Clean up CVE ID format
        cve_id = cve_id.upper().strip()
        if not cve_id.startswith("CVE-"):
            cve_id = f"CVE-{cve_id}"
    
        # Validate CVE ID format (CVE-YYYY-NNNN)
        if not re.match(r"^CVE-\d{4}-\d{4,}$", cve_id):
            return [
                types.TextContent(
                    type="text",
                    text=f"Error: Invalid CVE ID format. Expected format: CVE-YYYY-NNNN (e.g., CVE-2021-44228). Got: {cve_id}",
                )
            ]
    
        headers = {
            "User-Agent": "MCP Exploit Availability Checker v1.0",
            "Accept": "application/json",
        }
    
        exploit_sources = {}
    
        try:
            timeout = httpx.Timeout(15.0, connect=10.0)
            async with httpx.AsyncClient(
                follow_redirects=True, headers=headers, timeout=timeout
            ) as client:
                # Check 1: NIST NVD for CVE references that might indicate exploits
                nvd_url = f"https://services.nvd.nist.gov/rest/json/cves/2.0?cveId={cve_id}"
                try:
                    nvd_response = await client.get(nvd_url)
                    if nvd_response.status_code == 200:
                        nvd_data = nvd_response.json()
                        if nvd_data.get("totalResults", 0) > 0:
                            cve_item = nvd_data["vulnerabilities"][0]["cve"]
    
                            # Check references for exploit indicators
                            exploit_indicators = []
                            references = cve_item.get("references", [])
    
                            for ref in references:
                                url = ref.get("url", "").lower()
                                tags = [tag.lower() for tag in ref.get("tags", [])]
    
                                # Look for exploit-related keywords
                                if (
                                    "exploit" in tags
                                    or "exploit" in url
                                    or "poc" in url
                                    or "proof" in url
                                    or "github.com" in url
                                    or "packetstorm" in url
                                    or "metasploit" in url
                                    or "rapid7" in url
                                ):
                                    exploit_indicators.append(
                                        {
                                            "url": ref.get("url", ""),
                                            "source": ref.get("source", ""),
                                            "tags": ref.get("tags", []),
                                        }
                                    )
    
                            if exploit_indicators:
                                exploit_sources["NVD_References"] = {
                                    "status": "POTENTIAL_EXPLOITS_FOUND",
                                    "count": len(exploit_indicators),
                                    "details": exploit_indicators[:5],  # Limit to first 5
                                }
                            else:
                                exploit_sources["NVD_References"] = {
                                    "status": "NO_EXPLOIT_INDICATORS",
                                    "count": 0,
                                    "details": [],
                                }
                except Exception as e:
                    exploit_sources["NVD_References"] = {
                        "status": "ERROR",
                        "error": str(e),
                    }
    
                # Check 2: Search CVE Mitre for additional exploit references
                try:
                    mitre_url = f"https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword={cve_id}"
                    # Note: This is a basic check since MITRE doesn't have a simple API
                    mitre_response = await client.get(mitre_url)
                    if mitre_response.status_code == 200:
                        content = mitre_response.text.lower()
                        exploit_keywords = [
                            "exploit",
                            "proof of concept",
                            "poc",
                            "metasploit",
                            "weaponized",
                        ]
                        found_keywords = [kw for kw in exploit_keywords if kw in content]
    
                        if found_keywords:
                            exploit_sources["MITRE_Page"] = {
                                "status": "EXPLOIT_KEYWORDS_FOUND",
                                "keywords": found_keywords,
                            }
                        else:
                            exploit_sources["MITRE_Page"] = {
                                "status": "NO_EXPLOIT_KEYWORDS",
                                "keywords": [],
                            }
                except Exception as e:
                    exploit_sources["MITRE_Page"] = {
                        "status": "ERROR",
                        "error": str(e),
                    }
    
                # Check 3: Search GitHub for potential PoCs (indirect check)
                try:
                    # Note: This would require GitHub API for full search
                    # For now, we'll provide guidance on manual checking
                    exploit_sources["GitHub_Search"] = {
                        "status": "MANUAL_CHECK_RECOMMENDED",
                        "search_url": f"https://github.com/search?q={cve_id}+exploit&type=repositories",
                        "search_url_poc": f"https://github.com/search?q={cve_id}+poc&type=repositories",
                    }
                except Exception as e:
                    exploit_sources["GitHub_Search"] = {
                        "status": "ERROR",
                        "error": str(e),
                    }
    
                # Check 4: ExploitDB search guidance (since they don't have a public API)
                exploit_sources["ExploitDB"] = {
                    "status": "MANUAL_CHECK_RECOMMENDED",
                    "search_url": f"https://www.exploit-db.com/search?cve={cve_id}",
                    "description": "Check ExploitDB manually for verified exploits",
                }
    
                # Check 5: Metasploit modules guidance
                exploit_sources["Metasploit"] = {
                    "status": "MANUAL_CHECK_RECOMMENDED",
                    "search_guidance": f"Search for '{cve_id}' in Metasploit Framework",
                    "command": f"msfconsole -q -x 'search cve:{cve_id}; exit'",
                }
    
        except Exception as e:
            return [
                types.TextContent(
                    type="text",
                    text=f"Error: Failed to check exploit availability: {str(e)}",
                )
            ]
    
        # Analyze results and determine overall risk
        exploit_found = False
        potential_exploits = False
    
        for source, data in exploit_sources.items():
            if isinstance(data, dict):
                status = data.get("status", "")
                if "FOUND" in status or "POTENTIAL" in status:
                    if "POTENTIAL" in status:
                        potential_exploits = True
                    else:
                        exploit_found = True
    
        # Format the response
        result = f"šŸ›”ļø **Exploit Availability Report: {cve_id}**\n\n"
    
        # Overall assessment
        if exploit_found:
            risk_level = "šŸ”“ HIGH RISK"
            risk_desc = "Public exploits appear to be available"
        elif potential_exploits:
            risk_level = "🟠 MEDIUM RISK"
            risk_desc = "Potential exploit indicators found"
        else:
            risk_level = "🟢 LOW RISK"
            risk_desc = "No obvious public exploits found"
    
        result += f"āš ļø **Risk Assessment:** {risk_level}\n"
        result += f"šŸ“ **Assessment:** {risk_desc}\n\n"
    
        result += "šŸ” **Detailed Source Analysis:**\n\n"
    
        # NVD References Analysis
        nvd_data = exploit_sources.get("NVD_References", {})
        if nvd_data.get("status") == "POTENTIAL_EXPLOITS_FOUND":
            result += f"**šŸ“š NVD References:** āœ… Found {nvd_data.get('count', 0)} potential exploit references\n"
            for detail in nvd_data.get("details", [])[:3]:  # Show first 3
                result += f"   • {detail.get('url', '')}\n"
                if detail.get("tags"):
                    result += f"     Tags: {', '.join(detail.get('tags', []))}\n"
        elif nvd_data.get("status") == "NO_EXPLOIT_INDICATORS":
            result += "**šŸ“š NVD References:** ⚪ No exploit indicators in references\n"
        elif nvd_data.get("status") == "ERROR":
            result += f"**šŸ“š NVD References:** āŒ Error checking ({nvd_data.get('error', 'Unknown')})\n"
    
        # MITRE Analysis
        mitre_data = exploit_sources.get("MITRE_Page", {})
        if mitre_data.get("status") == "EXPLOIT_KEYWORDS_FOUND":
            result += f"**šŸ›ļø MITRE Page:** āš ļø Exploit-related keywords found: {', '.join(mitre_data.get('keywords', []))}\n"
        elif mitre_data.get("status") == "NO_EXPLOIT_KEYWORDS":
            result += "**šŸ›ļø MITRE Page:** ⚪ No exploit keywords detected\n"
    
        result += "\nšŸ”— **Manual Verification Recommended:**\n\n"
    
        # GitHub Search
        github_data = exploit_sources.get("GitHub_Search", {})
        result += "**šŸ™ GitHub Search:**\n"
        result += f"   • Repository search: {github_data.get('search_url', '')}\n"
        result += f"   • PoC search: {github_data.get('search_url_poc', '')}\n\n"
    
        # ExploitDB
        exploitdb_data = exploit_sources.get("ExploitDB", {})
        result += "**šŸ’„ ExploitDB:**\n"
        result += f"   • Search URL: {exploitdb_data.get('search_url', '')}\n"
        result += f"   • Description: {exploitdb_data.get('description', '')}\n\n"
    
        # Metasploit
        metasploit_data = exploit_sources.get("Metasploit", {})
        result += "**šŸŽÆ Metasploit Framework:**\n"
        result += f"   • Command: `{metasploit_data.get('command', '')}`\n"
        result += f"   • Guidance: {metasploit_data.get('search_guidance', '')}\n\n"
    
        result += "šŸ’” **Additional Resources:**\n"
        result += f"   • VulnCheck: https://vulncheck.com/search?q={cve_id}\n"
        result += f"   • PacketStorm: https://packetstormsecurity.com/search/?q={cve_id}\n"
        result += "   • SecLists: Check security mailing lists and advisories\n\n"
    
        result += "🚨 **Security Recommendations:**\n"
        if risk_level.startswith("šŸ”“"):
            result += "   • 🚨 **URGENT:** Treat as actively exploited\n"
            result += "   • šŸ›”ļø Implement immediate mitigations\n"
            result += "   • šŸ“Š Enhanced monitoring for attack attempts\n"
            result += "   • ⚔ Emergency patching procedures\n"
        elif risk_level.startswith("🟠"):
            result += "   • āš ļø **HIGH PRIORITY:** Assume exploitable\n"
            result += "   • šŸ“‹ Accelerated patching timeline\n"
            result += "   • šŸ‘€ Monitor for new exploit releases\n"
            result += "   • šŸ”’ Additional security controls\n"
        else:
            result += "   • šŸ“… **STANDARD:** Follow normal patching schedule\n"
            result += "   • šŸ“Š Continue monitoring threat landscape\n"
            result += "   • šŸ” Periodic re-evaluation recommended\n"
    
        result += (
            f"\nšŸ“Š **Report Generated:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
        )
    
        return [types.TextContent(type="text", text=result)]
  • Registers the 'get_exploit_availability' tool in the MCP server's list_tools() function, including its name, description, and input schema requiring 'cve_id'.
    types.Tool(
        name="get_exploit_availability",
        description="Check for public exploits and PoCs for a CVE",
        inputSchema={
            "type": "object",
            "required": ["cve_id"],
            "properties": {
                "cve_id": {
                    "type": "string",
                    "description": exploit_description,
                }
            },
        },
    ),
  • Dispatch logic in the server's fetch_tool() handler that routes calls to 'get_exploit_availability' by invoking the imported handler function with the 'cve_id' argument.
    elif name == "get_exploit_availability":
        if "cve_id" not in arguments:
            return [
                types.TextContent(
                    type="text", text="Error: Missing required argument 'cve_id'"
                )
            ]
        return await get_exploit_availability(arguments["cve_id"])
  • Input schema definition for the tool, specifying the required 'cve_id' string parameter with description.
    inputSchema={
        "type": "object",
        "required": ["cve_id"],
        "properties": {
            "cve_id": {
                "type": "string",
                "description": exploit_description,
            }
        },
    },
  • Re-exports the get_exploit_availability handler from its module for convenient import in the server.
    from .exploit_availability import get_exploit_availability
    from .package_vulnerability import check_package_vulnerabilities
    from .vex_status import get_vex_status
    from .vulnerability_search import search_vulnerabilities
    from .vulnerability_timeline import get_vulnerability_timeline
    
    __all__ = [
        "lookup_cve",
        "check_package_vulnerabilities",
        "get_epss_score",
        "calculate_cvss_score",
        "search_vulnerabilities",
        "get_exploit_availability",
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It adds context by listing sources (ExploitDB, Metasploit, GitHub, NVD) and return types (threat intelligence, exploitation indicators, weaponization status), but doesn't cover aspects like rate limits, authentication needs, or potential errors. It doesn't contradict annotations, as none exist.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence that front-loads the core purpose ('Check for public exploits and PoCs for a CVE') with no wasted words. Every part of the sentence contributes essential information, making it highly concise and well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (threat intelligence query), no annotations, and no output schema, the description is moderately complete. It covers purpose, sources, and return types, but lacks details on output format, error handling, or integration with sibling tools, leaving some gaps for an agent to infer behavior.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the input schema already fully documents the 'cve_id' parameter with format details and purpose. The description adds no additional parameter semantics beyond what's in the schema, meeting the baseline score of 3 for high coverage without extra value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose with specific verbs ('check for public exploits and PoCs') and resources ('for a CVE'), distinguishing it from siblings like 'cve_lookup' (general info) or 'get_epss_score' (exploit prediction). It precisely defines what the tool does without being vague or tautological.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage context by specifying 'check for public exploits and PoCs for a CVE,' suggesting it's for threat intelligence and risk assessment. However, it lacks explicit guidance on when to use this tool versus alternatives like 'search_vulnerabilities' or 'get_vex_status,' which could help differentiate further.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

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/firetix/vulnerability-intelligence-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server