An MCP (Model Context Protocol) server that exposes Kali Linux security tools (nmap, gobuster) over stdio. Built with C# on .NET 10 using the official ModelContextProtocol SDK. MCP clients (Claude, etc.) communicate with it via newline-delimited JSON on stdin/stdout.
The recommended way to run the server is inside a Docker container that bundles Kali Linux with all tools and wordlists pre-installed. It can also run directly via the .NET SDK CLI if nmap and gobuster are available on the host.
# Build the image
docker build --no-cache -t kali-mcp-server .
# Run standalone (stdio)
docker run --rm -i --cap-add=NET_ADMIN --cap-add=NET_RAW kali-mcp-server
NET_ADMINandNET_RAWare required so nmap can send raw packets (SYN scans, OS detection).
MCP server config (settings.json):
{
"mcpServers": {
"kali-mcp-server": {
"command": "docker",
"args": ["run", "--rm", "-i", "--cap-add=NET_ADMIN", "--cap-add=NET_RAW", "kali-mcp-server"]
}
}
}dotnet build
dotnet runMCP server config (settings.json):
{
"mcpServers": {
"kali-linux-tools": {
"command": "dotnet",
"args": ["run", "--project", "/home/mm/AgentWithOllama/KaliMCP.csproj"]
}
}
}Run an nmap scan against a target.
Run a gobuster directory scan against a target URL. Supports:
target— URL or IP to scanwordlistPath— path to wordlist inside the container (e.g./usr/share/seclists/Discovery/Web-Content/DirBuster-2007_directory-list-2.3-medium.txt)excludeStatusCodes— comma-separated status codes to blacklist (e.g.301)excludeLength— comma-separated response body lengths to exclude; use when the server wildcard-returns 200 with a fixed size (e.g.8753)resolve— hostname to send as theHostheader for vhost-based targets (e.g.silentium.htb)
Wordlists in the container are at /usr/share/seclists/ (installed via the Kali seclists apt package). Key paths:
/usr/share/seclists/Discovery/Web-Content/DirBuster-2007_directory-list-2.3-medium.txt/usr/share/seclists/Discovery/Web-Content/common.txt/usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt
Lists all .txt wordlist files available in the container across common wordlist directories. Useful for discovering what's installed before running a scan.
The Dockerfile uses a two-stage build:
- Build stage —
mcr.microsoft.com/dotnet/sdk:10.0compiles and publishes the server. - Runtime stage —
kalilinux/kali-rollingwithnmap,gobuster,seclists,wordlists, and the .NET 10 runtime installed via the officialdotnet-install.shscript.
Program.cs sets up the MCP host with .WithToolsFromAssembly() — tools are auto-discovered from the assembly via reflection. All console logs are routed to stderr to keep MCP stdout clean.
- Create a file in
Tools/as astatic classdecorated with[McpServerToolType]. - Add a
static Task<KaliToolResult>method decorated with[McpServerTool]and[Description(...)]. - Use
ProcessRunner.RunAsync(executable, args)to invoke the underlying binary. - No registration needed —
WithToolsFromAssembly()picks it up automatically.
See Tools/Nmap.cs as the canonical example.
KaliToolResult(inTools/Nmap.cs): shared return type for all tools; includesTool,Success,Message,CommandLine,ExitCode,DurationMs,StandardOutput,StandardError.ProcessExecutionResult(Helpers/ProcessRunner.cs): raw result from process execution;SuccessisExitCode == 0.ProcessRunner.RunAsyncusesProcessStartInfo.ArgumentList(not string concatenation) to avoid shell injection.