Back to Articles

Building an LLM-Powered Threat Intelligence Assistant with VirusTotal MCP

[ View on GitHub ]

Building an LLM-Powered Threat Intelligence Assistant with VirusTotal MCP

Hook

What if you could ask Claude “Is this URL malicious?” and get back not just a scan result, but a complete threat landscape including contacted domains, downloaded files, and linked threat actors—all from a single natural language query?

Context

Security analysts face a common problem: VirusTotal contains invaluable threat intelligence, but extracting comprehensive context requires multiple API calls, understanding relationship structures, and manually correlating data across entities. Want to investigate a suspicious file? You’ll need separate requests for the base report, behavioral analysis, dropped files, network connections, and threat actor associations. This fragmentation slows incident response and raises the barrier to entry for junior analysts.

The VirusTotal MCP server addresses this by implementing the Model Context Protocol—a specification that lets Large Language Models invoke functions as tools. By wrapping VirusTotal’s API in MCP-compatible functions, it transforms Claude Desktop (and other MCP clients) into a conversational threat intelligence platform. Instead of writing Python scripts or crafting API requests, analysts can ask natural language questions and receive automatically enriched security context. The server handles authentication, relationship traversal, and data aggregation behind the scenes.

Technical Insight

The architecture follows MCP’s tool-based paradigm where each function becomes a capability the LLM can invoke. The server exposes two tiers of tools: comprehensive report functions that automatically fetch relationship data, and granular relationship queries for deep investigation. This dual-layer design is the project’s most thoughtful architectural decision.

Consider the get_url_report tool. Rather than returning just scan results, it automatically fetches key relationships—communicating files, contacted domains, downloaded files, redirects, and threat actors. The README indicates these are fetched automatically, though the exact concurrency implementation details aren’t documented. Here’s how you’d use it from an MCP client:

await get_url_report(url="http://example.com/suspicious")

This single call returns a structured report with sections for basic analysis, detection statistics, and all relevant relationship data. For analysts, this means asking Claude “Analyze this URL” provides immediate context about infrastructure, payloads, and attribution—no follow-up queries needed.

When you need granular control, the relationship tools provide paginated access to specific entity connections. The get_url_relationship tool accepts a relationship type parameter (like communicating_files or contacted_domains), a limit (1-40 items), and an optional cursor for pagination:

await get_url_relationship(
    url="http://example.com/suspicious",
    relationship="communicating_files",
    limit=20,
    cursor="next_page_token"
)

This design elegantly balances convenience and control. Initial investigations get rich context automatically, while deep dives can retrieve hundreds of related objects through paginated requests. The relationship type enumerations are extensive—file reports support numerous relationship types including behavioral analysis, memory patterns, and embedded content.

The MCP integration itself relies on a server process that Claude Desktop (or other clients) launches via stdio. The server registers tools with typed parameters, and the LLM invokes them based on user queries. When you ask “What files has this IP distributed?”, the LLM maps that to get_ip_relationship with relationship="communicating_files", executes the call, and synthesizes the response into natural language. This abstraction makes threat intelligence accessible to non-technical stakeholders who can’t write API scripts.

One clever implementation detail: the report tools categorize relationship data by type (infrastructure, payloads, attribution) rather than dumping raw JSON. This structured formatting helps both LLMs and humans quickly identify relevant threat indicators. For example, domain reports separate SSL certificates, subdomains, and historical data into distinct sections, making it trivial to spot certificate anomalies or suspicious subdomain patterns.

Gotcha

The project’s biggest limitation is its documentation gaps. The README marks “Quick Start” as TBD and provides no manual installation instructions beyond “TBD.” While Smithery installation works (npx -y @smithery/cli install @emeryray2002/virustotal-mcp --client claude), developers who want to fork, modify, or run it standalone have no guidance. The requirements section shows incomplete dependency information—listing “Python >= 3.11” but cutting off the aiohttp version requirement mid-specification. For a security tool, this lack of complete documentation is concerning—you can’t audit what you can’t properly install.

API quota exhaustion is another practical concern. The report tools’ automatic relationship fetching is convenient but potentially quota-expensive. A single comprehensive report call fetches multiple relationship types automatically. VirusTotal’s free tier allows 500 requests per day, which could be consumed quickly with comprehensive queries. The tool doesn’t expose quota management, rate limiting, or selective relationship fetching—it’s all or nothing. Production use would require a premium VirusTotal subscription and possibly forking the code to add quota-aware request throttling.

With only 3 GitHub stars and no visible production deployments, this is uncharted territory. The codebase likely hasn’t faced edge cases like malformed API responses, network failures during relationship fetching, or handling VirusTotal’s eventual consistency model. There’s no test suite mentioned, no CI/CD badges, and no issue tracker activity. Using this in production security workflows means accepting the risk of being an early adopter.

Verdict

Use if you’re building LLM-powered security workflows with Claude Desktop or other MCP clients, and want to prototype threat intelligence features quickly without writing API integration code. The automatic relationship fetching genuinely accelerates security investigations by providing rich context in single queries—ideal for analysts who need fast triage or junior staff who lack deep VirusTotal expertise. It’s also valuable for security teams experimenting with AI-assisted incident response, where natural language queries lower the barrier to threat intelligence. Skip if you need production-ready reliability, comprehensive documentation, or fine-grained control over API quota usage—direct VirusTotal API integration offers better stability and flexibility for traditional automation. Also skip if you don’t already use MCP-compatible tools; adopting an entire protocol specification just for VirusTotal access is overkill when direct API integration or existing Python libraries suffice. Finally, skip if you’re building customer-facing security products where unvetted dependencies pose compliance or liability risks.

// QUOTABLE

What if you could ask Claude "Is this URL malicious?" and get back not just a scan result, but a complete threat landscape including contacted domains, downloaded files, and linked threat actors—al...

[ Tweet This ]
// ADD TO YOUR README
[![Featured on Starlog](https://starlog.is/api/badge/developer-tools/emeryray2002-virustotal-mcp.svg)](https://starlog.is/api/badge-click/developer-tools/emeryray2002-virustotal-mcp)