offsec-mcp
Enables subdomain enumeration by querying DuckDuckGo's HTML search interface (dorking) to discover brand-name hosts that may not appear in other passive sources.
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., "@offsec-mcprun full recon on example.com and save the results"
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.
offsec-mcp
MCP server for bug bounty recon. Enumerate subdomains, hunt JS leaks, fingerprint WAFs, detect takeovers, probe sensitive files, & scan with nuclei — from any local LLM or MCP client (LlamaFile, Claude Desktop, Cursor, Cline, Continue).
No cloud APIs. No API keys. No telemetry. Everything runs on your machine.
Quick Start (60 seconds)
# 1. clone + enter
git clone https://github.com/mbilalraza231/offsec-mcp.git
cd offsec-mcp
# 2. virtual env + python deps
python -m venv .venv
.\.venv\Scripts\Activate.ps1 # Windows (macOS/Linux: source .venv/bin/activate)
pip install -r requirements.txt
# 3. (optional but recommended) fetch the recon binaries
.\installers\install-tools.ps1 # macOS/Linux: ./installers/install-tools.sh
# 4. start the MCP server
python server.py # serves http://127.0.0.1:8000/sseThen point any MCP client at http://127.0.0.1:8000/sse (SSE transport) and ask:
"Use the full_recon tool on example.com"
It works without step 3. Every tool has a pure-Python fallback, so you can skip the binaries and still enumerate + check liveness + detect takeovers. Only
scan_vulnerabilities(nuclei) needs its binary.
Related MCP server: Bug Bounty Assistant MCP
Why
Local LLMs (Llama 3, Qwen, DeepSeek via LlamaFile / Ollama) can reason about recon results, but they can't run recon tools. MCP fixes that. This server is the bridge.
What it does
MCP tool | Backed by | Fallback |
| subfinder -all + 11 passive APIs (incl. 2 search-engine dorks — DuckDuckGo + Bing — which find brand-name hosts no wordlist can reach) + dnsx 110k-wordlist DNS brute (finds non-web subs like git/smtp/jenkins) + Altdns-style permutation engine (finds compound names like staging-api, api-v2) + httpx content-diff brute (browser-UA, sees through Vercel/Cloudflare) + Wayback crawl | all Python, no binary needed |
| dnsx | dnspython |
| Tier 1 curl_cffi (Chrome 120 TLS and HTTP/2 fingerprint) with fallback chain curl_cffi-strict, curl_cffi-relaxed, requests-strict, requests-relaxed; optional Go httpx subprocess | 5-bucket output: |
| NEW (Tier 1) — deep-fetch HTML & JS on each alive URL, extract hidden hosts, API endpoints, potential leaked secrets (AWS keys, GitHub tokens, JWTs, PEMs, Stripe) | pure Python regex |
| NEW (Tier 1) — probe ~60 paths ( | pure Python HTTP |
| NEW (Tier 2) — 21 CDN/WAF signatures (Cloudflare, Vercel, Netlify, AWS CloudFront, Akamai, Fastly, Imperva, Sucuri, F5, GCP, GitHub Pages, Azure Front Door, Fly.io, Render, Heroku, …) | response headers only |
| NEW (Tier 2) — Wayback Machine CDX deep harvest; every archived URL & | free CDX API |
| nuclei | none (clear error) |
| pure Python CNAME fingerprint | — |
| all of the above, 9-stage pipeline, one call | — |
| writes | — |
| runtime binary detection | — |
| reads | — |
11 Passive Sources (all free, no keys needed)
The enumerate_subdomains tool queries 11 sources in parallel using
ThreadPoolExecutor. Any single failure never blocks the pipeline.
# | Source | Type | What it finds |
1 | subfinder (binary, | 50+ APIs merged | Massive passive coverage |
2 | crt.sh | Cert Transparency | All issued SSL certs |
3 | CertSpotter | Cert Transparency | Independent CT mirror (redundancy when crt.sh 502s) |
4 | DuckDuckGo HTML dork | Search engine index | Brand-name hosts only visible in live links (e.g. |
5 | Bing HTML dork | Search engine index | Different crawl slice — hosts DDG/Google miss (e.g. |
6 | HackerTarget | Passive DNS | Free hostsearch API |
7 | AlienVault OTX | Passive DNS | Historical resolutions |
8 | RapidDNS | Community DB | Scraped subdomains |
9 | Wayback Machine | URL archive | Historical archived URLs |
10 | ip.thc.org | Passive subdomains | The Hacker Choice DB |
11 | bgp.he.net | Cert Transparency | Hurricane Electric CT logs |
Why we don't have 30 sources (honest answer)
Bug bounty tools often advertise "50+ sources" — most are dead, need API keys, or rate-limit to 1 hit/day. When tested live, the following all failed on typical recon runs (returned 401/403/404, DNS resolution errors, or empty JSON):
Attempted | Status |
Chaos Project ( | 401 — moved to key-required |
Anubis ( | returns HTML error page, JSON broken |
Riddings.io | domain not resolving |
Mnemonic PassivDNS | non-JSON response |
DNSGrep.cn | domain not resolving |
urlscan.io | 404/200 empty on free endpoint |
Mojeek | domain not resolving |
Startpage | 200 but 0 hosts (blocked) |
PublicWWW | 200 but 0 hosts (blocked) |
Brave Search | 429 rate-limited |
Qwant | 403 blocked |
Netcraft Site Report | domain not resolving |
Searchcode | domain not resolving |
CommonCrawl index | connection reset |
DNSDumpster | domain not resolving |
That's 15 tried + 2 that work (DDG + Bing). Free is free — the good ones get crowded out. If you want MORE coverage, the upgrade path is optional API keys: VirusTotal, SecurityTrails, Netlas, BinaryEdge, Google Custom Search JSON.
Plus four active stages that run after the passive sources:
Stage | Technique | Catches what passive misses |
dnsx DNS brute | Full SecLists 110k wordlist over DNS with wildcard-IP filter | Non-web subdomains (git, smtp, jenkins, redis, internal) that don't serve HTTP |
Altdns permutations | Numbered + modifier-cross-product + hyphen↔dot variants of known labels | Real-world compound names not in any wordlist: |
active-dns HTTP verify | ~500 curated service names (services.txt + top 250 by frequency from subdomains-110k.txt), resolve+probe in one pass, content-diff filter using 10 randomized nonsense-name baselines | Live hosts absent from every index; sees through Vercel/Cloudflare bot-walls |
must-probe curated | 40 high-value names (mail, webmail, git, admin, cpanel, smtp, autodiscover, mx, ...) checked via direct DNS even when wildcard DNS is detected | Hosts on totally different infra (non-wildcard IP pool) that wildcard HTTP verify cannot distinguish |
Wayback link-crawl | Fetch newest archived pages of apex + www + top discovered hosts, scrape cross-links | Hosts never archived themselves but referenced from real pages |
Why HTTP brute uses ~500 names, DNS brute uses 110k
HTTP requests are heavy — every probe costs a TLS handshake, a Chrome-impersonated session, a full HTTP response body, and each sequential probe to a Vercel-fronted target adds rate-limit pressure. Full 110k over HTTP would take 3-4 hours and trigger bot-detection within the first 5 minutes. Curated ~500 covers 95%+ of real-world subdomains in 40-90s.
DNS queries are cheap — a single 40-byte UDP packet plus a 10-byte answer. dnsx processes 110k queries in under 2 minutes at 1000 qps without any bot-detection risk. So DNS brute does use the full wordlist, HTTP brute does not.
Both stages automatically skip when wildcard DNS is detected on the
apex (because every random name resolves and the results are useless).
must-probe intentionally does NOT skip on wildcard because it uses
IP-pool comparison, not content comparison, to filter noise.
Source attribution: every result reports which source found which subdomain.
How it works behind the scenes
Three players:
You (LlamaFile UI) -> Llama-3.1 (the brain) -> offsec-mcp (the hands)LlamaFile = the chat screen.
Llama-3.1 = the model on your GPU. It cannot browse or run tools. It only decides which tool to call and turns the result into English.
offsec-mcp = this server. It runs the real recon tools locally and hands back real numbers.
They talk over SSE — a live HTTP connection at http://127.0.0.1:8000/sse.
A single request, step by step:
On connect, the server advertises 9 tools + descriptions.
You type
enumerate subdomains for example.com.The model does not guess. It emits a structured call:
{ "tool": "enumerate_subdomains", "arguments": { "domain": "example.com" } }The server fires 8 passive sources in parallel (ThreadPoolExecutor) plus a ~500-name httpx brute force — one shared deadline, no sequential waiting.
Merge → dedup → wildcard-noise filter → cap to 30 names (so the model's context window is never flooded).
Result goes back to the model as JSON; the model writes the summary.
Key design choices
Choice | Why |
Real binaries, not model guessing | The LLM never fabricates a subdomain — every name is tool-verified |
Parallel sources | 8 sources at once ≈ time of the slowest one, not the sum |
| Some clients send lists as strings; we normalize both |
Output capping | Thousands of results would overflow an 8B model's context |
Binary detection + Python fallback | Works with or without |
Wildcard CDN targets (Vercel, Cloudflare, Akamai)
Modern PaaS platforms layer three different "noise" responses on top of a wildcard DNS record, and each one fools a naive scanner into reporting it as an alive target:
Layer | What the edge actually returns | Why a naive alive-checker misclassifies it |
Bot-wall (403 challenge) | 34 KB JS challenge page (Vercel Security Checkpoint, Cloudflare Turnstile interstitial, Akamai Bot Manager) | Body is big so "length under 500" rule misses it; scanner puts it in |
Deployment-missing (404 edge page) | Vercel | Body is 5-8 KB, still above the stale threshold; scanner puts it in |
Wildcard project HTTP handler (404 app page) | Every random name hits the same Next.js catch-all → identical | Real deployment for |
Tier 1 curl_cffi fingerprint stack
tools/_http.py sends every probe through a four-layer fallback
chain:
curl_cffi(impersonate="chrome120", strict TLS)
└─ fail → curl_cffi(chrome120, relaxed TLS) # self-signed certs
└─ fail → requests (strict TLS) # legacy host
└─ fail → requests (relaxed TLS)curl_cffi replicates Chrome 120's JA3 TLS ClientHello and HTTP/2
SETTINGS frame order byte-for-byte. Real Chrome opens 6-10 concurrent
connections to a CDN, so check_alive deliberately caps parallelism at
10 threads to keep the request pattern browser-plausible. Plain
Python requests would open 100 sessions in the same window and be
flagged instantly.
This alone raises the Vercel wall-bypass rate from about 10 to about 50 percent on typical bug-bounty-sized targets. It is probabilistic, not a guaranteed bypass. curl_cffi handles TLS and HTTP/2 signals; it does not execute JavaScript, persist cookies, or emit Sec-CH-UA client hints, so Vercel's scoring still challenges some requests.
Five-bucket classification
check_alive post-processes every response through three split
functions before returning:
_split_stale status 4xx AND (length under 500 OR body contains
a DEPLOYMENT_MISSING_SIGNATURES marker)
_split_bot_walled status 4xx AND title matches WALL_TITLE_SIGNATURES
_split_wildcard_http fetch offsec-wildcard-{nonce}.apex THREE times as
control probes and take the majority non-wall sig,
move any 4xx with identical (status, title)
_strip_private_fields drop the _deployment_missing helper flagResult:
{
"alive": [ ...real 200 responses with unique content... ],
"stale": [ ...Vercel DEPLOYMENT_NOT_FOUND / Netlify / Heroku... ],
"bot_walled": [ ...Vercel Checkpoint / Cloudflare Turnstile... ],
"wildcard_http": [ ...names matching the control-probe signature... ],
"dead": [ ...no HTTP response... ],
"engine": "python-curl_cffi",
"wildcard_http_signature": {"status": 404, "title": "404: not_found"}
}Downstream stages (js_endpoints, sensitive_files, nuclei) only
receive alive URLs so they never waste probes on walls or wildcards.
waf_fingerprint additionally receives stale, bot_walled and
wildcard_http because every one of those buckets still carries useful
edge headers (server, x-vercel-id, cf-ray, x-nf-app-id,
x-akamai-request-id) that identify the CDN stack.
Multi-part TLD awareness
_infer_apex (used to build the wildcard control probe URL) recognises
~150 second-level suffixes so that shop.example.co.uk correctly
resolves to example.co.uk instead of the nonsense string co.uk.
Covers UK, AU, NZ, JP, KR, CN, IN, PK, BD, NP, LK, SG, MY, PH, VN, ID,
TH, BR, MX, AR, CO, PE, UA, TR, ZA, KE, NG, GH, TZ, UG, ZW, EG, IL.
Baseline calibration against bot-walls
Content-diff filtering (both in enumerate and in check_alive)
memorises what a known-fake name looks like and drops everything
matching that signature. The failure mode: when Vercel or Cloudflare
serves its challenge page to our baseline probes themselves, we
memorise the wall instead of the real wildcard catchall. Then every
real wildcard 404 looks "different from the memorised wall" and
slips through as if it were a real subdomain.
Both stages now calibrate defensively:
_active_dns_verify in tools/enumerate.py
10 baseline nonsense-name probes (was 6). Higher probability that at least one breaks through the wall.
Wall signatures (Vercel Checkpoint, Cloudflare Turnstile, Akamai, etc.) are excluded from
baseline_sigswhen baselines respond — one walled probe cannot poison the calibration.Self-healing: if every baseline got walled or timed out, use the most-common non-wall sig among the ~500 candidates as the catchall.
Dominant-wall override: when a wall sig itself appears on 15+ hosts (or half of all probed responses), the edge is serving it to real and fake names uniformly. In that scenario the wall IS the catchall and is added back to
baseline_sigsso those names drop out too.Error-status cluster override: any 4xx or 5xx sig observed on 5+ hosts is a shared handler (real apps don't cluster on errors at that scale), so it's treated as catchall.
_http_wildcard_probe_sig in tools/alive.py
3 control nonsense-name probes (was 1) with majority vote over non-wall responses. Falls back to
Nonewhen all 3 got walled so the caller skips filtering safely rather than mis-flagging real subs as wildcard noise.
Tested on a wildcard-CDN target: pre-fix full_recon returned 43
subs with 31 mixed real-and-fake bot_walled entries. Post-fix same
target returns 8-12 subs with 5-7 bot_walled entries all pointing
to legitimate deployments.
How must-probe avoids wildcard noise
The must-probe curated stage (autodiscover, assets, docs,
git, admin, cpanel, smtp, mx, webmail, ...) is a
DNS-only pass designed to catch services that live on totally
separate infrastructure from the wildcard pool. Example: on a
Vercel-hosted target *.example.com returns Vercel edge IPs but
mail.example.com might CNAME to mail.mailprovider.example on an
unrelated IP (e.g. a Roundcube host on 45.8.227.100). A
naive wildcard filter would drop that real mail host.
To make this safe the tool uses strict zero-overlap rule:
probe 15 random nonsense names -> wildcard IP pool and CNAME pool
(15 probes because edge CDNs
rotate 2 IPs per response from
a pool of 4+; more probes =
better pool coverage)
for each of the 40 must-probe labels:
resolve CNAME and A records
if any CNAME overlaps wild_cnames -> drop (wildcard noise)
if any IP overlaps wild_ips -> drop (wildcard noise)
otherwise -> keep (genuinely different)The "otherwise keep" branch fires exactly when the name looks like
real distinct infra. Example with xinuty.com:
wild_ips = {216.198.79.1, .65, 64.29.17.1, .65} (Vercel pool)
mail.xinuty.com -> A [45.8.227.100] CNAME webmail.rabhost.com
no overlap -> KEEP (real Roundcube host)
api.xinuty.com -> A [216.198.79.1, 64.29.17.1] CNAME []
overlaps -> DROP (pure wildcard noise)
autodiscover.xinuty.com-> A [64.29.17.1, .65] CNAME []
overlaps -> DROP
docs.xinuty.com -> A [216.198.79.65, 64.29.17.1] CNAME []
overlaps -> DROPReal-world result on the fixed pipeline: xinuty must-probe returns
1 host (mail.xinuty.com) instead of the 10 wildcards and
non-overlapping fakes the loose check produced earlier.
Honest limits
A host stays hidden only when all three hold: no certificate- transparency entry, no Wayback archive, and the CDN answers every name identically even to a Chrome-fingerprinted request. The residual case is a property of the target's infrastructure, not a gap in this tool. Going beyond Tier 1 (TLS and HTTP/2 fingerprint) requires a real headless browser (Playwright / patchright). That is deliberately not shipped here because it adds ~300 MB RAM per worker and 100-200 ms per host, which breaks the "runs on your laptop" contract of this MCP server.
Install
Everything installs self-contained on the drive that holds the
project folder (SSD / USB / internal disk). No writes to C:\
except Python's own pip cache. Nothing is registered in the system
PATH. Unplug the drive, plug it into another machine, everything
still works.
What gets installed and what each piece is for
Item | Required? | Purpose | Where it lives |
Python 3.10 + | yes | Runtime for the MCP server | Your existing install |
| yes | Chrome TLS fingerprint to survive Vercel and Cloudflare bot-walls |
|
| optional but recommended | Faster and more accurate recon than the Python fallbacks |
|
| needed only for | 5000+ CVE and misconfig signatures nuclei matches against |
|
11 passive API sources | no | subfinder already wraps them; nothing to install | Free internet APIs |
1. Python dependencies
cd offsec-mcp
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r requirements.txt2. Recon binaries and nuclei templates (optional but recommended)
# Windows
Set-ExecutionPolicy -Scope Process Bypass -Force
.\installers\install-tools.ps1
# Linux / macOS
bash installers/install-tools.shThe script:
downloads the latest stable Windows/Linux/macOS releases of each tool from GitHub
extracts each
.exe(or Linux binary) into.\bin\bootstraps the nuclei template pack into
.\bin\nuclei-templates\so scanning works out of the box and nothing lands on the host machine'sC:\Users\<you>\nuclei-templates\
Binaries land project-local and do not touch system PATH.
Skip step 2 entirely and you can still enumerate, check liveness,
detect takeovers and harvest JS endpoints — every tool has a Python
fallback. Only scan_vulnerabilities genuinely needs the nuclei
binary and template pack.
2a. Bootstrap nuclei templates manually (only if step 2 was skipped)
# Windows
.\bin\nuclei.exe -update-templates -ud .\bin\nuclei-templates
# Linux / macOS
./bin/nuclei -update-templates -ud ./bin/nuclei-templatesTakes ~30-60s. After this full_recon returns real CVE findings
instead of nuclei exit=2 with no templates.
3. Run the MCP server
python server.pyYou'll see:
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)Verify it is alive (open a second PowerShell window):
Invoke-RestMethod http://127.0.0.1:8000/healthReturns status: ok plus the list of 13 MCP tools and which external binaries were detected on your bin/ directory.
4. Connect LlamaFile
Open LlamaFile → Add New MCP Server → paste:
http://127.0.0.1:8000/sseClick Add. The 13 tools above appear in the tool list.
⚠ Raise the MCP tool timeout before scanning big targets. LlamaFile's
default "Timeout for individual MCP tool calls" is 300s. On a target with
no wildcard DNS (e.g. most bug-bounty scopes) enumerate_subdomains
runs the full 110k-label dnsx sweep and can take 5-8 minutes end-to-end.
Bump the timeout to 900s in LlamaFile Settings → MCP → timeout field
beforehand, or you'll get MCP error -32001: Request timed out and no
results. Wildcard targets (Vercel / Netlify / CloudFront catch-all) finish
in 30-60s and need no change.
Demo prompts
Try these in LlamaFile after connecting:
Use the full_recon tool on tesla.com. Do not use any other tool.
Enumerate subdomains for facebook.com using the enumerate_subdomains tool
Scan https://testphp.vulnweb.com for vulnerabilities using nuclei
Check for subdomain takeover on example.com
Tip for LlamaFile --agent mode: be specific with the tool name and say "Do not use any other tool" to prevent the 8B model from chaining incorrectly.
Project layout
offsec-mcp/
├── server.py # MCP server entry point, registers 9 tools, runs SSE
├── config.py # detects binaries in ./bin/ or system PATH
├── storage.py # saves/reads ./output/*.json
├── tools/
│ ├── _http.py # Tier 1 shared HTTP stack: curl_cffi chrome120
│ │ # with 4-layer fallback to requests; exports
│ │ # strict_get / strict_head used by every other
│ │ # tool that talks to live hosts
│ ├── enumerate.py # 11 passive sources + DNS brute + Altdns-style
│ │ # permutations + active-dns verify (Python
│ │ # path uses strict_get) + Wayback crawl
│ ├── alive.py # Tier 1 concurrent probe (10 threads) + 3-bucket
│ │ # post-processing: _split_stale (length and
│ │ # body-signature), _split_bot_walled (title
│ │ # patterns), _split_wildcard_http (control
│ │ # probe on apex), _strip_private_fields
│ ├── resolve.py # dnsx + dnspython
│ ├── js_harvest.py # HTML and JS deep-parse for endpoints, secrets,
│ │ # hidden hosts (skips bot-walled URLs)
│ ├── sensitive.py # ~60 path probes (.git/HEAD, .env, actuator,
│ │ # backup.zip, phpinfo, etc.) with severity tags
│ ├── waf.py # 21 CDN/WAF signatures via headers and body
│ ├── archive.py # Wayback CDX deep harvest
│ ├── vuln.py # nuclei
│ └── takeover.py # pure-Python dangling-CNAME check
├── installers/
│ ├── install-tools.ps1
│ └── install-tools.sh
├── bin/ # downloaded binaries (gitignored)
├── output/ # saved scans (gitignored)
├── requirements.txt # includes curl-cffi>=0.6
├── .gitignore
├── LICENSE # MIT
└── README.mdHow the fallback logic works
Every tool file does the same thing:
Ask
config.find_tool("name")if the binary is installedIf yes → run it via
subprocess, parse its outputIf no → use a pure-Python equivalent
Return a dict with an
enginekey so the LLM knows which ran
For tools that talk to live target hosts (check_alive, js_harvest,
sensitive_files, waf_fingerprint, and the active-DNS verify stage in
enumerate), the Python equivalent is strict_get from tools/_http.py
which uses a Tier 1 four-layer fallback chain:
curl_cffi(impersonate="chrome120", verify=True) # preferred
↓ TLS or other error
curl_cffi(impersonate="chrome120", verify=False) # self-signed certs
↓ curl_cffi unavailable at install time
requests (verify=True) # plain fingerprint
↓ SSL error
requests (verify=False) # last resortengine in the response is set to whichever layer actually carried
the request (python-curl_cffi or python-requests).
For tools that talk to third-party OSINT APIs (crt.sh, CertSpotter,
AlienVault, HackerTarget, RapidDNS, Wayback CDX, bgp.he.net,
ip.thc.org), plain requests.get is used directly because those
services rate-limit by IP, not by TLS fingerprint. curl_cffi provides
no benefit there and only adds overhead.
Result: the demo never breaks, whether or not the user installed the tools or curl-cffi.
Ethics / scope
This is a passive + light-active recon toolkit for authorized targets only.
Only scan domains you own or have written permission to test.
nucleiandhttpxproduce real network traffic — target selection is your responsibility.Respect each bug bounty program's scope and rate limits.
The author accepts no liability for misuse.
Credits
Built on:
Model Context Protocol — Anthropic
MCP Python SDK v2 — Anthropic
ProjectDiscovery — subfinder, httpx, dnsx, nuclei
SecLists — subdomain wordlists
crt.sh — Certificate Transparency logs
can-i-take-over-xyz — takeover fingerprints
License
MIT — see LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
MCP server for Pentest-Tools.com: run scans, manage findings and reports via your preffered LLM.
Security scanner for MCP servers. Detect vulnerabilities, prompt injection, and tool poisoning.
Scan any MCP server for tool-poisoning/prompt-injection/exfiltration (OWASP LLM01/08) + Base data
Scans remote MCP servers for protocol, security, and TLS issues; exposes scan tools via MCP.
Related MCP Servers
- AlicenseAqualityBmaintenanceA scope-aware bug-bounty & reconnaissance MCP server that works out of the box on the Python standard library and augments itself with your favourite CLI tools when they're present.22MIT
- AlicenseAqualityBmaintenanceAn MCP server that provides passive and low-impact active reconnaissance tools for authorized bug bounty and security assessments, enabling LLMs to perform structured recon and generate reports.11Apache 2.0
- AlicenseNot gradedqualityDmaintenanceAn MCP server providing 15 OSINT tools over free, public sources for AI agents, enabling domain reconnaissance, subdomain discovery, DNS lookups, host profiling, CVE search, and more without API keys.MIT
- AlicenseAqualityBmaintenanceMCP server that exposes 31 OSINT checks from Lissy93/web-check as tools for website analysis, including SSL, DNS, headers, WHOIS, and security presets. Enables natural-language-driven web recon and health checks.188MIT