Atlas / MCP servers / dtkmn / mcp-zap-server

mcp-zap-serverCAUTION

mcp/dtkmn/mcp-zap-server

Give AI agents a safe, self-hosted ZAP operator for guided web security scans, findings, reports, and production guardrails.

Verdict
CAUTION
Grade
D
Trust score
61 /100
Exposed tools
—
Transport
streamable-http
License
Apache-2.0
Stars
67
01

Overview

From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.

MCP ZAP Server

Give AI agents a safe, self-hosted ZAP operator for guided web security scans, findings, reports, and production guardrails.

Note This project is not affiliated with or endorsed by the ZAP project. It is an independent implementation.

mcp-zap-server exposes ZAP through MCP over streamable HTTP so agentic tools can run operator-controlled security workflows without brittle glue scripts or unsafe scanner access.

Use it when you want:

  • safe agentic scanning with guided defaults for spider, active scan, passive scan, API imports, findings, and reports
  • operator control through API-key or JWT auth, tool scopes, runtime policy bundles, rate limits, and audit events
  • self-hosted deployment with Docker Compose for local adoption and Helm for Kubernetes
  • expert ZAP access when you intentionally need lower-level ZAP context, user, scan, and report controls

Full documentation: danieltse.org/mcp-zap-server

Watch the demo: browser demo or YouTube

Quick Start

Prerequisites:

  • Docker 20.10+
  • Docker Compose v2 (`docker compo
Read from source at commit 0f0d122d2f46OBSERVED · 2026-10-07
02

Connect

Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.

claude-code (oci)
claude mcp add mcp-zap-server:v0.15.0 --env ZAP_API_KEY=${ZAP_API_KEY} --env MCP_API_KEY=${MCP_API_KEY} --env ZAP_API_KEY=${ZAP_API_KEY} --env MCP_API_KEY=${MCP_API_KEY} -- docker run -i --rm ghcr.io/dtkmn/mcp-zap-server:v0.15.0:None
claude-code (oci)
claude mcp add mcp-zap-server:v0.15.0 --env ZAP_API_KEY=${ZAP_API_KEY} --env MCP_API_KEY=${MCP_API_KEY} --env ZAP_API_KEY=${ZAP_API_KEY} --env MCP_API_KEY=${MCP_API_KEY} -- docker run -i --rm docker.io/dtkmn/mcp-zap-server:v0.15.0:None
03

Trust audit

CAUTIONgrade D · trust 61/100 Install with care. The audit found things worth knowing before you trust its output.

LayerWhat it checksResult
L0Provenance & inventoryWARN
L1Static analysis of the codeWARN
L2Instruction surface (what it tells the agent)PASS
L3Class-specific surfacePASS
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
declared (1 observation(s))
Network
declared (4 observation(s))
Shell
none-observed
Dependencies
not all pinned
Secrets in source
found

Findings (25)

MEDIUMInventory / provenance · inv.binary · CWE-1104
gradle/wrapper/gradle-wrapper.jar
gradle-wrapper.jar
Why it matters. a compiled or binary member cannot be reviewed from source
Fix. ship source, or explain the binary in the README
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
Dockerfile:62
CMD ["/usr/local/bin/http-healthcheck", "http://127.0.0.1:7456/actuator/health"]
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
docs/src/content/docs/security-modes/examples.md:192
api_key="your-generated-mcp-api-key",
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
src/test/java/mcp/server/zap/core/configuration/JwtRevocationBackendOutageIntegrationTest.java:44
private static final String API_KEY = "synthetic-outage-api-key";
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
src/test/java/mcp/server/zap/core/configuration/McpStreamableHttpProtocolRegressionTest.java:45
private static final String API_KEY = "claude-desktop-api-key";
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
src/test/java/mcp/server/zap/core/service/JwtRevocationLifetimeTest.java:53
private static final String SECRET = "synthetic-lifetime-secret-at-least-32-characters";
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
src/test/resources/client-spider/form-login.py:41
token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9." + payload.decode().rstrip("=") + "." + token_urlsafe(24)
LOWInventory / provenance · inv.hidden_file · CWE-1104
helm/mcp-zap-server/.helmignore
.helmignore
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
docs/scripts/sync-docs.mjs:15
'../../examples/cursor/mcp.json': 'https://github.com/dtkmn/mcp-zap-server/blob/main/examples/cursor/mcp.json',
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
docs/scripts/sync-docs.mjs:24
'../../../examples/aws-ec2/': 'https://github.com/dtkmn/mcp-zap-server/tree/main/examples/aws-ec2',
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
docs/scripts/sync-docs.mjs:25
'../../../helm/mcp-zap-server/README.md': 'https://github.com/dtkmn/mcp-zap-server/blob/main/helm/mcp-zap-server/README.md',
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
tests/python/test_mcp_zap_gate.py:115
"/zap/wrk/../../tmp/secret.txt",
LOWNetwork egress · net.metadata_ip · CWE-200, CWE-319
docs/operator/runbooks/AWS_EC2_COMPOSE_GUIDE.md:313
checks = [('smoke-target', 8080, True), ('169.254.169.254', 80, False),
Why it matters. cloud metadata endpoint: the classic SSRF credential grab
LOWNetwork egress · net.metadata_ip · CWE-200, CWE-319
src/test/java/mcp/server/zap/core/service/AutomationPlanServiceDockerTest.java:168
+ "jobs: [{type: requestor, requests: [{url: 'http://169.254.169.254/'}]}]\n");
Why it matters. cloud metadata endpoint: the classic SSRF credential grab
LOWNetwork egress · net.metadata_ip · CWE-200, CWE-319
src/test/java/mcp/server/zap/core/service/AutomationPlanTargetPolicyTest.java:77
ENV + "jobs: [{type: requestor, requests: [{url: 'http://169.254.169.254/'}]}]",
Why it matters. cloud metadata endpoint: the classic SSRF credential grab
LOWNetwork egress · net.metadata_ip · CWE-200, CWE-319
src/test/java/mcp/server/zap/core/service/AutomationPlanTargetPolicyTest.java:109
ENV + "requests: &requests [{url: 'http://169.254.169.254/'}]\njobs: [{type: requestor, requests: *requests}]",
Why it matters. cloud metadata endpoint: the classic SSRF credential grab
LOWNetwork egress · net.metadata_ip · CWE-200, CWE-319
src/test/java/mcp/server/zap/core/service/OpenApiTargetPolicyTest.java:46
"http://169.254.169.254/api", "http://0.0.0.0/api", "http://224.0.0.1/api",
Why it matters. cloud metadata endpoint: the classic SSRF credential grab
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
.github/actions/zap-security-gate/mcp_zap_gate.py:1089
parser.add_argument("--zap-proxy-url", default="http://127.0.0.1:8090")
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
.github/actions/zap-security-gate/run-gate.sh:215
"--zap-proxy-url" "${INPUT_ZAP_PROXY_URL:-http://127.0.0.1:8090}"
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
docs/operator/runbooks/AWS_EC2_COMPOSE_GUIDE.md:357
Your client endpoint is now **`http://127.0.0.1:17456/mcp`**. Configure your MCP
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
docs/src/content/docs/scanning/client-spider.md:110
'http://127.0.0.1:8090/JSON/core/action/accessUrl/' \
LOWSupply chain · supply.unpinned · CWE-829, CWE-1357
docs/package.json
@astrojs/sitemap, @astrojs/starlight, @fontsource/ibm-plex-mono, @fontsource/rajdhani, astro, sharp, @astrojs/check, typescript
Why it matters. 8 dependency range(s) float
Fix. pin exact versions or ship a lockfile
LOWPrompt injection · prompt.credential_read · CWE-94, CWE-1427
docs/releases/RELEASE_NOTES_0.10.0.md:52
- Normal unauthenticated scans and MCP access authentication through API keys or JWT remain supported.
Why it matters. asks the agent to read credentials
LOWPrompt injection · prompt.credential_read · CWE-94, CWE-1427
docs/src/content/docs/getting-started/authentication-quick-start.md:63
use Spring configuration; the application does not automatically read `.env`.
Why it matters. asks the agent to read credentials
LOWPrompt injection · prompt.credential_read · CWE-94, CWE-1427
docs/src/content/docs/getting-started/authentication-quick-start.md:99
No access credential is required. Never expose this mode to other users or
Why it matters. asks the agent to read credentials

Gates applied: no_behavioural_pass.

Audited 2026-10-07 · audit v0.4.1 · source sha 0f0d122d2f46full audit observations/trust-audit/mcp-server/dtkmn__mcp-zap-server.json · Report an issue / request a re-scan
04

Audit history

Every audit this server has had. A grade with a past is a grade somebody is still checking.

DateSourceVerdictGradeScoreChange
2026-10-070f0d122d2f46CAUTIOND61first audit
05

Questions

What is the mcp-zap-server MCP server?

Give AI agents a safe, self-hosted ZAP operator for guided web security scans, findings, reports, and production guardrails.

Is mcp-zap-server safe to connect to an agent?

With care. The audit graded it D (61/100) and found 25 things worth knowing before you trust this server, listed below with the exact line each was found on.

What credentials does mcp-zap-server need?

It reads MCP_API_KEY and ZAP_API_KEY from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.

How does mcp-zap-server run?

It speaks streamable-http, so it runs as a service you connect to over the network. It is published on npm as docs at 0.0.1.

How current is this page?

The grade is for one exact copy of the source (0f0d122d2f46), read on 2026-10-07. The repository is watched and re-audited when it changes.

Advertisement