I work at a cybersecurity startup. You would think that would automatically make me someone who knows their way around a terminal running nmap and thinking in CVEs. It did not, at least not at first. My day to day was more infrastructure and tooling than active security work. But the longer you sit inside a company that thinks about attackers for a living, the more the curiosity seeps in. I started paying attention to the security side of things, reading about how attacks actually work, and a few months ago I picked up CTFs.
This post is about one part of that setup that made everything smoother: getting Kali talking to Claude Code through MCP.
There is a specific kind of frustration that comes from switching between tools mid-thought. You are in Claude Code, reasoning through a problem, and you need to run nmap or check a certificate or do something that requires a Kali tool. So you alt-tab to a terminal, run the command, paste the output back. It works but it breaks the flow completely. The AI loses context. You lose context. It is two separate conversations happening in parallel when they should be one.
I had been doing this for a while before I decided to fix it properly.
The fix is to run Kali inside a VM on your Mac and then connect it to Claude Code as an MCP server. Claude Code can then reach into the VM and run Kali tools directly, read the output, and use it as context for whatever you are working on. No alt-tabbing. No copy-pasting. One continuous thread.
Here is how I set it up.
Why UTM
If you are on a Mac and you want to run a Linux VM, UTM is the answer. It is free, it runs well on both Apple Silicon and Intel, and it does not require you to hand over your email address or install a daemon that runs on startup. Parallels costs money. VMware Fusion used to cost money and is now free but still feels heavy. UTM just works and stays out of your way.
For Apple Silicon specifically, UTM can run ARM64 VMs at near-native speed using the hardware virtualization built into the chip. Kali has official ARM64 images. The combination is fast enough that you sometimes forget it is a VM.
Step 1: Download UTM
Go to mac.getutm.app and download the app. You can also install it from the App Store if you prefer, though the direct download is free and the App Store version costs a few dollars to support development. Either works. I used the direct download.
Move it to your Applications folder and open it.
Step 2: Download the Kali ISO
Go to the Kali Linux downloads page and grab the installer ISO. If you are on Apple Silicon, pick the ARM64 build. On Intel, pick x86_64. The ISO is around 3 to 4 GB.
Once it finishes downloading, open UTM and create a new VM. Click the plus button, choose Virtualize (not Emulate), select Linux, and point it at the ISO you just downloaded. Set memory to at least 4 GB and give it 30 to 40 GB of storage. Leave the rest at defaults for now.
The networking question will come up. Set it to Shared Network. More on why in a moment.
Step 3: First Boot and the Display Problem
Start the VM. There is a good chance the first thing you see is a black screen with something like “no display found” or the display just stays blank. This is a known issue with how UTM handles video output for freshly created Linux VMs.
The fix is to go into the VM settings, scroll down to the Devices section, and enable the Serial device. Save the settings and start the VM again. This time you will get a serial console window that drops you into the installer. From there you can work through the Kali installer like normal — pick your language, set up disk partitioning, create a user.
The installer is text-based through the serial console but it works fine. Go through it, let it finish, and reboot into your new Kali install.
Step 4: Basic Kali Setup
First thing I always do is update the package list and change the default password.
sudo apt update && sudo apt upgrade -y
passwd
Then find out the VM’s IP address. You will need this to configure the MCP connection later.
ip addr show | grep 'inet ' | grep -v '127.0.0.1'
Write down that IP. On UTM’s shared network it usually looks like 192.168.64.x. It tends to stay stable across reboots but you can also set a static IP if you want to be sure.
Step 5: Set Up SSH
The MCP connection from your Mac to Kali happens over SSH, so you want that working cleanly before anything else. Inside the VM, make sure the SSH server is installed and running.
sudo apt install -y openssh-server
sudo systemctl enable --now ssh
Now find the VM’s IP address.
ip addr show | grep 'inet ' | grep -v '127.0.0.1'
On UTM’s shared network it usually looks like 192.168.64.x. Take note of it.
Back on your Mac, add an entry to ~/.ssh/config so you can refer to the VM by a short hostname instead of an IP.
Host kali
HostName 192.168.64.x
User rohan
Replace 192.168.64.x with the actual IP and rohan with whatever username you created during the Kali install. Then copy your SSH key into the VM so you do not get a password prompt every time.
ssh-copy-id kali
Test it.
ssh kali
If you get a shell, the SSH side is done.
Step 6: Install the MCP Server
This is the part I expected to be complicated but turned out to be a single command. Inside the Kali VM, run:
sudo apt install mcp-kali-server
That is it. No Node, no npm, no manual PATH wrangling. The package manager handles everything. The server binary ends up at mcp-server and is ready to use.
Step 7: Connect Claude Code
Back on your Mac, open ~/.claude/settings.json (or the project-level .claude/settings.json if you only want this for specific work) and add the MCP server config.
{
"mcpServers": {
"mcp-kali-server": {
"command": "ssh",
"args": [
"rohan@kali",
"mcp-server"
]
}
}
}
What this does is elegant in its simplicity. When Claude Code needs a Kali tool, it opens an SSH connection to your VM and runs mcp-server on the other end. The MCP protocol runs over stdio through the SSH tunnel. No ports to open, no HTTP endpoints to manage, no tokens. The SSH config entry you set up in Step 5 means rohan@kali resolves cleanly without you having to track the VM’s IP in multiple places.
Restart Claude Code. It will connect to the MCP server on startup and enumerate the available tools. You should see them listed if you ask Claude what tools it has access to.
What It Looks Like in Practice
Once it is connected, the experience is different enough that it took me a few sessions to stop being surprised by it. You can describe a task in plain language and Claude will reach into the VM to gather information, reason about what it finds, and ask follow-up questions or suggest next steps, all in the same conversation.
Something like “scan this host and tell me what’s running” becomes a single prompt. Claude runs the scan, reads the output, identifies the services, and tells you what it thinks is interesting, all without you leaving the terminal. If you want to dig deeper into something it found, you continue the conversation. The context stays intact across every tool call.
It is not magic. Claude is still the same model. But removing the friction of context-switching changes how you actually use it. Problems that would have taken three context switches and four separate commands become one conversation.
A Few Honest Notes
The MCP server runs with whatever permissions your user has in the VM. That is fine for most things but worth knowing if you are running privileged tools like nmap’s SYN scan, which requires root. You can configure specific commands to use sudo without a password for just those binaries rather than running the whole server as root.
The VM’s IP can change across reboots since UTM uses DHCP. When that happens the SSH config entry breaks and Claude Code will silently fail to connect. Setting a static IP on the VM’s interface once is worth the five minutes it takes. Alternatively, if the IP does change, you only have to update it in ~/.ssh/config — the MCP config itself never needs to change because it refers to kali not a raw IP.
Keep the VM’s network on UTM’s shared mode rather than bridged. Bridged mode puts the VM directly on your local network, which is not what you want for a penetration testing environment.
The Actual Lesson
I have been using AI tools for about a year and the biggest productivity gains have not come from the models getting smarter. They have come from reducing the friction between asking a question and getting the right context in front of the model. The more context you can give it without manually assembling that context yourself, the better the output.
The MCP architecture is interesting because it lets you define that context programmatically. Instead of describing what a scan found, you let the model run the scan and read the output directly. Instead of pasting command output into a chat window, the command output is already in the conversation.
This Kali setup is one example. There are others. But the pattern is the same: find the places where you are manually bridging two tools and ask whether the bridge can be automated.
Usually it can. Usually someone already built it. Usually you just did not know it existed.