nmap MCP SKILL for openclaw
nmap-mcp
An nmap MCP server for AI-assisted network security auditing.
A Model Context Protocol server that wraps nmap with 14 purpose-built tools, returning structured JSON output instead of raw text — so your AI agent can actually reason about what it finds.
Built for use with OpenClaw and compatible with any MCP client.
Why this one?
Most nmap MCP servers dump raw nmap text back at the model. This one parses everything into structured JSON, so you get machine-readable port lists, service versions, OS matches, and script output — not walls of text to squint at.
It also ships with things you actually need for responsible security tooling:
- Scope enforcement — CIDR allowlist, configured in
config.yaml. Targets outside your allowed ranges are rejected before nmap runs and logged. No accidental scans of the public internet. - Audit logging — every tool call is logged as a JSON line: timestamp, tool, target, args, success/fail.
- Scan persistence — every result is saved to disk with a
scan_id. Retrieve any past scan cross-session withnmap_get_scan. - Injection guard —
nmap_custom_scanstrips shell metacharacters before they touch a subprocess. - Privilege-aware — SYN, OS, and ARP scans need raw socket access. The README tells you the one command to set it up cleanly (
setcap), no full root required.
Requirements
- OpenClaw — the MCP-native AI agent runtime this is built for
- mcporter — MCP server manager (
npm install -g mcporter); not bundled with OpenClaw, needs separate install - Python 3.10+
- nmap 7.0+ installed and in PATH
fastmcp,python-nmap,pyyaml(seerequirements.txt)
Installation
Option A — ClawHub (recommended)
The easiest way if you're already using OpenClaw:
# Install the ClawHub CLI if you haven't already
npm i -g clawhub
# Install the skill
clawhub install nmap-mcp
Files land in ~/.openclaw/workspace/skills/nmap-mcp/. Then follow the Post-install setup steps below.
Option B — GitHub
git clone https://github.com/sbmilburn/nmap-mcp.git
cd nmap-mcp
Then follow the Post-install setup steps below.
Post-install setup
1. Install Python dependencies
pip install -r requirements.txt
2. Grant nmap raw socket capability
Required for SYN scans, OS detection, and ARP discovery. Only needs to be done once (redo after nmap upgrades):
sudo setcap cap_net_raw+ep $(which nmap)
# Verify
getcap $(which nmap)
# /usr/bin/nmap cap_net_raw=ep
Why
setcapinstead ofsudo? It gives nmap exactly the capability it needs (raw sockets) without running the whole process as root. Cleaner and less risky than a sudoers rule.
3. Configure scope
Edit config.yaml and set your allowed CIDRs before running:
allowed_cidrs:
- "127.0.0.0/8" # loopback (always useful for testing)
- "192.168.1.0/24" # your local network
- "10.0.0.0/8" # internal RFC1918 — trim to your actual range
audit_log: "./audit.log"
scan_dir: "./scans"
nmap_bin: "/usr/bin/nmap"
timeouts:
quick: 120
standard: 300
deep: 600
Register with mcporter (OpenClaw)
1. Install mcporter (if you haven't already)
mcporter is a separate package — not bundled with OpenClaw:
npm install -g mcporter
Verify: mcporter list should run without errors.
2. Add nmap-mcp to mcporter's config
Edit (or create) ~/.mcporter/mcporter.json:
{
"mcpServers": {
"nmap": {
"command": "python3",
"args": ["-u", "/path/to/nmap-mcp/server.py"],
"type": "stdio",
"env": {
"NMAP_CONFIG": "/path/to/nmap-mcp/config.yaml"
}
}
}
}
Replace /path/to/nmap-mcp/ with the actual path to the skill:
- ClawHub install:
~/.openclaw/workspace/skills/nmap-mcp/ - GitHub clone: wherever you ran
git clone
If mcporter.json already exists with other servers, add just the "nmap": { ... } block inside "mcpServers" — don't replace the whole file.
3. Restart OpenClaw
OpenClaw reads mcporter.json at startup. After restarting, verify the tools loaded:
npx mcporter list nmap
You should see all 14 tools listed. If you see an error, check that python3 is in your PATH and that fastmcp is installed (pip install fastmcp).
Tools
Host Discovery
| Tool | Description | Needs cap_net_raw |
|------|-------------|:-----------------:|
| nmap_ping_scan(target) | ICMP + TCP ping sweep, no port scan | No |
| nmap_arp_discovery(target) | ARP discovery — most reliable on LAN, returns MAC+vendor | Yes |
Port Scanning
| Tool | Description | Needs cap_net_raw |
|------|-------------|:-----------------:|
| nmap_top_ports(target, count=100) | Fast TCP connect scan of N most common ports | No |
| nmap_syn_scan(target, ports="1-1024") | SYN half-open scan — faster and stealthier | Yes |
| nmap_tcp_scan(target, ports="1-1024") | Full TCP connect scan — no special privileges | No |
| nmap_udp_scan(target, ports="...") | UDP scan — finds SNMP, DNS, NTP, TFTP, etc. | Yes |
Service & OS Detection
| Tool | Description | Needs cap_net_raw |
|------|-------------|:-----------------:|
| nmap_service_detection(target, ports, intensity=7) | Service name, product, version, CPE | No |
| nmap_os_detection(target) | OS fingerprinting with accuracy % | Yes |
NSE Scripts
| Tool | Description | Needs cap_net_raw |
|------|-------------|:-----------------:|
| nmap_script_scan(target, scripts, ports) | Run named NSE scripts, e.g. ssl-cert,http-title | No |
| nmap_vuln_scan(target, ports) | Full vuln NSE category — checks CVEs + misconfigs | No |
All-in-One & Utilities
| Tool | Description | Needs cap_net_raw |
|------|-------------|:-----------------:|
| nmap_full_recon(target, ports) | SYN + service + OS + default scripts combined | Yes |
| nmap_custom_scan(target, flags) | Arbitrary flags, still scope-checked and logged | Varies |
| nmap_list_scans(limit=20) | List recent saved scans | No |
| nmap_get_scan(scan_id) | Retrieve full result of any past scan | No |
Usage with OpenClaw
Just ask naturally — OpenClaw picks the right tool and runs it:
"Scan 10.35.251.0/24 for open ports"
"Run a full recon on 10.35.251.10"
"What services are running on 10.35.251.50?"
"Check 10.35.251.25 for known vulnerabilities"
"Do an ARP sweep of the 10.35.251.0/24 network and tell me what's alive"
The agent picks the appropriate tool, runs it, and gets back structured JSON it can actually reason about — not a wall of text to parse.
Example Output
Network sweep — find live hosts and open ports across a subnet
Prompt: "Do a fast port scan of 10.35.251.0/24"
{
"scan_id": "20260304_120000_a1b2c3",
"target": "10.35.251.0/24",
"top_ports_scanned": 100,
"total_open": 11,
"per_host": {
"10.35.251.1": {
"hostname": "gateway.local",
"state": "up",
"open_ports": [
{"port": 53, "protocol": "tcp", "state": "open", "service": "domain", "version": ""},
{"port": 80, "protocol": "tcp", "state": "open", "service": "http", "version": ""},
{"port": 443, "protocol": "tcp", "state": "open", "service": "https", "version": ""}
]
},
"10.35.251.20": {
"hostname": "",
"state": "up",
"open_ports": [
{"port": 22, "protocol": "tcp", "state": "open", "service": "ssh", "version": ""},
{"port": 80, "protocol": "tcp", "state": "open", "service": "http", "version": ""},
{"port": 443, "protocol": "tcp", "state": "open", "service": "https", "version": ""}
]
},
"10.35.251.55": {
"hostname": "",
"state": "up",
"open_ports": [
{"port": 80, "protocol": "tcp", "state": "open", "service": "http", "version": ""},
{"port": 631, "protocol": "tcp", "state": "open", "service": "ipp", "version": ""},
{"port": 9100, "protocol": "tcp", "state": "open", "service": "jetdirect", "version": ""}
]
},
"10.35.251.100": {
"hostname": "",
"state": "up",
"open_ports": [
{"port": 8080, "protocol": "tcp", "state": "open", "service": "http-proxy", "version": ""}
]
}
}
}
The agent can immediately tell you: .1 is the gateway, .55 looks like a network printer (IPP + JetDirect), .20 has SSH exposed, and .100 has something on 8080 worth investigating.
Service detection — find out exactly what's running
Prompt: "What services are running on 10.35.251.20?"
{
"scan_id": "20260304_120045_b2c3d4",
"target": "10.35.251.20",
"intensity": 7,
"total_open": 2,
"per_host": {
"10.35.251.20": {
"hostname": "",
"state": "up",
"open_ports": [
{
"port": 22,
"protocol": "tcp",
"state": "open",
"service": "ssh",
"version": "OpenSSH 9.6p1 Ubuntu 3ubuntu13.14"
},
{
"port": 80,
"protocol": "tcp",
"state": "open",
"service": "http",
"version": "nginx 1.24.0"
}
]
}
}
}
Exact software versions — actionable for CVE lookup or patch management.
Typical Audit Workflow
1. Find live hosts: nmap_arp_discovery("10.35.251.0/24")
2. Quick port overview: nmap_top_ports("10.35.251.0/24", count=100)
3. Service detection: nmap_service_detection("10.35.251.20")
4. OS fingerprint: nmap_os_detection("10.35.251.20")
5. Check for known vulns: nmap_vuln_scan("10.35.251.20")
6. Deep single-host audit: nmap_full_recon("10.35.251.20")
Running Tests
python3 -m pytest tests/ -v
28 tests covering scope enforcement, audit logging, scan persistence, injection guards, port summary logic, and live integration against localhost.
Set SKIP_LIVE_TESTS=1 to run only unit tests (no actual nmap calls):
SKIP_LIVE_TESTS=1 python3 -m pytest tests/ -v
Security Notes
- Only scan networks you own or have explicit written permission to scan. Unauthorized network scanning is illegal in many jurisdictions.
- Keep your
config.yamlCIDR allowlist tight — default to your actual subnet, not all of RFC1918. - The audit log captures all scan activity. Review it periodically.
nmap_custom_scanrejects shell metacharacters (;,|,&,`,$, etc.) but is still the most flexible tool — use the specific tools where possible.
License
MIT
Contributing
PRs welcome. Please include tests for new tools or behavior changes — the test suite is the spec.