nmap_scan.py•4 kB
"""
Nmap Scan Tool - Windows/WSL Compatible
Port scanning and service detection using nmap
"""
from typing import Dict, Any, List
from .base_tool import BaseTool
import subprocess
import platform
import shlex
class NmapScanTool(BaseTool):
"""Nmap port scanning tool"""
def __init__(self):
super().__init__()
self.name = "nmap_scan"
self.description = "Port scanning and service detection using nmap. Scans target host for open ports and running services."
def get_tool_definition(self) -> Dict[str, Any]:
"""Return MCP-compatible tool definition"""
return {
"name": self.name,
"description": self.description,
"inputSchema": {
"type": "object",
"properties": {
"target": {
"type": "string",
"description": "Target host or IP address to scan (e.g., scanme.nmap.org or 192.168.1.1)"
},
"scan_type": {
"type": "string",
"description": "Type of scan: 'quick' (default, -F), 'full' (-p-), or 'version' (-sV)",
"enum": ["quick", "full", "version"],
"default": "quick"
}
},
"required": ["target"]
}
}
async def execute(self, arguments: Dict[str, Any]) -> List[Dict[str, Any]]:
"""Execute nmap scan"""
try:
target = arguments.get("target", "")
scan_type = arguments.get("scan_type", "quick")
if not target:
return self.format_error("Target is required")
# Build nmap command based on scan type
if scan_type == "quick":
nmap_args = ["-F", "-Pn", target]
elif scan_type == "full":
nmap_args = ["-p-", "-Pn", target]
elif scan_type == "version":
nmap_args = ["-sV", "-Pn", target]
else:
nmap_args = ["-F", "-Pn", target]
# Detect platform and build appropriate command
is_windows = platform.system() == 'Windows'
if is_windows:
# Use WSL on Windows
cmd = ["wsl", "nmap"] + nmap_args
else:
# Direct execution on Linux/Mac
cmd = ["nmap"] + nmap_args
# Execute nmap
try:
result = subprocess.run(
cmd,
capture_output=True,
text=True,
timeout=600 # 10 minutes max
)
if result.returncode == 0:
output = result.stdout if result.stdout else "Scan completed but no output received"
# Format output nicely
formatted = f"""✅ Nmap Scan Results for {target}
{'='*60}
Scan Type: {scan_type}
Command: {' '.join(cmd)}
{output}
{'='*60}"""
return self.format_success(formatted)
else:
error = result.stderr or result.stdout or "Unknown error"
return self.format_error(f"Nmap scan failed: {error}")
except FileNotFoundError:
if is_windows:
return self.format_error("WSL not found. Please install WSL and nmap: wsl --install, then sudo apt install nmap")
else:
return self.format_error("Nmap not found. Please install: sudo apt install nmap")
except subprocess.TimeoutExpired:
return self.format_error("Scan timeout (exceeded 10 minutes)")
except Exception as e:
return self.format_error(f"Execution failed: {str(e)}")
tool_instance = NmapScanTool()