The Model Context Protocol (MCP) turned the phrase "control Kali with AI" from a demo trick into a repeatable, auditable workflow. Instead of copy-pasting commands into a chat window, you register your security tools as MCP servers, and Claude Code calls them as structured, permission-gated functions — with the output flowing straight back into the agent's reasoning.
This guide covers three install paths (native on Kali, Docker, and WSL2), the exact configuration files and commands, how to build your own Python MCP server that wraps a scanner, and — critically — how to lock the whole thing down so the agent can only touch assets you have authorised. Everything here assumes lab or authorised engagement use only.
◈ Table of Contents
01 · What MCP-Driven Kali Control Actually Is
why it mattersThe Model Context Protocol is an open standard for connecting AI assistants to external tools and data through a uniform client/server interface. Claude Code — Anthropic's command-line coding and automation agent — acts as the MCP client. Each tool you expose (a port scanner, a fuzzer, a notes database) runs as an MCP server. When you ask the agent to "enumerate the web ports on the lab host", it does not guess a shell string; it selects a declared tool, fills in typed parameters, and the server returns structured output the model can reason over.
For a security practitioner, that distinction is the whole point. A raw "let the AI run bash" setup is fast but opaque and dangerous. An MCP setup gives you a typed contract per tool, per-tool permission prompts, an audit trail of exactly which tool ran with which arguments, and the ability to keep credentials and scope enforcement on the server side where the model can never see or bypass them.
MCP servers reach the client over one of three transports, and the one you pick shapes the rest of your setup. STDIO is the default and simplest: the client launches the server as a child process and they talk over standard input and output. It is perfect for a server that lives on the same host as Claude Code, which covers the native and Docker paths in this guide. SSE (server-sent events) and streamable HTTP are network transports — you register the server by URL instead of by launch command, which is what you want when the tools run on a separate box or you need multiple clients to share one server. Most single-analyst labs never need anything beyond STDIO; reach for the HTTP transports only when the topology demands it.
| Transport | How you register it | Best for |
|---|---|---|
| STDIO | claude mcp add name -- cmd | Server on the same host (native, Docker) — the default |
| SSE | --transport sse name url | Remote server, streaming, shared by clients |
| HTTP | --transport http name url | Remote server behind a normal HTTP endpoint |
It helps to be precise about what "the AI controls Kali" means here, because the phrase invites the wrong mental model. The model never gets a shell. It emits a request to call a named tool with named arguments; the server decides whether that request is legal, runs the underlying binary if so, and returns the result. Every decision that actually matters — what a tool can do, which targets it will accept, what happens to the output — is code you write and control, not behaviour the model improvises. That is why this approach is safe enough to recommend for authorised testing while "pipe the model into bash" is not.
Guided Recon
Describe a scope in plain English; the agent runs discovery in the right order and summarises live hosts, open ports and service banners.
Report Drafting
Tool output feeds straight into the model, so a first-pass findings write-up is generated alongside the raw evidence.
Tool Orchestration
Chain nmap → nuclei → ffuf with the model deciding follow-ups, while every call stays typed and logged.
Learning Aid
Ask why a flag was chosen or what a banner implies — the agent explains as it works, useful for OSCP-style practice labs.
AUTHORISATION IS NON-NEGOTIABLE. Running scanners against systems you do not own or lack written permission to test is illegal in most jurisdictions. Restrict every setup in this guide to your own lab (Metasploitable, DVWA, a VulnHub box) or an engagement with a signed scope.
02 · Prerequisites & Requirements
before you startYou need a working Kali install, a modern Node.js runtime for Claude Code, Python 3.11+ for the custom server later, and either a Claude subscription (Pro or Max, which entitle Claude Code use) or an Anthropic API key. The table below is the baseline for a comfortable lab.
A quick word on the auth choice, because it trips people up. A Pro or Max subscription lets you use Claude Code through an interactive browser login and is the right call for hands-on lab work — you get a flat monthly cost and no token accounting to think about. An API key, set through the ANTHROPIC_API_KEY environment variable, is metered per token and suits automation or CI-style runs where no human is present to click a login prompt. You do not need both; pick the one that matches how you will actually drive the agent. Either way the default model is Opus 4.8, and you do not have to configure it explicitly.
| Component | Requirement | Notes |
|---|---|---|
| OS | Kali Linux 2026.x (rolling) | Bare metal, VM, or WSL2 all work |
| CPU / RAM | 2 vCPU / 4 GB MIN 4 vCPU / 8 GB REC | Scanners are the heavy part, not the agent |
| Disk | 25 GB free | Kali tools + Node + Docker images |
| Node.js | 18 LTS or newer (20/22 preferred) | Required by Claude Code |
| Python | 3.11+ | For the custom MCP server in Phase 9 |
| Auth | Claude Pro/Max or Anthropic API key | API key set via ANTHROPIC_API_KEY |
| Network | Isolated lab segment | Keep targets off production VLANs |
Know exactly what you are on before layering software over it — version drift is a common source of package conflicts.
A stale rolling release causes dependency conflicts the moment you add Node or Docker. Bring the box current first.
PRO TIP: Snapshot the VM (or the WSL2 distro export) before installing anything. If an agent-run command misbehaves in your lab, a two-minute rollback beats an afternoon of cleanup.
03 · Method 1 — Native Install on Kali
recommended for labsThe native path runs Claude Code directly on Kali so the agent shares the same filesystem and tool binaries. This is the simplest setup and the one most people want. Before you commit, the table below compares the three install methods so you can pick by your constraints rather than by habit.
| Method | Isolation | Setup effort | Pick it when |
|---|---|---|---|
| Native (Phase 3) | Low | Lowest | Dedicated Kali lab VM you can snapshot |
| Docker (Phase 4) | High | Medium | You want disposable, reproducible tool sandboxes |
| WSL2 / remote (Phase 5) | Medium | Medium | Windows workstation, or Kali on a separate box |
Kali's default Node can lag behind. Use nvm so you control the version without fighting apt.
Install the CLI globally, then confirm it resolves on your PATH.
Do NOT run npm install -g with sudo. A root-owned global npm prefix is the #1 cause of "permission denied" errors on later updates. If you skipped nvm, set a user-writable prefix with npm config set prefix ~/.npm-global and add it to PATH.
Launch Claude Code in your working directory and log in. Subscription users authenticate in the browser; API users export a key instead.
Add a server with claude mcp add. Everything after the -- is the command that launches the server. Here we add the reference filesystem server as a smoke test before wiring in security tools.
- claude mcp list shows the server with a "connected" status
- Running /mcp inside a session lists the server and its tools
- No red "failed to connect" line in the startup banner
PRO TIP: Use --scope project when you want the server config committed to a repo (it writes .mcp.json), --scope user for servers you want in every project, and the default local for one-off experiments that stay private to the current directory.
04 · Method 2 — Docker Deployment
isolation + repeatabilityContainerising the security tooling gives you a disposable, reproducible sandbox: the agent talks to a Kali-tools container over MCP, and if a scan wedges the box you just recreate it. The pattern below keeps Claude Code on the host and runs the MCP server plus tools inside the container.
Base off the official Kali rolling image, add the scanners you want the agent to reach, and install the Python MCP SDK. Save this as Dockerfile.
The kali_mcp_server.py file referenced here is the one you build in Phase 9. Keep it in the same directory as the Dockerfile.
A minimal docker-compose.yml. The container joins a dedicated lab network and mounts a shared output directory so results land on the host.
Register an MCP server whose launch command runs the container over STDIO. Claude Code starts the container on demand and speaks MCP through it.
cap_drop: ALL then re-adding only NET_RAW/NET_ADMIN is deliberate. Never run the tools container with --privileged — it hands the agent a path to the host kernel. If a tool complains it needs more, add the single capability it names, not the blanket flag.
05 · Method 3 — WSL2 / VM Setup
windows & remoteMany analysts drive Kali from a Windows workstation via WSL2, or keep Kali on a remote VM and connect over SSH. Both work; the only wrinkle is where Claude Code runs and how it reaches the tools.
Install the Kali distro under WSL2, then treat the WSL shell exactly like the native path in Phase 3 — Node, Claude Code and MCP servers all run inside the Linux userland.
Raw-socket scans (nmap -sS) can behave oddly under WSL2's virtualised network stack. If SYN scans hang, fall back to a TCP connect scan (-sT) or run the tools in a proper Kali VM for anything network-timing sensitive.
Keep Claude Code on your laptop but run the MCP server on a remote Kali box. Wrap the launch command in SSH so the server process lives on the VM.
PRO TIP: Use an SSH key with a dedicated, low-privilege account on the VM and lock that key to the single command with command= in authorized_keys. The agent then cannot use the SSH channel for anything except launching the MCP server.
A third remote option is a network transport instead of STDIO. If your server speaks HTTP or SSE, register it by URL rather than by command:
06 · Initial Configuration & First Run
first launchWith at least one MCP server registered, start a session and confirm the agent can see the tools. The /mcp slash command is your health check inside Claude Code.
Start a session in the engagement directory, then use the built-in slash commands to confirm servers and auth are healthy.
Config is layered, and understanding the layers saves hours of confusion later. Server registrations resolve from three scopes in order of increasing reach: local (private to the current directory), project (written to .mcp.json, meant to be committed), and user (available in every project). When the same name exists in more than one scope, the narrower scope wins. Behaviour and permissions are separate and live in settings.json under .claude/. Keep servers in one file and permissions in another.
Keep the core claude mcp subcommands handy — these five cover almost everything you do with servers.
| Command | What it does |
|---|---|
| claude mcp add | Register a server (append --transport and --scope as needed) |
| claude mcp list | Show every registered server and its connection status |
| claude mcp get <name> | Print one server's launch command and config |
| claude mcp remove <name> | Unregister a server you no longer trust or need |
| /mcp (in session) | List connected servers and the tools they expose |
If you prefer editing the file by hand to running claude mcp add, this is the shape a project-scoped registration takes.
PRO TIP: Commit .mcp.json to your engagement repo but keep secrets out of it. Reference environment variables (for example an API token the server needs) rather than hardcoding values, so the file is safe to share with teammates.
07 · Core Configuration — Wiring Tools Through MCP
the settings that matterThis is the phase that separates a toy from a controlled setup. The two levers that matter most are permissions (which tools run without asking) and scope (what the tools are allowed to touch). Get these right before you let the agent loose.
| Permission tier | Behaviour | Use for |
|---|---|---|
| allow | Runs with no prompt | Read-only, non-network tools (banner grab, local parse) |
| ask | Prompts every time | Anything that touches the network (scanners, fuzzers) |
| deny | Blocked outright | Destructive or exfil-shaped commands (rm, curl) |
By default Claude Code prompts before running an MCP tool. You can pre-approve specific tools in settings.json to reduce friction — but only the read-only, safe ones. Keep anything that touches the network on a manual prompt at first.
MCP tool permission keys follow the pattern mcp__<server>__<tool>. Naming the exact tool is far safer than a broad wildcard.
Never trust the model to "remember the scope". Enforce the allowed target range inside the MCP server so an out-of-scope argument is rejected before any binary runs. You will implement exactly this check in Phase 9.
The single most important control in this whole guide: the server must validate every target against an allowlist and refuse anything outside it. A prompt-side instruction ("only scan 10.10.0.0/24") is a suggestion; a server-side check is a boundary.
Drop a CLAUDE.md in the engagement directory. Claude Code reads it automatically at session start — use it to record the authorised scope, the rules of engagement and preferred tools, so you are not re-typing them each session.
PRO TIP: Fast mode (toggle with /fast) runs the same Opus 4.8 model with faster output — handy during interactive recon when you want quick tool-call turnaround without downgrading the model.
08 · Integration — Workflow, Scoping & Reporting
day-to-day useOnce tools are wired and permissioned, the workflow becomes conversational. You describe intent; the agent selects tools, runs them within the server-enforced scope, and writes structured output you can review and turn into a report.
State the goal in plain language and gate each network action. The agent selects tools; the server keeps them in scope.
Scope-first prompts
Reference the range in CLAUDE.md; the server rejects anything outside it regardless of prompt wording.
Evidence to loot/
Have every tool write raw output to a mounted directory so findings are backed by artefacts, not just chat text.
Draft findings
Ask the agent to produce a findings table from the collected output — a first draft you then verify by hand.
Chained follow-ups
Let the model propose the next tool (ports → templates → content discovery) while you gate each network action.
The workflow that scales best is a tight loop: state intent, review the proposed tool call, approve or refuse, read the structured result, and let the agent suggest the next step. Because the model sees the tool output in its own context, it can spot a follow-up you might miss — an open management port that warrants a template scan, a redirect that hints at a virtual host worth fuzzing. Your job shifts from typing commands to gating decisions and sanity-checking conclusions, which is exactly where a human adds the most value on an engagement.
Pull the tool-call history and archive it with the loot. Because every MCP call is structured, you can tie a finding back to the exact command and arguments that produced it — the auditability that raw-bash AI setups lack.
Treat AI-drafted findings as a first pass, never a final report. The agent can misread a banner or over-state severity. Every finding needs human verification before it reaches a client deliverable.
09 · Advanced — Build a Custom Kali MCP Server
power usersThe real leverage comes from your own MCP server that exposes exactly the tools you want, with scope validation baked in. The official Python SDK (mcp[cli], which bundles FastMCP) makes this short. Below is a complete, minimal server that wraps nmap and enforces an allowlist.
Work in a virtualenv so the SDK stays isolated from Kali's system Python.
Save this as kali_mcp_server.py. It declares one tool, validates every target against an allowlist, and never touches a shell.
Two design choices carry most of the safety. First, the scope allowlist is a module-level constant the model cannot reach or rewrite — a target outside 10.10.0.0/24 is refused before nmap is invoked. Second, the command is assembled as a list and handed to subprocess.run with no shell, so a crafted target string cannot break out into arbitrary command execution. Extending the server means adding more @mcp.tool() functions of the same shape: validate inputs, build an argument list, cap the runtime, return the output.
Register the server exactly like any other, then confirm the tool appears inside a session.
Run through this checklist for every tool you add. A server is only as safe as its least-checked tool.
- Every tool validates its target against the ALLOWED allowlist first
- Arguments are passed as a list (no shell string interpolation)
- A timeout caps every subprocess so a hung scan can't wedge the server
- The tool docstring describes intent so the model calls it correctly
- Sensitive tools stay on the permission "ask" list, never "allow"
Build commands as argument lists (["nmap", "-sT", ...]), never with shell=True and string concatenation. Passing model-supplied text into a shell is a command-injection sink — the exact class of bug you are paid to find in other people's code.
PRO TIP: Add one tool at a time and test each before exposing the next. A server that quietly exposes ten tools is ten times harder to reason about when the agent picks the wrong one.
10 · Monitoring, Maintenance & Troubleshooting
keep it runningMCP failures are almost always one of a handful of things: a server that won't launch, a transport mismatch, a permission wall, or a stale binary. Start with the built-in diagnostics, then work the table.
First stop for any "tool not available" problem — confirm the server is registered, see its exact launch command, then get verbose startup output.
If the diagnostics say a server failed to connect, run its launch command directly. A broken import or syntax error surfaces here in plain text instead of being swallowed by the client.
| Symptom | Likely cause | Fix |
|---|---|---|
| Server shows "failed to connect" | Launch command wrong or binary missing | Run the command from mcp get manually; fix the path or install the missing dependency |
| Tools never appear in /mcp | Server started but registered no tools | Check the @mcp.tool() decorators and that mcp.run() is reached |
| "permission denied" on npm -g | Root-owned global prefix | Reinstall via nvm, or set a user-writable npm prefix — never sudo |
| Docker server hangs at start | Missing -T / no STDIO | Add -T to docker compose run and stdin_open: true in compose |
| nmap SYN scan fails | No raw-socket capability | Add NET_RAW in compose, or use -sT connect scan (esp. under WSL2) |
| Agent scans out of scope | Scope only in the prompt | Enforce the allowlist in the server code (Phase 9), not in prose |
| Tool runs but returns nothing | Timeout too short or wrong stream | Return stderr as a fallback; raise the subprocess timeout |
Keep three things current: Claude Code, the Kali tool packages, and the Python SDK. A monthly cadence avoids most "it worked last week" surprises. Prune servers you no longer use in the same pass.
Review your MCP server list periodically. Every registered server is code the agent can invoke — a forgotten experimental server is attack surface. If you did not write it or vet it, remove it.
PRO TIP: Log the agent's tool calls into the engagement folder and diff them against your rules of engagement at the end of each day. It is the cheapest way to catch a mis-scoped action before it becomes a finding against you.
11 · Sources & References
go deeperPrimary documentation for the tools and protocols used in this guide:
Building an AI-assisted testing lab?
Pair this setup with our other hands-on guides — the CyberHawk blog covers Nmap, BloodHound and privilege escalation end to end, and our Live Tools and Courses take you from lab to engagement. Keep every scan inside an authorised scope.
◈ Stay Connected
Follow CyberHawk Threat Intel for threat intelligence, deployment guides and hands-on SOC tooling content.
"They can't exploit you if you are the Exploit."