OWASP ZAP MCP Server
๐ท๏ธ OWASP ZAP MCP Server
Drive the world's most popular web app scanner from your AI assistant.
Point Claude, Cursor, or any MCP client at OWASP ZAP and run real crawls, authenticated scans, and vulnerability triage โ through 67 curated, safety-gated tools built straight from the official ZAP API.
Authorized use only. Active scanning sends real attack payloads. Run it only against systems you have explicit, written permission to test. This server refuses cloud-metadata targets and can be pinned to an engagement scope โ but the responsibility is yours.
โจ Why this exists
Talking to ZAP's raw REST API from an LLM is clumsy and risky: hundreds of endpoints, no guardrails, and it's easy to point an attack at the wrong host. This project gives your AI assistant a small, opinionated, safe surface:
๐ Safe by design
Cloud metadata endpoints (
169.254.169.254) are always refusedOptional scope allowlist + private-range blocking
Control port bound to localhost by default
๐ Real authenticated scanning
Full workflow: context โ auth method โ indicators โ user โ forced-user
scan_as_userfor spider, AJAX spider, and active scanThe thing most ZAP wrappers skip entirely
๐งฑ Reliable under load
One pooled async client, bounded retries with backoff
Typed errors + a uniform result envelope
A single bad call can never crash the server
๐ข Production posture
Fail-closed config, secrets never logged
Pinned, non-root, health-gated containers
Green CI on every push
๐๏ธ Architecture
flowchart LR
A["๐ค LLM client<br/>(Claude ยท Cursor)"] -->|MCP / Streamable HTTP<br/>127.0.0.1:8000| B
B["๐ท๏ธ zap-mcp-server<br/>Python 3.12 ยท 67 tools<br/>target policy ยท pooled client"] -->|internal docker net<br/>http://zap:8080| C
C["๐ก๏ธ zap-daemon<br/>OWASP ZAP 2.17.0<br/>API restricted to private ranges"]
B -.->|refuses metadata / out-of-scope| X["โ blocked targets"]The MCP server reaches ZAP over the internal Docker network.
Both ports are published on
127.0.0.1only โ nothing is world-exposed.Every state-changing ZAP action requires the API key.
๐ Quick start
# 1. Set your secret (never committed)
cp .env.example .env
# edit .env -> ZAP_API_KEY=<long-random-value>
# 2. Launch (ZAP starts, becomes healthy, then the MCP server starts)
docker compose up -d --build
# 3. Confirm
docker compose ps # both services: healthy
docker compose logs -f mcp-server # "Registered 67 MCP tools"Then point your MCP client at it:
{
"mcpServers": {
"owasp-zap": { "url": "http://localhost:8000/mcp" }
}
}๐ Authenticated scanning in 6 steps
The capability most ZAP wrappers skip โ scan behind a login:
1. create_context โโโโโโโโโโโโโโบ scope it (include app, exclude /logout)
2. set_authentication_method โโโบ e.g. formBasedAuthentication
3. set_logged_in / out_indicator
4. new_user โ set_user_credentials โ set_user_enabled
5. set_forced_user (+ mode) โโโบ keeps the session alive during scans
6. spider_scan_as_user โ active_scan_as_userPrefer repeatable runs? Drive the whole pipeline with a ZAP
Automation Framework
plan via zap_run_automation_plan.
๐งฐ The 67 tools
Tools marked ๐ฏ are gated by the target-authorization policy. Every tool returns
a uniform envelope: {"status":"success",...} or
{"status":"error","code":...,"retryable":...}.
Group | Tools |
Core & health |
|
Spider |
|
AJAX spider |
|
Group | Tools |
Active scan |
|
Passive scan |
|
Findings & triage |
|
Group | Tools |
Context & scope |
|
Authentication |
|
Users |
|
Forced user |
|
Imports & automation |
|
Reports |
|
All tool names are prefixed with
zap_(e.g.zap_active_scan).
๐ก๏ธ Security model
Control | Behavior |
API key | Required. Server won't start without |
Metadata block |
|
Scope allowlist |
|
Private-range block |
|
Localhost binding | MCP |
Response caps | Large lists are bounded ( |
The MCP endpoint hasno built-in auth and can launch attacks. To expose it
beyond localhost, set MCP_BIND=0.0.0.0 and front it with an
authenticating reverse proxy.
Variable | Default | Description |
| (required) | Must match the ZAP daemon's key. |
|
| ZAP API base URL. |
| (empty) | Comma-separated allowed host suffixes. |
|
| Refuse private/loopback targets. |
|
| Host interface the MCP port binds to. |
|
| HTTP timeouts (s). |
|
| Retry policy. |
|
| Cap on returned list items. |
๐งช Development
python -m venv .venv && source .venv/bin/activate
pip install -r requirements-dev.txt
pytest -q # policy, config, error envelope, tool behaviorCI runs py_compile + pytest on every push to main.
โ๏ธ Responsible use
Active scanning is an attack. In most jurisdictions, testing systems without permission is illegal. Before you scan:
โ Confirm the target is in scope for an engagement you're authorized to run
โ Pin scope with
ZAP_TARGET_ALLOWLIST; considerZAP_BLOCK_PRIVATE_TARGETS=trueโ Use a long random
ZAP_API_KEY; never commit.env
Cloud metadata endpoints are always refused and this cannot be overridden.
๐ License
MIT ยฉ Neeraj829784 โ swap the LICENSE file for Apache-2.0 if you
want an explicit patent grant.