# NetScope MCP Server

Package/command: `netscope-mcp`

An MCP (Model Context Protocol) server that gives AI assistants access to NetScope — an internet-scale network scanner with Shodan-style search across hosts, services, banners, TLS certificates, HTTP responses, SNMP data, and Nuclei security findings.

Designed to work alongside [`eip-mcp`](https://codeberg.org/exploit-intel/eip-mcp) so an AI assistant can cross-reference scan findings with vulnerability/exploit intelligence.

## Highlights

- Shodan-style search across all discovered services, hosts, and findings
- Full service detail: banners, TLS certs, HTTP responses, technologies, SNMP
- Nuclei security findings — CVEs, misconfigurations, exposures, tech detections
- 12K+ Nuclei template catalog with search and filtering
- Screenshot gallery for visual reconnaissance
- Distributed drone fleet monitoring
- Plain-text output optimized for LLM consumption

## What This Enables

With this MCP server, your AI assistant can:

- Search services across your scanned network using Shodan-style syntax
- Identify what's running on a specific IP (ports, services, OS, SNMP data)
- Find all hosts affected by a specific vulnerability
- Discover exposed web applications, login pages, and admin panels
- Review TLS certificates, JARM fingerprints, and SMB signing status
- Browse the full attack surface: products, countries, technologies, open ports
- See screenshot previews of web and RDP services
- Monitor the scanning drone fleet
- Cross-reference findings with eip-mcp for full exploit intelligence

## Tools (13)

| Tool | Description |
|---|---|
| `search_services` | Search services with Shodan-style syntax (port, IP, product, tech, country, banner, TLS, etc.) |
| `search_hosts` | Search hosts grouped by IP with aggregated ports and services |
| `get_service` | Full service detail: banner, HTTP, TLS, technologies, enumeration, screenshots, Nuclei findings |
| `get_host` | Everything about an IP: all services, GeoIP, ASN, reverse DNS, SNMP data |
| `get_facets` | Aggregated counts by service, port, product, tech, country, status, severity |
| `get_dashboard` | High-level scan statistics and default facets |
| `get_findings` | Top Nuclei security findings by severity (CVEs, misconfigs, exposures, tech detections) |
| `get_webapps` | Top web applications (HTTP titles) by host count |
| `get_ports` | Top open ports with primary service names |
| `explore` | Browse full listings: products, services, countries, technologies, findings, ports, scans |
| `get_drones` | Scanning drone fleet status, capabilities, and assignments |
| `search_templates` | Search 12K+ Nuclei templates by name, CVE, severity, or category |
| `get_gallery` | Screenshot gallery — services with HTTP/RDP screenshots |

## Installation

### Requirements

- **Python 3.10 or newer** (check with `python3 --version`)
- **pip** (comes with Python on most systems)
- An MCP-compatible AI client (Cursor IDE, Claude Desktop, etc.)

### Linux (Ubuntu / Debian / Kali)

```bash
sudo apt update && sudo apt install -y python3-pip python3-venv

# Recommended: pipx
sudo apt install -y pipx
pipx install netscope-mcp

# Alternative: virtual environment
python3 -m venv ~/.venvs/netscope-mcp
source ~/.venvs/netscope-mcp/bin/activate
pip install netscope-mcp
```

### macOS

```bash
brew install python3 pipx
pipx install netscope-mcp
```

### From Source

```bash
git clone https://github.com/netscope/netscope-mcp.git
cd netscope-mcp
python3 -m venv .venv
source .venv/bin/activate
pip install -e .
```

### With Streamable HTTP Transport

If you need to run the MCP server as a remote HTTP service (e.g., on the scanner host itself):

```bash
pip install 'netscope-mcp[http]'
```

## Configuration

### Required Environment Variables

| Variable | Description |
|---|---|
| `NETSCOPE_URL` | Base URL of your NetScope instance (e.g. `https://scanner.corp:8443`) |
| `NETSCOPE_PASS` | Basic auth password |

### Optional Environment Variables

| Variable | Default | Description |
|---|---|---|
| `NETSCOPE_USER` | `admin` | Basic auth username |
| `NETSCOPE_VERIFY_TLS` | `true` | Set to `false` for self-signed certificates |
| `NETSCOPE_MCP_TRANSPORT` | `stdio` | Transport: `stdio` or `streamable-http` |
| `NETSCOPE_MCP_HOST` | `127.0.0.1` | Bind address for HTTP transport |
| `NETSCOPE_MCP_PORT` | `8080` | Bind port for HTTP transport |
| `NETSCOPE_MCP_MAX_CONCURRENCY` | `4` | Max concurrent tool calls |
| `NETSCOPE_MCP_MAX_CALLS` | `60` | Rate limit: max calls per period |
| `NETSCOPE_MCP_CALL_PERIOD_SECONDS` | `60` | Rate limit window in seconds |
| `NETSCOPE_MCP_STATELESS` | `false` | Disable HTTP session tracking |
| `NETSCOPE_MCP_ALLOWED_HOSTS` | *(auto)* | Comma-separated allowed Host headers for HTTP transport |

## Connecting to Your AI Client

### Option A: Local stdio (Python on same machine)

Add to `.cursor/mcp.json`:

```json
{
  "mcpServers": {
    "netscope": {
      "command": "netscope-mcp",
      "env": {
        "NETSCOPE_URL": "https://your-scanner:8443",
        "NETSCOPE_PASS": "your-password",
        "NETSCOPE_VERIFY_TLS": "false"
      }
    }
  }
}
```

If using a virtual environment, use the full path:

```json
{
  "mcpServers": {
    "netscope": {
      "command": "/home/user/.venvs/netscope-mcp/bin/netscope-mcp",
      "env": {
        "NETSCOPE_URL": "https://your-scanner:8443",
        "NETSCOPE_PASS": "your-password",
        "NETSCOPE_VERIFY_TLS": "false"
      }
    }
  }
}
```

### Option B: Remote HTTP (server runs on scanner host)

Install on the scanner host with `pip install 'netscope-mcp[http]'`, then run as a systemd service or manually:

```bash
export NETSCOPE_URL=https://127.0.0.1:8443
export NETSCOPE_PASS=your-password
export NETSCOPE_VERIFY_TLS=false
netscope-mcp --transport streamable-http --host 0.0.0.0 --port 8081
```

Then point Cursor at the remote URL in `.cursor/mcp.json`:

```json
{
  "mcpServers": {
    "netscope": {
      "url": "http://scanner-ip:8081/mcp"
    }
  }
}
```

When binding to `0.0.0.0`, set `NETSCOPE_MCP_ALLOWED_HOSTS` to include the IP clients will connect from (e.g. `192.168.1.100:8081,127.0.0.1:8081`). This prevents HTTP 421 errors from DNS rebinding protection.

### Claude Desktop

Add to Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS, `%APPDATA%\Claude\claude_desktop_config.json` on Windows):

```json
{
  "mcpServers": {
    "netscope": {
      "command": "netscope-mcp",
      "env": {
        "NETSCOPE_URL": "https://your-scanner:8443",
        "NETSCOPE_PASS": "your-password",
        "NETSCOPE_VERIFY_TLS": "false"
      }
    }
  }
}
```

### Verify

After restarting your AI client, you should see 13 tools available. Try asking:

> "Show me the dashboard"

### Troubleshooting

| Problem | Solution |
|---|---|
| MCP server not showing up | Restart Cursor/Claude Desktop after editing the config |
| `command not found: netscope-mcp` | Use the full path to the binary inside the venv |
| HTTP 421 error | Add the client IP to `NETSCOPE_MCP_ALLOWED_HOSTS` |
| HTTP 401 error | Check `NETSCOPE_USER` and `NETSCOPE_PASS` |
| Connection refused | Check that `NETSCOPE_URL` is correct and the scanner is reachable |
| TLS certificate errors | Set `NETSCOPE_VERIFY_TLS=false` for self-signed certs |

## Search Syntax

NetScope uses Shodan-style search operators. All operators work with `search_services`, and many work with `get_findings`, `get_webapps`, and `get_gallery`.

### Service Filters

| Operator | Example | Description |
|---|---|---|
| `port` | `port:443` | Exact port, range (`1-1024`), or list (`80,443,8080`) |
| `ip` | `ip:10.0.0.0/24` | Exact IP, CIDR range, or wildcard (`10.0.0.*`) |
| `service` | `service:http` | Service name (http, ssh, ftp, etc.) |
| `product` | `product:nginx` | Software product name |
| `version` | `version:1.18` | Software version substring |
| `banner` | `banner:OpenSSH` | Full-text banner search |
| `tech` | `tech:WordPress` | Detected technology |

### HTTP Filters

| Operator | Example | Description |
|---|---|---|
| `title` | `title:"Login"` | HTTP page title |
| `status` | `status:200` | HTTP status code (or `2xx` for ranges) |
| `server` | `server:Apache` | HTTP Server header |
| `header` | `header:X-Powered-By` | Any HTTP header content |

### TLS Filters

| Operator | Example | Description |
|---|---|---|
| `cn` | `cn:*.example.com` | TLS subject CN or SAN |
| `issuer` | `issuer:DigiCert` | TLS issuer organization |
| `jarm` | `jarm:21d14d` | JARM TLS fingerprint prefix |
| `expires` | `expires:<30d` | Certificate expiry (relative or absolute) |

### GeoIP Filters

| Operator | Example | Description |
|---|---|---|
| `country` | `country:US` | Two-letter country code |
| `asn` | `asn:13335` | Autonomous System Number |
| `org` | `org:Cloudflare` | AS organization name |
| `rdns` | `rdns:*.corp.com` | Reverse DNS hostname |

### Enumeration Filters

| Operator | Example | Description |
|---|---|---|
| `os` | `os:Windows` | Operating system |
| `hostname` | `hostname:DC*` | NetBIOS/DNS hostname |
| `domain` | `domain:corp.local` | AD/DNS domain |
| `signing` | `signing:disabled` | SMB signing status |
| `share` | `share:C$` | SMB share name |
| `snmp` | `snmp:Linux` | SNMP data substring |
| `sysdesc` | `sysdesc:Ubuntu` | SNMP sysDescr field |

### Security Filters

| Operator | Example | Description |
|---|---|---|
| `finding` | `finding:CVE-2024-*` | Nuclei finding template ID, name, or tags |
| `vuln` | `vuln:CVE-2020-3952` | Medium+ severity findings only |
| `severity` | `severity:critical` | Finding severity level |

### Boolean Filters

| Operator | Example | Description |
|---|---|---|
| `has:screenshot` | | Services with screenshots |
| `has:tls` | | Services with TLS certificates |
| `has:nuclei` | | Services with Nuclei findings |
| `has:enum` | | Services with enumeration data |
| `has:banner` | | Services with banners |
| `has:http` | | HTTP services |
| `has:tech` | | Services with detected technologies |
| `has:favorite` | | Favorited IPs |

### Date Filters

| Operator | Example | Description |
|---|---|---|
| `seen:<7d` | | Seen within last 7 days |
| `seen:>30d` | | Not seen in 30+ days |
| `seen:2024-01-01..2024-12-31` | | Date range |

### Combining and Negating

Combine operators: `port:443 country:US has:nuclei severity:critical`

Negate with `-`: `-port:22 -service:ssh` excludes SSH services.

## User Guide

Below are real questions and actual output from a live NetScope instance.

---

### "Give me an overview of the scan data"

Uses `get_dashboard`:

```
NetScope Dashboard

STATISTICS:
  total_hosts: 4,795
  total_services: 42,685
  total_countries: 5
  total_findings: 1,717

TOP FACETS:
  PORT:
    80                                3043
    443                               2830
    22                                2279
    53                                1088
    143                                837
  PRODUCT:
    OpenSSH                           3058
    nginx                             1391
    Microsoft-HTTPAPI                 1247
    Microsoft-IIS                      669
    Microsoft Windows RPC              639
  COUNTRY:
    IR                                4576
    BB                                 138
    AG                                  50
    US                                  30
    GB                                   1
  SEVERITY:
    critical                           119
    high                               185
    medium                              71
    low                                126
    info                              1216
```

---

### "What are the top security findings?"

Uses `get_findings`:

```
Security Findings

  [CRITICAL] CVE-2025-49844
             Redis Lua Parser < 8.2.2 - Use After Free
             Affected hosts: 23

  [CRITICAL] CVE-2025-46817
             Redis < 8.2.1 lua script - Integer Overflow
             Affected hosts: 23

  [CRITICAL] CVE-2020-3952
             VMware vCenter Server LDAP Broken Access Control
             Affected hosts: 13

  [CRITICAL] CVE-2025-49113
             Roundcube Webmail - Remote Code Execution
             Affected hosts: 6

  [CRITICAL] CVE-2024-42009
             Roundcube Webmail - Cross-Site Scripting
             Affected hosts: 6
```

---

### "What's running on 31.25.90.4?"

Uses `get_host`:

```
============================================================
Host: 31.25.90.4  [5 services]
============================================================
Country: IR
ASN: AS34412 (SABA-HOST, IR)
rDNS: 31-25-90-4.hosted-by.saba.host
Open ports: 5
First seen: 2026-02-12 15:10  |  Last seen: 2026-02-12 16:25

SNMP:
  sys_name: promat.mizban.cloud
  community: public
  sys_descr: Linux promat.mizban.cloud 5.4.0-91-generic #102-Ubuntu SMP ...
  sys_contact: Me <me@example.org>
  sys_location: Sitting on the Dock of the Bay

SERVICES:
  :22/tcp  ssh  [service_id=1188]
    Enum: ssh_banner=Unknown SSH Version, skipping...
  :1332/tcp  http  [service_id=1338]
    Title: Prometheus Time Series Collection and Processing Server
  :1333/tcp  http  [service_id=911]
    Title: Alertmanager
  :1335/tcp  http  [service_id=904]
    Banner: HTTP/1.1 400 Bad Request
  :49153/tcp  http  (Node.js)  [service_id=558] [screenshot]
```

---

### "What vulns affect the 31.25.90.0/24 subnet?"

Uses `get_findings` with query `ip:31.25.90.0/24`:

```
Security Findings for: ip:31.25.90.0/24

  [CRITICAL] CVE-2025-49844
             Redis Lua Parser < 8.2.2 - Use After Free
             Affected hosts: 2

  [CRITICAL] CVE-2025-46817
             Redis < 8.2.1 lua script - Integer Overflow
             Affected hosts: 2

  [CRITICAL] CVE-2024-28000
             WordPress LiteSpeed Cache - Unauthenticated Privilege Escalation
             Affected hosts: 1

  [CRITICAL] CVE-2020-3952
             VMware vCenter Server LDAP Broken Access Control
             Affected hosts: 1

  [HIGH    ] CVE-2025-46819
             Redis < 8.2.1 Lua Long-String Delimiter - Out-of-Bounds Read
             Affected hosts: 2
```

---

### "Show me the VMware ESXi service detail"

Uses `get_service` with a service_id from search results:

```
============================================================
185.116.161.52:443/tcp  https  [service_id=85378]
============================================================
First seen: 2026-02-13 03:11  |  Last seen: 2026-02-13 03:48
Scan: #55  |  Current: yes

GEO/NETWORK:
  Country: IR
  ASN: AS61173 (GWSN-AS, IR)
  rDNS: static.52.161.116.185.clients.irandns.com

HTTP:
  Status: 200
  Title: Welcome to VMware ESXi

TLS:
  Subject CN: localhost.localdomain
  Issuer: VMware Installer
  Expires: 2031-04-23 05:40
  JARM: 21d14d00021d21d21c21d14d21d21d3e9a0dda94718e521eb7d1409c9e3601

SCREENSHOTS (1):
  [http] Welcome to VMware ESXi
    URL: https://185.116.161.52/

SECURITY FINDINGS (3):
  [CRITICAL] CVE-2020-3952
    VMware vCenter Server LDAP Broken Access Control
    Tags: cve,cve2020,vmware,vcenter,ldap,auth-bypass,passive,kev,vkev
  [INFO] esxi-system
    ESXi System Login Panel - Detect
  [INFO] vmware-detect
    VMware Detection
```

---

### "Find nginx services with vulnerabilities"

Uses `search_services` with query `product:nginx has:nuclei`:

```
Found 92 services for query: product:nginx has:nuclei

  212.23.201.206:8080/tcp  http  (nginx/1.18.0 (Ubuntu)) [screenshot]
    Title: Pazhonic Zabbix: Zabbix
    Geo: IR PARVASYSTEM, IR
    Seen: 2026-02-13 13:03  [service_id=97517]

  212.23.201.190:443/tcp  https  (nginx/1.18.0 (Ubuntu))
    Title: n8n.io - Workflow Automation
    Geo: IR PARVASYSTEM, IR
    Seen: 2026-02-13 13:03  [service_id=97128]

  212.23.201.191:9000/tcp  http  (nginx 1.27.3) [screenshot]
    Title: MinIO Console
    Geo: IR PARVASYSTEM, IR
    Seen: 2026-02-13 13:03  [service_id=97090]
```

---

### "What web apps are on the network?"

Uses `get_webapps`:

```
Web Applications

    307 hosts  Welcome to nginx!
    264 hosts  Service Unavailable
    215 hosts  Default Web Site Page
    174 hosts  cPanel Login
    152 hosts  WHM Login
    133 hosts  IIS Windows Server
    113 hosts  Webmail Login
     92 hosts  Evolution | DirectAdmin
     60 hosts  Web Server's Default Page
     52 hosts  Node Exporter
```

---

### "What's the port distribution on HTTPS services?"

Uses `get_facets` with query `port:443`:

```
Facets for query: port:443

  SERVICE:
    https                             2536
    tls                                201
    http                                88

  PRODUCT:
    nginx                              342
    Apache                             183
    nginx/1.24.0 (Ubuntu)              156
    nginx/1.18.0 (Ubuntu)              121
    LiteSpeed                          115

  COUNTRY:
    IR                                2744
    BB                                  39
    US                                  30
    AG                                  16
    GB                                   1

  SEVERITY:
    critical                            34
    high                                 8
    medium                              15
    low                                 12
    info                               260
```

---

### "Show me the scanning drones"

Uses `get_drones`:

```
Scanning Fleet (6 drones)

  drone-01  [IDLE]  209.141.32.226
    Scans completed: 0  |  Last seen: 2026-02-17 06:31
    Capabilities: zmap, zgrab2, snmp_scan, service_enum, nmap_identify,
                  rdp_screenshot, http_screenshot

  drone-02  [IDLE]  205.185.113.200
    Scans completed: 0  |  Last seen: 2026-02-17 06:31
    Capabilities: zmap, nuclei, zgrab2, snmp_scan, service_enum,
                  nmap_identify, rdp_screenshot, http_screenshot
  ...
```

---

### "Find critical Redis Nuclei templates"

Uses `search_templates` with query `redis`, severity `critical`:

```
Nuclei Templates: 5 total (query='redis', severity=critical)

  [CRITICAL] CVE-2020-11981 [verified]
             Apache Airflow <=1.10.10 - Command Injection
             by pussycat0x | CVE-2020-11981 | cves | CVSS:9.8
             Tags: cve, cve2020, network, redis, unauth, apache, airflow

  [CRITICAL] CVE-2022-0543
             Redis Sandbox Escape - Remote Code Execution
             by dwisiswant0 | CVE-2022-0543 | cves | CVSS:10.0
             Tags: cve, cve2022, network, redis, unauth, rce, kev

  [CRITICAL] CVE-2025-46817 [verified]
             Redis < 8.2.1 lua script - Integer Overflow
             by pussycat0x | cves
             Tags: cve, cve2025, js, redis, network, passive
```

---

### "Show me login pages with screenshots"

Uses `get_gallery` with query `title:Login`:

```
Screenshot Gallery: 897 services with screenshots matching: title:Login

  171.22.26.131:8083  [service_id=98214]
    Title: LOGIN - panel.nobifa.shop - Hestia Control Panel
    [http] LOGIN - panel.nobifa.shop - Hestia Control Panel

  34.149.180.14:443  [service_id=119183]
    Title: Bringg | Login
    [http] Bringg | Login
```

---

### "What hosts are in Barbados?"

Uses `search_hosts` with query `country:BB`:

```
Found 138 hosts

  69.80.31.13  [3 services]
    Ports: 80, 443, 541
    Services: http, https, tls
    Geo: BB ASN15344-SLU - Karib Cable, LC
    Last seen: 2026-02-13 03:07

  69.80.31.23  [1 services]
    Ports: 8206
    Services: unknown
    Geo: BB ASN15344-SLU - Karib Cable, LC
    Last seen: 2026-02-13 03:07
```

## Cross-Reference with eip-mcp

When both `netscope-mcp` and `eip-mcp` are configured, an AI assistant can:

1. Use `get_findings` to discover CVE-based findings on the network
2. Use eip-mcp's `get_vulnerability` with the CVE ID for full exploit intelligence (EPSS score, ranked exploits, MITRE ATT&CK techniques — exploits are included in the response)
3. Use eip-mcp's `search_vulnerabilities` with product names from service banners to find additional CVEs not caught by Nuclei
4. Use `search_services` to find all hosts affected by a specific vulnerability

Example workflow:

> "What critical vulnerabilities are on my network, and are there working exploits for them?"

The assistant calls `get_findings` (netscope-mcp) to discover CVE-2020-3952 affecting 13 hosts, then calls `get_vulnerability` (eip-mcp) to see it has 127 public exploits including a Metasploit module. It can also pull version strings from `get_service` (e.g. "Samba 3.0.20") and search eip-mcp's `search_vulnerabilities(query="samba 3.0")` to find CVEs that Nuclei didn't scan for.

## Security

### Input Validation

Every parameter passes through strict validation before reaching the API:

- **IP addresses**: IPv4/IPv6 format validated
- **Service IDs**: Positive integers, capped at 2^31
- **Search queries**: Max 500 chars, null bytes rejected, control characters stripped
- **Enums**: Severity, category, sort order validated against allowlists
- **Limits**: Range-checked (1-200 for most endpoints)

### Network

- TLS verification enabled by default (configurable for self-signed certs)
- Basic Auth credentials sent only to the configured `NETSCOPE_URL`
- Timeouts on all HTTP calls (30s read, 10s connect)
- Rate limiting: 60 calls per 60 seconds by default

### Response Safety

- All output is plain text (no executable content)
- Error messages are generic (no internal API details leaked)
- Banners and descriptions truncated to prevent context overflow

## Building

```bash
make build          # Build dist/*.whl and dist/*.tar.gz
make check          # Validate with twine
make pypi           # Upload to PyPI
make release VERSION=0.1.0   # Full release: bump, build, upload, tag
```

## Dependencies

- `mcp>=1.2.0` — Official MCP Python SDK
- `httpx>=0.27.0` — HTTP client
- Python 3.10+

Optional (for HTTP transport):
- `uvicorn>=0.27.0`
- `starlette>=0.36.0`
- `sse-starlette>=1.6.0`

## License

MIT
