# Pentest MCP
[](https://smithery.ai/server/@DMontgomery40/pentest-mcp)
[](https://mseep.ai/app/fa558a10-f45c-4668-9bb6-15630dd51f27)
Professional penetration-testing MCP server with modern transport/auth support and expanded recon tooling.
## What Changed in 0.9.0
- Upgraded MCP SDK to `@modelcontextprotocol/sdk@^1.26.0`
- Kept MCP Inspector at the latest release (`@modelcontextprotocol/inspector@^0.20.0`) with bundled launcher
- Streamable HTTP is now the primary network transport (`MCP_TRANSPORT=http`)
- SSE is still available only as a deprecated compatibility mode
- Added bearer-token auth with OIDC JWKS and introspection support
- Added first-class tools: `subfinderEnum`, `httpxProbe`, `ffufScan`, `nucleiScan`, `trafficCapture`, `hydraBruteforce`, `privEscAudit`, `extractionSweep`
- Added report-admin tools: `listEngagementRecords`, `getEngagementRecord`
- Added SoW capture flow for reports using MCP elicitation (`scopeMode=ask`) with safe template fallback
- Hardened command resolution so web probing uses `httpx-toolkit` (preferred) or validated ProjectDiscovery `httpx`, avoiding Python `httpx` CLI collisions
- Integrated bundled MCP Inspector launcher (`pentest-mcp inspector`)
- Runtime baseline is now Node.js 22.7.5+
- Added invocation metadata in new tool outputs when auth/session context is available
## Included Tools
- `nmapScan`
- `runJohnTheRipper`
- `runHashcat`
- `gobuster`
- `nikto`
- `subfinderEnum`
- `httpxProbe`
- `ffufScan`
- `nucleiScan`
- `trafficCapture`
- `hydraBruteforce`
- `privEscAudit`
- `extractionSweep`
- `generateWordlist`
- `listEngagementRecords`
- `getEngagementRecord`
- `createClientReport`
- `cancelScan`
## Quick Start
### Install
```bash
npm install -g pentest-mcp
```
### Run locally (stdio)
```bash
pentest-mcp
```
### Launch bundled MCP Inspector (no separate install)
```bash
pentest-mcp inspector
```
You can forward Inspector flags directly:
```bash
pentest-mcp inspector --help
```
### Run over network (Streamable HTTP)
```bash
MCP_TRANSPORT=http MCP_SERVER_HOST=0.0.0.0 MCP_SERVER_PORT=8000 pentest-mcp
```
### Run legacy SSE mode (deprecated)
```bash
MCP_TRANSPORT=sse MCP_SERVER_PORT=8001 pentest-mcp
```
## Transport Notes
- `stdio`: default for local MCP clients.
- `http`: modern network transport. Recommended.
- `sse`: compatibility only. Deprecated and will be removed in a future major release.
## Inspector Integration
- `pentest-mcp inspector` launches the bundled `@modelcontextprotocol/inspector` CLI.
- It auto-targets this MCP server over stdio by spawning:
- `node <this-package-entrypoint> stdio`
- You do not need to install Inspector separately.
## Auth Configuration (Bearer + OIDC)
Set these env vars when using `MCP_TRANSPORT=http` (or `sse` if needed):
```bash
MCP_AUTH_ENABLED=true
MCP_AUTH_MODE=bearer
MCP_AUTH_SCOPES=read,write
MCP_AUTH_AUDIENCE=
MCP_OIDC_ISSUER=https://issuer.example.com
MCP_OIDC_JWKS_URL=https://issuer.example.com/.well-known/jwks.json
# optional alternative/backup validation mode:
MCP_OIDC_INTROSPECTION_URL=https://issuer.example.com/oauth/introspect
MCP_OAUTH_CLIENT_ID=...
MCP_OAUTH_CLIENT_SECRET=...
```
Legacy aliases are still accepted temporarily:
- `MCP_OAUTH_ENABLED`
- `MCP_OAUTH_PROVIDER_URL`
- `MCP_OAUTH_SCOPES`
## Workflow + Reporting
`createClientReport` now supports SoW handling modes:
- `scopeMode=ask`: prompt user via MCP elicitation (recommended)
- `scopeMode=provided`: use `scopeOfWork` value directly
- `scopeMode=template`: use built-in generic authorized-testing template
If elicitation is declined/unavailable, the report automatically falls back to the template.
### How users provide SoW (right now)
There is no separate file-upload API yet. Current options are:
1. Ask interactively via MCP user invocation (elicitation)
```json
{
"tool": "createClientReport",
"arguments": {
"title": "Q1 External Pentest",
"assessmentType": "external-network",
"scopeMode": "ask"
}
}
```
2. Paste SoW text directly into `scopeOfWork`
```json
{
"tool": "createClientReport",
"arguments": {
"title": "Q1 External Pentest",
"assessmentType": "external-network",
"scopeMode": "provided",
"scopeOfWork": "Authorized targets: ...\nOut-of-scope: ...\nTesting window: ...\nRules of engagement: ..."
}
}
```
3. Use template mode when client details should not be shared
```json
{
"tool": "createClientReport",
"arguments": {
"title": "Q1 External Pentest",
"assessmentType": "external-network",
"scopeMode": "template"
}
}
```
### How this cuts admin time
- Every tool run stores a structured engagement record (`recordId=...`) with invocation context.
- Use `listEngagementRecords` to pull all work artifacts quickly.
- Generate the report from selected `recordIds` (or latest records by default) instead of manual copy/paste.
- Scope notes are attached automatically from one of:
- user elicitation form (`ask`)
- pasted SoW text (`provided`)
- safe default template (`template`)
## Roadmap
These are planned specifically to reduce pentest admin overhead.
- `scopeFilePath` ingestion (load SoW from a local file path on the MCP host)
- `scopeDocument` chunked upload flow (send SoW content directly through MCP for remote clients)
- SoW parser that auto-extracts targets, exclusions, test windows, and rules of engagement
- Evidence auto-linking from tool outputs (`recordId`) to findings and report sections
- Finding dedup/merge across overlapping tools (`nuclei`, `nikto`, etc.)
- Auto severity + impact draft text for faster writeups
- One-click report pack generation (executive summary + technical appendix + remediation table)
- Retest diff mode (fixed/reopened/new findings between engagements)
- Ticket export sync (Jira/Linear/GitHub) with status backfill
- Deliverable QA checks (missing evidence, missing scope fields, weak remediation notes)
Adoption note:
- Expect strong usage for `scopeFilePath` and `scopeDocument` because most teams already maintain SoW in docs/PDF and want to avoid repeated paste-and-reformat steps.
## Recon + Exploitation Examples
### Subdomain enumeration
```json
{
"tool": "subfinderEnum",
"arguments": {
"domain": "example.com",
"recursive": true,
"allSources": true
}
}
```
### Probe live hosts
```json
{
"tool": "httpxProbe",
"arguments": {
"targets": ["example.com", "api.example.com"],
"includeTitle": true,
"includeStatusCode": true
}
}
```
### Fuzz content paths
```json
{
"tool": "ffufScan",
"arguments": {
"targetUrl": "https://example.com/FUZZ",
"wordlist": "/usr/share/seclists/Discovery/Web-Content/common.txt",
"threads": 40
}
}
```
### Template scanning
```json
{
"tool": "nucleiScan",
"arguments": {
"targets": ["https://example.com"],
"severities": ["medium", "high", "critical"]
}
}
```
### Traffic capture (sniffing)
```json
{
"tool": "trafficCapture",
"arguments": {
"networkInterface": "eth0",
"packetCount": 200,
"bpfFilter": "tcp port 80"
}
}
```
### Brute-force checks
```json
{
"tool": "hydraBruteforce",
"arguments": {
"target": "10.10.10.20",
"service": "ssh",
"usernameList": "/usr/share/seclists/Usernames/top-usernames-shortlist.txt",
"passwordList": "/usr/share/seclists/Passwords/Common-Credentials/10k-most-common.txt"
}
}
```
### SQLi extraction sweep
```json
{
"tool": "extractionSweep",
"arguments": {
"targetUrl": "https://target.local/item.php?id=1",
"risk": 2,
"level": 3
}
}
```
## Docker
```bash
docker-compose --profile http up
docker-compose --profile stdio up
docker-compose --profile sse up
```
The Docker image installs:
- `nmap`, `john`, `hashcat`, `gobuster`, `nikto`, `ffuf`, `hydra`, `sqlmap`, `tcpdump`
- `subfinder`, `httpx` + `httpx-toolkit` alias, `nuclei`
## Required Host Tools (non-Docker runs)
Ensure the binaries are in `PATH`:
```bash
which nmap john hashcat gobuster nikto subfinder httpx-toolkit ffuf nuclei hydra sqlmap tcpdump
```
If `httpx-toolkit` is not installed, a validated ProjectDiscovery `httpx` binary is accepted as fallback.
## Security Notice
Authorized use only. Run against systems/networks where you have explicit written permission.