threatintel-mcp
Provides tools for looking up file hashes, domains, and IP addresses to retrieve multi-engine detection ratios, threat labels, and reputation context from VirusTotal.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@threatintel-mcplookup ip 8.8.8.8"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
threatintel-mcp
An MCP server that wraps threat-intelligence lookup APIs — urlscan.io and VirusTotal — so an AI agent (e.g. Claude) can pivot on indicators during an investigation the way an analyst does at a terminal.
This is a portfolio demonstration. It is a compact, self-contained example built to show design judgment around MCP servers for threat intelligence: tool ergonomics, compact/structured output, rate-limit hygiene, OPSEC, and treating tool output as untrusted. It is not a production incident-response platform, and it wraps only a small slice of each provider's API.
Why this exists
When you investigate a suspicious indicator, you pivot: a URL leads to a domain, the domain resolves to an IP, the IP belongs to an ASN, a dropped file has a hash, that hash shows up on other scans. Each hop is an API call to a different threat-intel platform.
Exposing those platforms as MCP tools lets an agent do that pivoting autonomously and in natural language — "is this domain malicious, and what else lives on its hosting?" — while the human stays in the loop for judgment. MCP is the clean seam for this: one small server, any MCP-capable client.
Related MCP server: virustotal-mcp-server
What it does — the tools
Tool | Provider | Purpose |
| urlscan.io | Submit a URL for a live sandbox scan (returns a |
| urlscan.io | Poll a scan |
| urlscan.io | Passively search historical scans (Elasticsearch query syntax). |
| VirusTotal v3 | Multi-engine verdict + threat label for a file hash (MD5/SHA-1/SHA-256). |
| VirusTotal v3 | Reputation, registrar, creation date, categories for a domain. |
| VirusTotal v3 | Reputation + hosting context (ASN, owner, country) for an IP. |
Each tool's docstring is written as a "when to call me" prompt — FastMCP turns the type hints and docstring into the JSON Schema and description the model sees, so the tools are self-documenting to the agent.
Architecture & design decisions
Three urlscan primitives, three VT lookups. urlscan is modeled around its own submit → poll → search loop; VirusTotal around direct object lookups. That mapping keeps each tool a thin, predictable wrapper over one endpoint.
Compact, structured output — not raw API JSON. A single VirusTotal file
report or urlscan result can be hundreds of KB (every AV engine's verdict, the
full DOM, every request/response). Dumping that into a model's context is
wasteful and buries the signal. Every tool projects the response down to the
handful of fields an investigator actually pivots on — detection ratio, threat
label, reputation, ASN/owner, contacted domains/IPs, first/last seen. This is a
deliberate design choice, commented at each summarize_* function in
virustotal.py / urlscan.py.
All tool output is treated as untrusted and defanged. Threat-intel responses
contain attacker-controlled content — a phishing page's title, a malicious
domain, a WHOIS record. MCP tool output is a prompt-injection surface for the
model and a click-hazard for a human reading a terminal. So every indicator
is defanged on the way out (http → hxxp, evil.test → evil[.]test,
1.2.3.4 → 1[.]2[.]3[.]4) at a single central choke point (sanitize.py).
Client-side rate limiting. The VirusTotal public tier allows 4 req/min and
500/day. A per-API sliding-window limiter (ratelimit.py) throttles locally so a
well-behaved server never trips the upstream 429 under normal single-analyst use.
Structured errors, never raw tracebacks. Auth failures, 404s, upstream 429s,
timeouts and local rate-limit hits are all mapped to small categorized dicts
(errors.py) so the agent can decide whether to retry, back off, or ask for a
key.
Secrets from the environment only. VT_API_KEY and URLSCAN_API_KEY are
read from the environment (or a local, gitignored .env). Nothing is hardcoded.
Transports: stdio vs. Streamable HTTP
stdio (default) — the client spawns the server as a subprocess over stdin/stdout. Best for a single local analyst running Claude Desktop or an IDE MCP client on their own workstation with their own keys.
Streamable HTTP (
--transport http) — the server runs as a long-lived networked process. Best for a shared team deployment: one server holding the org's keys and rate-limit budget, many analysts pointing their clients at it.
Setup
Requires Python 3.10+.
git clone https://github.com/ChristianPresley/threatintel-mcp.git
cd threatintel-mcp
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e ".[dev]"
cp .env.example .env # then edit .env and add your keysGet API keys:
VirusTotal: https://www.virustotal.com/gui/my-apikey
urlscan.io: https://urlscan.io/user/profile/
Running
# stdio (local analyst) — this is what an MCP client launches for you:
threatintel-mcp --transport stdio
# Streamable HTTP (shared team) — long-lived server on a port:
threatintel-mcp --transport http --host 0.0.0.0 --port 8000Claude Desktop / MCP client config
Add to claude_desktop_config.json (macOS:
~/Library/Application Support/Claude/, Windows:
%APPDATA%\Claude\):
{
"mcpServers": {
"threatintel": {
"command": "threatintel-mcp",
"args": ["--transport", "stdio"],
"env": {
"VT_API_KEY": "your-virustotal-key",
"URLSCAN_API_KEY": "your-urlscan-key"
}
}
}
}If threatintel-mcp isn't on the client's PATH, use the absolute path to the
venv entry point (e.g. .venv/Scripts/threatintel-mcp.exe on Windows) or invoke
via python -m threatintel_mcp.server.
Worked example: pivoting a suspicious domain
An analyst hands the agent a suspicious link. A natural investigation flow:
scan_url("http://secure-login-microsoft.example/")— submits an unlisted scan (so the adversary isn't tipped off) and returns auuid.get_url_result(uuid)— comes backmalicious: true, brandMicrosoft(credential phish), and a set of contacted domains/IPs includingpage_ip: 203[.]0[.]113[.]9on ASNEVIL-HOST.lookup_domain("secure-login-microsoft.example")— VT shows a creation date three days ago (newly-registered-domain signal) and a couple of engines already flagging it.lookup_ip("203.0.113.9")— the hosting IP has poor reputation and hosts in a country inconsistent with the impersonated brand.search_urlscan("page.ip:203.0.113.9")— passively reveals other phishing pages on the same box, expanding the campaign's footprint.
Five hops, two providers, one MCP server — and every indicator in the transcript is defanged so nothing is accidentally clicked or re-interpreted downstream.
Development
pytest # runs the mocked test suite — no real API calls are made
ruff check . # lintTests mock every HTTP interaction with respx; the suite never touches the
network and needs no real API keys.
License
MIT © 2026 Christian Presley — see LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Security scanner for MCP servers. Detect vulnerabilities, prompt injection, and tool poisoning.
MCP server for Pentest-Tools.com: run scans, manage findings and reports via your preffered LLM.
URLhaus MCP — wraps abuse.ch URLhaus malware URL database (free, no auth)
MCP server for secureFlows: token-free URL builders and integration-linting tools for AI agents.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceAn MCP server that exposes a 60+ tool security and threat-intel stack to AI agents, enabling secret scanning, Sigma rule generation, ransomware lookup, OSINT, and deep research.1MIT
- FlicenseAqualityDmaintenanceMCP server for security analysis using VirusTotal API, enabling AI assistants to analyze URLs, files, IP addresses, and domains with automatic relationship fetching.81-
- AlicenseCqualityDmaintenanceA Model Context Protocol (MCP) server that enables LLMs to interact with the VirusTotal API for malware analysis, URL scanning, and threat intelligence.81MIT
- AlicenseAqualityBmaintenanceMCP server for urlscan.io that scans URLs, searches historical scan data, and assesses indicators with compact, context-efficient summaries instead of raw API responses.14MIT