offsec-mcp
Offensive-security tooling for AI agents — over the Model Context Protocol.
Give Claude, Cursor, or any MCP client the ability to run reconnaissance, pull CVE intelligence, analyze JavaScript, and scan ports — only against targets you're authorized to test.
Why
Pentesters and bug-bounty hunters live in a dozen CLI tools. AI agents are great at orchestrating multi-step work — but they can't touch those tools. offsec-mcp bridges the gap: it exposes a focused set of security capabilities as MCP tools, so you can just ask —
"Enumerate subdomains of
example.com, check which are live, and tell me if any run software with a critical CVE."
— and the agent chains recon_subdomains → http_probe → cve_search for you.
Built on battle-tested logic from reconwave, cve-forge, and jsintel.
Guardrails first
This is a dual-use tool, so authorization is enforced in code, not left to good intentions:
- Passive OSINT (CT logs, DNS, RDAP, NVD, analyzing pasted JS) runs freely — it never touches the target.
- Active tools (
port_scan,http_probe,security_headers) refuse to run unless the target is in your configured authorization scope. No scope → no active probing. - Discovered secrets are redacted in output, never returned in full.
See SECURITY.md for the responsible-use policy.
Tools
| Tool | Type | What it does |
|---|---|---|
recon_subdomains |
passive | Sub-domain enumeration from Certificate Transparency (crt.sh) |
dns_lookup |
passive | A/AAAA/MX/NS/TXT/CNAME via DNS-over-HTTPS |
whois |
passive | Registration data via RDAP (registrar, dates, nameservers) |
cve_search |
passive | Search NVD by keyword, filter by CVSS |
cve_lookup |
passive | Full details + references for a CVE id |
analyze_js |
passive* | Extract secrets, endpoints & params from JS |
http_probe |
active | Status, headers & tech fingerprint of a URL |
security_headers |
active | Audit security headers, grade A–F |
port_scan |
active | Async TCP-connect scan of common/custom ports |
scope_status |
— | Report whether an authorization scope is set |
* analyze_js is passive on pasted content; fetching a URL requires scope.
Install
Run instantly with uv — no clone needed:
uvx offsec-mcp # runs the server (stdio)
Or install from source:
git clone https://github.com/nadirzhon/offsec-mcp
cd offsec-mcp
uv pip install -e ".[dev]"
Configure your MCP client
Claude Desktop / Claude Code
Add to your MCP config (see examples/claude_desktop_config.json):
{
"mcpServers": {
"offsec": {
"command": "uvx",
"args": ["offsec-mcp"],
"env": {
"OFFSEC_SCOPE": "example.com,*.staging.example.com,10.0.0.0/24"
}
}
}
}
Authorization scope
Active tools only run against hosts you list. Two ways to set it:
# inline — domains, wildcards, and CIDRs
export OFFSEC_SCOPE="example.com,*.staging.example.com,10.0.0.0/24"
# or a file, one entry per line (# comments allowed)
export OFFSEC_SCOPE_FILE="./scope.txt"
For a fully-owned lab you control, OFFSEC_ALLOW_ANY=1 disables the guard. NVD_API_KEY
(optional) raises NVD rate limits.
Example session
You: Find subdomains of example.com and check the main site's security headers.
Agent: → recon_subdomains("example.com") → 143 subdomains from CT logs
→ security_headers("https://example.com")
→ Grade C (60): missing CSP, Permissions-Policy.
www, api, staging, dev.example.com are live.
See examples/sample_output.md for real tool output.
Development
uv pip install -e ".[dev]"
pytest # scope guard + tool logic
ruff check .
Part of an AI × Security toolkit
- offsec-mcp — MCP server giving AI agents offensive-security tools (recon, CVE, JS analysis) · (this repo)
- specter — autonomous AI recon agent that drives those tools end-to-end
- vigil — AI security review for every pull request
- mcpscan — security scanner for MCP servers (tool poisoning, injection surfaces)
- State of MCP Security — research: 87% of scanned MCP servers expose a medium+ hardening issue
License
MIT — see LICENSE. Published for authorized security testing, research, and education only. You are responsible for having explicit permission to test any target.
Release files for offsec-mcp 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| offsec_mcp-0.1.0.tar.gz | 14.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| offsec_mcp-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 29.3 kB
Release files / offsec_mcp-0.1.0.tar.gz
| Download URL | offsec_mcp-0.1.0.tar.gz |
|---|---|
| Size | 14.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b6500d6c7c83649547054c822259ad038816bf38af0bbf415a845ccf5f9bc492
|
|
BLAKE2b-256 checksum How to use checksums |
69eae12829ef0e558f1b98d69c5cb30a6fe6557069126c55ba4c8368f4092d71
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.10.3 {"installer":{"name":"uv","version":"0.10.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / offsec_mcp-0.1.0-py3-none-any.whl
| Download URL | offsec_mcp-0.1.0-py3-none-any.whl |
|---|---|
| Size | 15.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
98d720b5a45a09e86767acd7addcc10f0fddfc3b68d6a695c402bd5ded6081c5
|
|
BLAKE2b-256 checksum How to use checksums |
7c3c2debd2277bd41a498b6d1b412812e92cb6f672818d4c01b1305817ff5be1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.10.3 {"installer":{"name":"uv","version":"0.10.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|