Pentest MCP: Professional Penetration Testing Toolkit
LocalAbout Pentest MCP: Professional Penetration Testing Toolkit
Pentest MCP is a TypeScript server for authorized security assessments by human researchers or tool-using agents. It gates actions by engagement scope and time, records evidence durably, and supports evidence-based report preparation.
Key features
- 01Register engagements and assessment plans
- 02Enforce target, time, and tool limits
- 03Run security assessment tools
- 04Store and retrieve evidence records
- 05Prepare reports from selected evidence
Use cases
- 01Conduct an authorized scoped security assessment
- 02Review and investigate recorded scan results
- 03Run a planned assessment with an agent
- 04Prepare a report using analyst-verified findings
MCP support
Exposes scoped assessment, evidence, engagement, and reporting tools to MCP clients. Active calls are checked against engagement targets, time windows, and applicable tool allowlists.
Configuration
Local server config is the same for every client. Copy it into your client’s MCP config file.
We haven’t collected a package or remote endpoint for this server. Follow the instructions in the project README.
Tools
Local servers expose tools only once running on your machine, and the maintainer has not provided a tool list.
Details
From the project READMEPentest MCP
Pentest MCP is a TypeScript MCP server for authorized security assessments. It gives a human researcher or a tool-using assessment agent one scoped interface for discovery, validation, capture, credential checks, local audit, evidence retrieval, and report preparation. Each active tool call is tied to an engagement and a durable record. The server checks the declared targets and time window; the researcher verifies findings before publication.
October 2026 workflow
- Create an engagement from signed authorization and rules of engagement, then save the assessment plan. The operator chooses a stable
engagementId. - A researcher or fresh Codex process in the managed assessment container connects to the Pentest MCP server. It sees the complete catalog, while the plan's exact
allowedToolNameslist permits only selected calls. Active tools also pass the engagement target and time gate. - Review
recordIdvalues and correlated scope decisions withlistEngagementRecordsandgetEngagementRecord. Records persist across restarts. Import external research withrecordResearchActivity; the import does not replace MCP tool use. - Draft a report from the complete evidence ledger, inspect candidate findings against source records, and publish only analyst-verified findings. Retrieve Markdown or JSON later with
getClientReport.
The declared-target check is an operational guardrail, not a complete network boundary. DNS changes, redirects, Nmap scripts, Nuclei templates, and other third-party tool behavior can create secondary traffic. Review tool configuration and keep network controls aligned with the engagement's rules.
Agentic assessment uses the MCP tools
The assessment stage is a tool-using agent session. runAgentAssessment supports local Codex or Claude in a dedicated account profile, Codex in a pinned container, a loopback OpenAI-compatible server such as llama.cpp or Ollama, and OpenRouter. CLI workers receive a locked, single-engagement Pentest MCP server and discover the full catalog. Guarded API models receive only the exact plan allowlist intersected with the worker catalog. Every requested action still reaches the same worker-side plan, target, parent-status, and time checks before a handler starts. Optional hostileModelProtection adds duplicate-action, token-accounting, and finish-reason circuit breakers and defaults to false. An interrupted run with a durable start receipt and no terminal receipt blocks replay; reconcileAgentAssessment requires an operator to confirm that the prior process stopped, records reviewer and rationale, and revokes the prior worker scope when it is still available. The returned toolCounts, importedRecordIds, and importMapRecordId identify recorded actions and imported evidence. A run with no successful assessment-tool call fails.
draftAssessmentReport is a later, context-quarantined report-writing step; a draft alone does not show that Pentest MCP helped the assessment. OpenAI, Anthropic, OpenRouter, OpenAI-compatible, local Codex, local Claude, container Codex, and configured SSH profiles can draft from a bounded evidence packet without scanner tools. local-agent accepts self-hosted CLI profiles and loopback OpenAI-compatible profiles while rejecting hosted providers before context is sent. The guarded model guide gives llama.cpp and OpenRouter profiles, enforced stop conditions, audit fields, and hostile-model deployment boundaries. The container assessment guide gives CLI profile fields, real acceptance command, and isolation limits. The agentic workflow covers scope, evidence review, Daybreak/Glasswing access, and Faxbot planning.
Release acceptance uses scripts/run-real-acceptance.mjs. It has no default target or authorization and refuses to pass unless installed Nmap and ProjectDiscovery HTTPX create successful evidence records. With --profile, the managed agent must invoke both through Pentest MCP. With --report-profile, a separate report context must produce the saved draft. Test doubles remain in automated tests only and are never shipped as acceptance receipts.
Quick start
Requires Node.js 22.19.0 or newer and the host binaries for the tools you intend to use. The Docker image includes the listed tools; native installations must provide them in PATH.
npm install -g pentest-mcp
pentest-mcp
Stdio is the default for local MCP clients. pentest-mcp inspector starts the bundled MCP Inspector against this server over stdio; Inspector flags can be forwarded, for example pentest-mcp inspector --help.
Set PENTEST_DATA_DIR to choose the local evidence directory. Otherwise the server uses $XDG_DATA_HOME/pentest-mcp when that variable is set, or ~/.pentest-mcp. Evidence and report files are stored with private directory and file permissions. Treat raw outputs, hashes, captured traffic, and reports as client-sensitive data; control access, retention, and backups accordingly.
Register an engagement
Call createEngagement before scanning. Use dates, targets, and references from the actual signed authorization; the values below are illustrative.
{
"tool": "createEngagement",
"arguments": {
"engagementId": "client-2026-10",
"authorizationReference": "Signed SoW section 4, approved 2026-10-24",
"notBefore": "2026-10-25T09:00:00-06:00",
"expiresAt": "2026-10-26T18:00:00-06:00",
"allowedTargets": ["app.example.com", "192.0.2.0/28"],
"excludedTargets": ["192.0.2.7"],
"testingWindows": [
{
"start": "2026-10-25T09:00:00-06:00",
"end": "2026-10-25T17:00:00-06:00"
}
]
}
}
Allowed targets accept exact hosts, CIDRs, wildcard subdomains, and HTTP(S) URL prefixes. Exclusions take precedence. All timestamps need an explicit timezone. getEngagement and listEngagements inspect stored registrations. closeEngagement revokes later execution, aborts managed assessments running in the same server process, and causes a separate managed runner to stop when it observes the parent registry closure.
Run and review
Use the same engagementId for active tools. The default non-root container supports a TCP connect scan; SYN and OS detection need additional privileges that are not granted by default.
{
"tool": "nmapScan",
"arguments": {
"engagementId": "client-2026-10",
"target": "app.example.com",
"scanTechnique": "Connect",
"serviceVersionDetection": true
}
}
A successful tool response includes a recordId for its stored evidence. Retrieve only the records you need:
{
"tool": "listEngagementRecords",
"arguments": {
"engagementId": "client-2026-10",
"limit": 50
}
}
listEngagementRecords returns summaries and accepts limit and offset for paging through older records. getEngagementRecord takes both engagementId and recordId and returns stored evidence when permitted. Credential tools return counts and output digests. New unauthenticated Gobuster/Nikto records retain private scanner output and findings for owner-scoped reads; older scanner records remain redacted. Nmap XML and bounded ffuf/Nuclei machine output are retained alongside summaries. A record's outcome is succeeded, failed, or cancelled, with a start time and duration when tracked; subprocess failures create an audit record rather than a successful scan result. A preflight scope refusal starts no command. For authenticated HTTP, engagement and evidence access is scoped to the verified token owner; stdio data is local to the server installation.
Give the agent a client-specific plan
saveAssessmentPlan stores objectives, human-readable allowed and prohibited methods, exact allowedToolNames, data handling, stop conditions, report audience, work ownership, and model data policy as a versioned evidence record. getAssessmentPlan reads the latest version. The managed worker receives the full catalog but the server rejects any call omitted from allowedToolNames before its handler runs, leaving a failed audit receipt. When a plan exists, its allowlist also gates direct manual MCP calls to the 14 assessment methods; denials are audited before the handler or command runs. Direct calls on legacy engagements without a plan keep their previous behavior and still pass engagement scope gates. This plan cannot expand createEngagement targets or time. An external-client plan needs a provider client-work approval reference before model drafting, and no-model permits only the deterministic draft. See the plan schema and example.
After a plan with modelDataPolicy: "local-agent" or "approved-provider" and nonempty allowedToolNames is recorded, launch the tool-using run:
{
"tool": "runAgentAssessment",
"arguments": {
"engagementId": "client-2026-10",
"profileId": "daybreak-cli-assessment",
"timeoutSeconds": 900
}
}
The response includes a run ID, status, model, toolCounts, imported evidence IDs, importMapRecordId, and an ID for unreviewed model output. If the model, MCP child, or an assessment tool fails, inspect the retained failure and any imported records before retrying. If only a start receipt exists after a process interruption, verify that the old process stopped and call reconcileAgentAssessment with that run ID, the reviewer identity, and the reason for the decision. The server will not silently replay the run. A process that finishes without a successful assessment-tool call is rejected; its bounded output is retained privately with a failed outcome and linked hash for diagnosis, never as verified finding evidence. A completed agent process does not make its observations confirmed findings. The worker blocks engagement creation, closure, plan changes, recursive assessment launches, reconciliation, and report publication.
Ask for useful wordlist clues
Call generateWordlist with engagementId and omit baseWords when the MCP client supports form elicitation. The server asks the authorized operator for known names and aliases, organization or product terms, dates, location or address terms, and prefix or suffix patterns. They may skip unknown categories or decline. The prompt excludes current passwords and patient data. If the client lacks form elicitation, the tool returns the questions so the assistant can ask and retry with explicit baseWords, dates, locationWords, and customPatterns. The private wordlist record retains input counts and a SHA-256 digest rather than the supplied words or a sample of the list. Wordlist creation does not authorize password attempts; hydraBruteforce, runJohnTheRipper, and runHashcat must also fit the engagement methods.
Produce an evidence-backed report
createClientReport requires a registered engagement, client, title, assessment type, summary, and explicit recordIds. Use [] only when no tool evidence should be attached. Select the evidence records for each report deliberately; the server never silently chooses a limited subset. Audit, scope-gate, and report-workflow records cannot be attached as vulnerability evidence. Supply analyst-confirmed findings with severity, impact, remediation, verifier, timestamp, and evidence references. Scanner output remains an observation until a researcher verifies it. A report with an empty findings array explicitly says no analyst-verified vulnerability findings were included.
{
"tool": "createClientReport",
"arguments": {
"engagementId": "client-2026-10",
"client": "Example Client",
"title": "External Assessment",
"assessmentType": "External network",
"summary": "Assessment activity and verified outcomes are summarized below.",
"recordIds": [],
"findings": [],
"recommendations": ["Review the evidence index and validate remediation with a retest."],
"methodology": "Authorized, scoped enumeration and manual verification.",
"limitations": ["The example has no attached scan records."]
}
}
Replace recordIds with IDs from this engagement and add verified findings only after manual review. Each finding can include evidenceRecordIds, externalEvidence, affected assets, reproduction steps, references, CWE, CVSS vector, and retest status. Optional scopeOfWork text adds report context; it does not change executable scope. The report includes scope details from the registered engagement, verified severity counts, a completeness checklist, an evidence index with raw-output SHA-256 hashes, and limitations. Raw scanner output is kept in private evidence records rather than copied into the client-facing Markdown.
listClientReports takes engagementId. getClientReport takes engagementId and reportId, with format set to markdown or json. The Markdown report is also available as the mcp://pentest/clientReport/{reportId} resource.
For an agent-assisted report, call draftAssessmentReport after assessment records exist. Omit profileId for a deterministic evidence inventory or select a configured draft profile for model-written observations. local-agent permits CLI profiles and loopback openai-compatible profiles; approved-provider permits a configured API or CLI profile, including OpenRouter. Both receive bounded scope, plan and evidence summaries and may suggest unverified candidates. Under metadata-only, the model receives structural counts, tool names, evidence IDs and digests without client or plan prose, target names, authorization reference, evidence summaries or observations; candidate vulnerabilities are rejected. publishAgentReport requires a reviewer and explicit verified findings with evidence IDs and never promotes candidates automatically.
Tool inventory
| Work | Tools |
|---|---|
| Engagement lifecycle | createEngagement, getEngagement, listEngagements, closeEngagement |
| Discovery and validation | nmapScan, gobuster, nikto, subfinderEnum, httpxProbe, ffufScan, nucleiScan |
| Capture and credential checks | trafficCapture, hydraBruteforce, runJohnTheRipper, runHashcat, generateWordlist |
| Local audit and extraction | privEscAudit, extractionSweep |
| Scope, agent, and report workflow | saveAssessmentPlan, getAssessmentPlan, listAgentProfiles, runAgentAssessment, reconcileAgentAssessment, recordResearchActivity, draftAssessmentReport, listAgentReportDrafts, getAgentReportDraft, publishAgentReport |
| Evidence and direct reports | listEngagementRecords, getEngagementRecord, createClientReport, listClientReports, getClientReport |
| Runtime and scan control | getRuntimeStatus, listActiveScans, cancelScan |
Gobuster and Nikto accept Basic Auth and cookie values only as literal command arguments in the installed CLI versions, so the MCP tools reject those fields, URL userinfo, and query strings. Their immediate responses and report drafts include counts but not scanner text; new successful records retain private raw output and finding details for the engagement owner. Failed runs retain output digests. Use an operator-reviewed execution method outside these tools when authenticated scanning is required. Historical Gobuster/Nikto records are redacted on MCP reads and report drafting; previously stored files should be handled under the engagement's retention policy.
trafficCapture needs network capabilities and access to the interface being captured. In Docker, use the explicit Linux capture profile below. privEscAudit is available only over local stdio; inside a container it audits that container, so run the server natively when the authorized target is the host itself. Hashcat GPU acceleration also depends on host hardware and device passthrough, which the default container does not configure.
runHashcat can use Hashcat 8's bundled PCFG attack and custom hash recipes when version 8 is installed on the execution host; v8-only requests are rejected on older runtimes. It also accepts OpenCL/backend device IDs; FPGA bcrypt requires Hashcat 8, Linux, a compatible bridge, and a supported board. The Dockerfile builds the signed 8.0.0 source release and includes CPU OpenCL, while the default container does not pass through GPU or FPGA hardware. See Hashcat usage for inputs, version checks, and evidence handling.
getRuntimeStatus reports the active transport, remote execution gate, command limits, Nuclei template readiness, and expected binary availability. listActiveScans lists Nmap scans for one engagement; cancelScan needs that engagement ID and a returned scan ID. The server also warns at startup when expected host commands are missing. A missing binary or failed command is a tool error, not evidence that a target is clean. Keep tool output and test limitations with the engagement record.
Nuclei requires an absolute MCP_NUCLEI_TEMPLATES_DIR containing operator-reviewed,
signed HTTP templates. The server does not accept caller-selected template paths.
It selects HTTP templates, excludes Interactsh templates, disables redirects,
headless execution, automatic probing, stdin targets, and update checks. Its
target also needs host-wide authorization, because templates may contact other
ports on that host. Template review and a network egress policy remain necessary:
an HTTP template can specify another destination. The bundled template library
is available for review but is not selected automatically.
Transport and authentication
stdiois the default local transport.httpuses Streamable HTTP at/mcpwith a/healthendpoint. Direct local use binds to127.0.0.1by default.- Legacy
sseis disabled because its shared session cannot isolate clients.
For direct local HTTP use:
MCP_TRANSPORT=http MCP_SERVER_HOST=127.0.0.1 MCP_SERVER_PORT=8000 pentest-mcp
A non-loopback HTTP listener requires MCP_AUTH_ENABLED=true, an exact
MCP_ALLOWED_ORIGINS list, MCP_OIDC_ISSUER, MCP_AUTH_AUDIENCE, and an HTTPS
MCP_PUBLIC_BASE_URL. Issuer and audience are required for authenticated HTTP
even when a reverse proxy publishes a loopback-bound listener. Bearer tokens
must be verified through an OIDC JWKS URL or introspection endpoint. A request
that supplies an Origin header is rejected unless it matches the allowed
list. Put remote access behind TLS and an explicit network policy.
Authenticated HTTP scanner execution has a separate default-off gate:
MCP_REMOTE_EXECUTION_ENABLED=true. Enable it only for a dedicated, trusted
deployment with the engagement's authorization and access policy in place.
When false, authenticated clients cannot launch assessment commands.
Bearer tokens need the read scope for discovery and evidence retrieval,
write for engagement and report changes, and execute for scanners and
command cancellation. Each tool checks its own required scope; batched calls
need every scope they use. The scope names can be mapped to provider-specific
tokens with MCP_AUTH_READ_SCOPE, MCP_AUTH_WRITE_SCOPE, and
MCP_AUTH_EXECUTE_SCOPE. The old MCP_AUTH_SCOPES setting is ignored.
Remote gobuster, ffufScan, and Hydra list inputs may read only wordlists
generated for that token owner or files under an operator-configured absolute
MCP_SHARED_WORDLIST_DIR. Mount a shared directory read-only in Docker. Hash
cracking, host packet capture, and host privilege audit remain local stdio tools.
MCP_TRANSPORT=http
MCP_SERVER_HOST=127.0.0.1
MCP_SERVER_PORT=8000
MCP_AUTH_ENABLED=true
MCP_AUTH_MODE=bearer
MCP_ALLOWED_ORIGINS=https://research.example.com
MCP_PUBLIC_BASE_URL=https://research.example.com
MCP_OIDC_ISSUER=https://issuer.example.com
MCP_OIDC_JWKS_URL=https://issuer.example.com/.well-known/jwks.json
MCP_AUTH_AUDIENCE=pentest-mcp
MCP_AUTH_READ_SCOPE=read
MCP_AUTH_WRITE_SCOPE=write
MCP_AUTH_EXECUTE_SCOPE=execute
MCP_REMOTE_EXECUTION_ENABLED=true
MCP_OIDC_INTROSPECTION_URL can be used instead of JWKS, with MCP_OAUTH_CLIENT_ID and MCP_OAUTH_CLIENT_SECRET when the provider requires them. Legacy MCP_OAUTH_* aliases remain accepted but should be migrated. The Docker HTTP profile always enables authentication, including when it publishes only to loopback.
Operational limits
MCP_COMMAND_TIMEOUT_MSandMCP_COMMAND_OUTPUT_LIMIT_BYTESbound command execution and captured output. A timed-out, nonzero-exit, or truncated command must be reviewed as incomplete. Tracked subprocess failures are recorded with a failed or cancelledoutcomeand appear as such in the report evidence index.- MCP request cancellation and closing an engagement abort active tracked commands. A managed assessment also checks the authoritative parent engagement before every MCP tool dispatch and polls it while Codex runs; closure cancels the container run and closes its worker scope. Scanner subprocesses use the captured scope deadline, including for Nmap, and recheck engagement status immediately before launch.
rawOptionsand scanner features that can override declared targets are restricted, but externally maintained templates and scripts still need operator review.- Reports are analyst-authored; the server does not infer vulnerability severity from an open port or a scanner template match.
- There is no automatic ticket sync, cloud upload, or proof that the declared authorization reference is valid.
Docker
The Compose image below runs the Pentest MCP server. The managed Codex assessment uses a different pinned image and Docker context; follow the container assessment guide for that worker. Its Codex container has bridge networking for model access, while the scanner MCP child runs on the host. Neither side has a destination egress allowlist here, so apply host and VM network policy before client testing.
Docker Compose defaults to a local stdio service with no published port. It runs as an unprivileged user, drops Linux capabilities, and persists scan records, reports, and the scan journal in the host data directory. Prepare that private directory before starting the container:
cp .env.example .env
mkdir -p .pentest-data
chmod 700 .pentest-data
docker compose run --build --rm -T pentest-mcp
The host directory is PENTEST_DATA_HOST_DIR (default ./.pentest-data),
mounted at the container's PENTEST_DATA_DIR=/var/lib/pentest-mcp. On Linux,
make the host directory writable by container UID 1000 before the first run
(for example, sudo chown 1000:1000 .pentest-data). Compose will refuse to
auto-create a missing bind path. Protect and back up this directory as client
evidence; it is excluded from Git and the Docker build context.
HTTP access
The HTTP profile is opt-in and publishes to 127.0.0.1 by default. It always
enables bearer authentication. In .env, configure exact
MCP_ALLOWED_ORIGINS, MCP_OIDC_ISSUER, MCP_AUTH_AUDIENCE, an HTTPS
MCP_PUBLIC_BASE_URL, and either MCP_OIDC_JWKS_URL or
MCP_OIDC_INTROSPECTION_URL. Set OAuth client credentials if introspection
requires them. The server fails startup if these listener and verifier
requirements are missing. Keep MCP_REMOTE_EXECUTION_ENABLED=false until
this is a dedicated trusted scanner deployment, then explicitly set it to
true to permit authenticated scanner calls.
chmod 600 .env
docker compose --profile http up --build pentest-mcp-http
The endpoint is http://127.0.0.1:8000/mcp unless you change
MCP_SERVER_PORT. Compose uses that same port inside and outside the
container. Compose binds the service to 0.0.0.0 inside its network namespace,
so the HTTPS public base URL and identity settings are required even when the
published host port remains on loopback. For remote clients, keep the Compose
listener on loopback and put a TLS reverse proxy with access controls in front
of it. Set
MCP_BIND_ADDRESS to a non-loopback address only when that address and its
firewall policy are intentional; bearer tokens must travel over TLS.
Network capture and custom wordlists
The default container can scan targets on its Docker network but cannot capture
host interface traffic. On a Linux host, the separate capture profile opts in
to host networking plus NET_RAW and NET_ADMIN for tcpdump:
docker compose --profile capture run --build --rm -T pentest-mcp-capture
That profile can observe the host network namespace and should be used only when the engagement allows packet capture. Docker Desktop does not provide the same host interface access. To use private wordlists without adding them to the image, attach a read-only host directory to a one-off run:
docker compose run --rm -T --volume /absolute/wordlists:/app/custom-wordlists:ro pentest-mcp
To enable reviewed, signed Nuclei HTTP templates in Compose, set
MCP_NUCLEI_TEMPLATES_HOST_DIR in .env to an absolute host directory and use
the opt-in override file. It mounts that directory read-only at
/reviewed-nuclei:
docker compose -f docker-compose.yml -f docker-compose.nuclei.yml run --build --rm -T pentest-mcp
The Docker image installs:
nmap,john,hashcat,gobuster,nikto,ffuf,hydra,sqlmap,tcpdumpsubfinder,httpx+httpx-toolkitalias,nuclei
Required Host Tools (non-Docker runs)
Ensure the binaries are in PATH:
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.
MCP assessment contract
The October 2026 server declares @modelcontextprotocol/sdk@^1.32.2 and exposes the tool inventory above over stdio or authenticated Streamable HTTP. Tools have Zod schemas and MCP annotations. An assessment CLI should load the entire catalog, then select a method based on the engagement plan, available binaries, and observed results. It must treat tool output and target content as untrusted data. An MCP transport connection is not itself evidence of a test: the durable record and matching scope decision are the acceptance evidence.
The server's target gate checks declared inputs before execution. It cannot prove that a third-party tool will never make secondary requests. Keep the agent's OS identity, filesystem mounts, credentials, outbound network policy, and the scanner's own configuration aligned with the signed scope. For a client engagement, separate the scope author, assessment agent, and report reviewer so the agent does not inherit repository-building conversations or another client's context.
Keep client-specific deployment inventories, authorization gaps, host details, and evidence locations in private engagement storage outside the public repository and model-builder context. The Daybreak and Glasswing note identifies current program and client-work access requirements. An API key or CLI model label by itself is not a grant to run a customer assessment.
Security notice
Use the server only on systems covered by explicit written authorization. Keep evidence and client data private, and validate findings before reporting them.
Comments
New to MCP?
From what the protocol is to installing your first server, these answers cover most first questions.
An open protocol that defines how AI applications connect to external tools and data in a uniform way. Clients talk to the model; MCP servers provide tools, resources and prompt templates. They exchange standard messages, so one server can be reused by many clients.