Kali MCP
Enables authorized security testing by letting LLM clients run Kali Linux tools inside an isolated Docker container.
README
Kali MCP
An MCP server that lets Claude (Desktop, Code) and other local-LLM clients drive a full Kali Linux toolset for authorized security testing and analysis.
The model doesn't run tools on your Windows host — it runs them inside an
isolated Kali Docker container. The MCP server is a thin Python layer that
docker execs into that container, captures output, and manages long-running
scans as background jobs.
Claude / local LLM ──MCP──► kali_mcp.server (Python) ──docker exec──► kali_mcp container
(stdio or HTTP) (kali-linux-headless)
/workspace (isolated volume)
Sandboxing
The container is confined so nothing it runs can touch the Windows host, while still reaching the internet and its targets:
- No host filesystem access. Output lives in a Docker-managed named volume
(
kali_mcp_kali_workspace), not a host bind mount. Retrieve results with thekali_read_filetool ordocker cp kali_mcp:/workspace ./workspace. - Not privileged, no host namespaces, no docker socket — the escape vectors that would give a container access to the host are simply absent.
- Minimal capabilities — only
NET_RAW/NET_ADMIN(needed by nmap and friends), which act solely on the container's own isolated network stack. - Resource caps — 6 GB RAM, 4 CPUs, 4096 PIDs, so a runaway scan can't starve the host.
- Dedicated bridge network — isolated from other containers, NAT'd to the internet.
To pull all results out to Windows at once:
docker cp kali_mcp:/workspace ".\workspace"
Optional: VPN egress (route scans through a VPS)
By design, a container reaches the internet by NAT through the host's network stack — so scan traffic transits your machine, where host AV/IPS can see and interfere with it. This is networking, not a container-isolation gap, and no amount of container hardening changes it. The fix is to control egress.
docker-compose.vpn.yml runs the Kali container through a WireGuard tunnel
(gluetun sidecar) to an egress you control:
- Scan traffic exits from your VPS IP, not your workstation.
- Your host AV sees only encrypted UDP — no scan signatures to flag.
- Kill-switch: if the tunnel drops, the container has no route out (fail closed) and can't reach your LAN or host. This is the meaningful network isolation upgrade.
cp .env.example .env # fill in your WireGuard/VPS details (never commit .env)
docker compose down # stop the plain stack first
docker compose -f docker-compose.vpn.yml up -d
docker exec kali_mcp curl -s ifconfig.me # should print your VPS IP
Run active scans this way; keep your workstation out of the traffic path.
Egress provider: .env supports two modes. VPN_SERVICE_PROVIDER=custom
points the tunnel at your own VPS (recommended for active scanning — you own
a whitelistable IP and stay within provider terms). VPN_SERVICE_PROVIDER=protonvpn
uses a ProtonVPN WireGuard config (from Proton → Downloads → WireGuard) with
no VPS needed — but ProtonVPN's terms prohibit port scanning, so use it for
passive / OSINT egress only, not active scans.
Pivoting into internal networks
VPN egress controls outbound traffic. To reach a network segment only
accessible through a foothold (an in-scope jump box), route tools through it.
Both approaches use tools already in the image, driven via kali_run:
- proxychains (TCP-only). With a SOCKS proxy on the foothold
(
ssh -D 1080 user@pivot, or chisel / Meterpretersocks), prefix commands:proxychains4 -q curl http://10.10.0.5. It hooks TCPconnect()only, so usenmap -sT -Pn -n— no SYN, UDP, or OS detection through the chain, and non-TCP traffic is not proxied. - ligolo-ng / sshuttle (tun-based, preferred for scanning). These create a
real network interface, so full nmap (
-sS, UDP, OS detection) works through the pivot without proxychains' TCP-only limitation.
Keep the WireGuard tunnel for outbound egress; use pivoting only to reach internal networks via an authorized foothold.
What's inside the container
The image installs the full kali-linux-headless metapackage — hundreds of
tools (nmap, masscan, nikto, gobuster, ffuf, sqlmap, nuclei, hydra, whatweb,
dnsrecon, wpscan, searchsploit, metasploit, and many more) — plus SecLists and
common utilities. First build is several GB and can take a while.
Prerequisites
- Docker Desktop (running) — already set up on this machine
- Python 3.11+ (3.14 present) with the
mcpandpydanticpackages
Setup
From this directory (C:\path\to\kali_mcp):
.\setup.ps1
That builds the image, starts the kali_mcp container, creates a .venv, and
installs the Python deps. To do it by hand:
docker compose up -d --build # build image + start container
py -m venv .venv # dedicated virtual environment
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
Why a venv (not
pip install --user)? MCP clients such as LM Studio and Claude Desktop launch the server with a stripped-down environment that omits%APPDATA%, so user-site packages become invisible and you getModuleNotFoundError: No module named 'pydantic'. The venv's packages are found via its own prefix regardless of environment, which fixes this for every client. All client configs must point at.venv\Scripts\python.exe.
The container stays up (restart: unless-stopped). Scan reports are written to
the isolated /workspace volume — read them back with the kali_read_file
tool or copy them out with docker cp kali_mcp:/workspace ./workspace (see
Sandboxing above).
Connecting a client
Claude Desktop (stdio)
Merge the kali block from claude_desktop_config.example.json
into %APPDATA%\Claude\claude_desktop_config.json, then
restart Claude Desktop. It launches the server itself over stdio.
Claude Code (stdio)
This repo already contains a project-scoped .mcp.json. Open Claude
Code in this folder and it offers to enable the kali server. Or register it
globally:
claude mcp add kali -e PYTHONPATH=C:\path\to\kali_mcp -- "C:\path\to\kali_mcp\.venv\Scripts\python.exe" -m kali_mcp.server
Other local LLM clients (HTTP)
Start the server in HTTP mode:
.\.venv\Scripts\python.exe -m kali_mcp.server --http --host 127.0.0.1 --port 8765
It serves the streamable HTTP MCP transport at http://127.0.0.1:8765/mcp.
Point any MCP-capable client (LM Studio, Open WebUI with an MCP bridge, custom
clients, etc.) at that URL.
Tools
| Tool | Purpose |
|---|---|
kali_run |
Run any command in the container and wait for the result. The main workhorse. |
kali_run_background |
Launch a long scan detached; returns a job_id. |
kali_job_status |
Check / tail a background job by id. |
kali_stop_job |
Kill a background job. |
kali_list_jobs |
List this session's background jobs. |
kali_nmap |
nmap wrapper that also saves XML to /workspace. |
kali_recon |
Workflow: nmap service scan → whatweb fingerprint → optional nikto/gobuster (run_web_scan) and nuclei (run_nuclei). Saves all artifacts for reporting. |
kali_engagement_set |
Set engagement metadata: client, assessor, dates, scope, rules of engagement. |
kali_engagement_get |
Show current engagement metadata. |
kali_add_finding |
Record an analyst-authored finding (severity, CVSS, affected assets, description, impact, remediation, references, evidence). CVSS score auto-computed from the vector if omitted. |
kali_list_findings |
List manual findings. |
kali_remove_finding |
Delete a manual finding by ID. |
kali_report |
Consulting report: merges engagement metadata + manual findings + every nmap/nuclei/nikto/whatweb/gobuster/ffuf artifact + the audit log into Markdown, styled HTML, and (with pdf: true) a print-optimized PDF. Automated findings are deduplicated across hosts. Supports min_severity filtering and a PASS/FAIL gate. |
kali_export_findings |
Export consolidated findings to CSV and/or JSON for import into ticketing/GRC tools. |
kali_list_results |
List result files (scans, reports, loot) in the workspace. |
kali_update |
Refresh nuclei templates and the searchsploit DB. |
kali_cleanup |
End-of-engagement wipe of /workspace (scans, reports, engagement, findings, audit log). Requires confirm: true; otherwise a dry-run preview. |
kali_which |
Search installed tools by name. |
kali_read_file |
Read a file (e.g. a scan report) out of the container. |
kali_write_file |
Write a target list / wordlist / notes into the container. |
kali_status |
Container state, Kali version, tool count. |
Reporting workflow
Every command is logged to /workspace/audit.log (JSON lines: timestamp,
command, exit code, duration) — disable with KALI_MCP_AUDIT=0. Read-only
helpers (kali_read_file, kali_status, kali_which, kali_list_results)
are not logged, so the log reflects actual testing activity.
A consulting engagement flow:
-
Define the engagement —
kali_engagement_setwith client, assessor, dates, scope, and rules of engagement. This drives the report cover page and scope section. -
kali_update— refresh feeds (once per engagement). -
Test —
kali_recon <host>for each target (addrun_web_scan: truefor nikto+gobuster,run_nuclei: truefor a vuln pass), and/or drive any tool directly withkali_run. -
Record findings —
kali_add_findingfor each analyst-identified issue (severity, CVSS, affected assets, impact, remediation, evidence, references). These are the heart of the report. -
kali_report— assembles a professional report:- cover page (client, assessor, dates, classification banner)
- executive summary with overall risk rating and metrics
- optional severity gate —
gate: highadds a PASS/FAIL verdict (FAIL if any finding is at/above the threshold) - scope & rules of engagement
- findings ranked by severity — manual findings (full CVSS/impact/remediation) plus automated findings from nuclei/nikto;
min_severityfilters out low/info noise - per-host details — ports, service versions, OS guess, web technologies, content discovery (gobuster/ffuf)
- methodology / command log (from the audit trail)
- artifact appendix
Saved to
/workspace/report/report-<timestamp>.{md,html}. Pull it withdocker cp kali_mcp:/workspace/report .and open the HTML in a browser.
The report engine also picks up artifacts from raw kali_run scans as long as
they land in /workspace — nmap -oX *.xml, nuclei -jsonl, nikto
-Format json, whatweb --log-json, gobuster -o, and ffuf -of json
outputs are all parsed automatically. Engagement data (metadata + manual
findings) persists in /workspace/engagement/engagement.json.
Findings hygiene, built in:
- CVSS auto-rating — supply a
cvss_vector(CVSS v3.0/3.1) tokali_add_findingand the base score is computed for you (e.g.AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H→ 9.8). - Deduplication — the same automated check firing across many hosts (e.g. a nuclei template on 20 servers) collapses into one finding listing all affected assets, with an instance count.
- Export —
kali_export_findingswrites flat CSV/JSON of the consolidated, deduplicated findings for import elsewhere.
Example prompts
- "Run a service-version nmap scan against
scanme.nmap.organd summarize the open ports." - "Full-port-scan
192.168.1.0/24in the background, then check the job in a minute." - "Fuzz
https://target.exampledirectories with ffuf and the common wordlist." - "What SQL-related tools are installed?" (uses
kali_which)
Configuration
Environment variables (optional):
| Variable | Default | Meaning |
|---|---|---|
KALI_MCP_CONTAINER |
kali_mcp |
Container name to exec into. |
KALI_MCP_DOCKER |
docker |
Docker CLI path. |
KALI_MCP_COMPOSE_DIR |
project root | Where the compose file lives. |
KALI_MCP_MAX_OUTPUT |
60000 |
Max output chars returned per call. |
Scope and responsible use
This server runs real offensive tooling with no built-in target restrictions —
by design. Only test systems you own or are explicitly authorized to assess.
You are responsible for staying within the scope of your engagement and
applicable law. Scan outputs live in the isolated kali_mcp_kali_workspace
volume; treat them as sensitive. If you later want a target allowlist or
command audit log, the executor.py layer is the single place to add it.
Troubleshooting
- "Container is not present and could not be created" — run
docker compose up -d --buildin this folder and checkdocker ps. - Server won't start in a client — confirm the Python path in the config matches
py -c "import sys; print(sys.executable)", and thatPYTHONPATHpoints at this folder. - Raw-socket scans fail — the container is granted
NET_ADMIN/NET_RAWindocker-compose.yml; make sure you started it via compose, not a baredocker run. - Rebuild after editing the Dockerfile —
docker compose up -d --build.
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.