Skip to main content

Unified MCP Server for Web Security — 39 tools for autonomous pentesting

Project description

nodriver-proxy-mcp

Give your AI agent a browser, a proxy, and a Python sandbox.
It navigates like a human, intercepts like Burp, and codes its own exploits on the fly.

Python 3.10+ MCP MIT License

한국어


Why this exists

Existing security MCP servers give the AI read-only access to traffic or just wrap CLI tools. This one gives full, autonomous control: the agent opens a browser that bypasses bot detection, captures every request through a MITM proxy, and when the built-in tools aren't enough, it writes and runs its own Python to chain everything together.

"Scan target.com for IDOR vulnerabilities"

  1. Agent starts proxy + browser
  2. Navigates to login page, types credentials, clicks submit
  3. Captures the auth flow, extracts the JWT
  4. Replays API requests with different user IDs
  5. Writes a Python script to automate the full IDOR check
  6. Reports which endpoints are vulnerable

No human touches the keyboard. The agent does it all through 39 MCP tools.


Why pentesters should care

What can it do that Burp / ZAP can't?

Burp Suite / ZAP nodriver-proxy-mcp
Who drives? You click manually AI does everything autonomously
Bot detection Blocked by Cloudflare, DataDome, etc. Bypasses automatically (nodriver)
Scripting Write extensions / macros yourself AI writes Python scripts on the fly, with access to all 38 tools via SDK
Client-side data Not visible Reads localStorage, sessionStorage, JS console, DOM hidden inputs
Can they work together? Yes — chain through Burp with upstream="localhost:8080"

What can it do that other security MCP servers can't?

Most security MCP servers just wrap curl or read-only traffic viewers. This one has:

  • Real mitmproxy — full traffic recording, replay, fuzzing, interception rules, session variables. Not a simplified HTTP client.
  • Two ways to modify traffic — browser-level (instant, CDP Fetch) or proxy-level (system-wide, all HTTP clients). Other MCPs offer neither.
  • Code-mode with SDK — the AI writes a Python script that runs in a sandbox, calling 29 tools in loops with asyncio. Race conditions, blind SQLi, and brute-force that would take thousands of MCP round-trips finish in seconds.

What it's great at

Use case How the agent handles it
IDOR Opens two browser sessions (victim + attacker), extracts tokens, replays requests swapping user IDs in a loop
XSS Types payloads into inputs, clicks submit, checks if alert() dialog fires. Inspects DOM for injection points.
Auth bypass Scans traffic to detect JWT / API key / session cookie patterns, extracts tokens, replays with modifications
API testing Captures all API calls, searches by keyword/status, replays with regex replacement, fuzzes with anomaly detection
Race conditions Code-mode sends 50+ concurrent requests via asyncio.gather() with precise timing
Blind SQLi Code-mode runs binary search extraction — hundreds of conditional requests with logic between each one
CSP bypass Intercepts responses at browser level, strips or modifies Content-Security-Policy header before Chrome enforces it

Architecture

Overall system

graph TB
    Agent["🤖 AI Agent<br/>(Claude, Cursor, etc.)"]

    subgraph MCP["MCP Server Process"]
        direction LR
        PT["Proxy Tools<br/>18 tools"]
        BT["Browser Tools<br/>20 tools"]
        CT["Code-mode<br/>1 tool"]
    end

    subgraph Proxy["mitmproxy :8082"]
        Addon["Addon Script<br/>record + intercept"]
        DB[("SQLite<br/>traffic.db")]
        Addon -->|write| DB
    end

    subgraph BrowserSession["BrowserDaemon (per session)"]
        Chrome["Chrome<br/>nodriver (anti-bot)"]
        Fetch["CDP Fetch<br/>intercept hooks"]
        Chrome --- Fetch
    end

    subgraph Sandbox["Code-mode Sandbox"]
        Script["AI-generated<br/>Python script"]
        SDK["NdpSDK<br/>29 methods"]
        Script --> SDK
    end

    Target[("🎯 Target")]

    Agent <-->|"stdio JSON-RPC"| MCP
    PT --> Proxy
    BT -->|"TCP IPC<br/>JSON-RPC"| BrowserSession
    CT -->|"subprocess<br/>fork+exec"| Sandbox

    Chrome -->|"all traffic routed"| Proxy
    Proxy <-->|"HTTP/S"| Target

    SDK -.->|"direct read/write"| DB
    SDK -.->|"TCP IPC"| BrowserSession

Two interception layers

graph LR
    subgraph Layer1["Layer 1 — CDP Fetch (instant)"]
        direction LR
        C1["Chrome"] -->|"request"| F1["Fetch API<br/>inject header / block"]
        F1 -->|"modified"| P1["→ mitmproxy"]
        P2["mitmproxy →"] -->|"response"| F2["Fetch API<br/>replace body / block"]
        F2 -->|"modified"| C2["→ Chrome"]
    end

    subgraph Layer2["Layer 2 — mitmproxy (system-wide)"]
        direction LR
        Any["Any HTTP client"] --> M1["mitmproxy<br/>inject header / replace body / block"]
        M1 --> T2["→ Target"]
    end

    style Layer1 fill:#1a1a2e,stroke:#3fb950,color:#e6edf3
    style Layer2 fill:#1a1a2e,stroke:#58a6ff,color:#e6edf3

CDP Fetch = browser-only, instant, per-session. mitmproxy rules = all traffic, ~5s cache delay, system-wide.

Process lifecycle

Process Parent IPC method Auto-cleanup
mitmproxy MCP server SQLite (shared file) Watchdog thread kills on parent death; stderr drain prevents pipe hang
BrowserDaemon MCP server TCP JSON-RPC (dynamic port) Parent PID watch → IPC close → SIGTERM → SIGKILL
Chrome BrowserDaemon CDP (Chrome DevTools Protocol) browser.stop() on daemon exit
Code-mode script MCP server Env vars (ports, sessions) Job Object / killpg; 256MB RAM, 60s CPU

NdpSDK — Code-mode Python SDK

NdpSDK is a Python wrapper that exposes the same 38 tools (proxy + browser) as async methods, designed for use inside execute_security_code. When the AI needs loops, concurrency, or multi-step logic that would be impractical as individual MCP calls, it writes a script using NdpSDK instead.

from nodriver_proxy_mcp.sdk import NdpSDK
import asyncio

async def main():
    sdk = NdpSDK()  # auto-discovers running proxy + browser sessions

    flows = await sdk.get_traffic_summary(limit=20)
    await sdk.browser_go("https://target.com/admin")

    # Loops — this is why NdpSDK exists
    for uid in range(1, 100):
        resp = await sdk.replay_flow(
            flow_id,
            replacements=[{"regex": r"/users/\d+", "replacement": f"/users/{uid}"}]
        )
        if resp["status_code"] == 200:
            print(f"IDOR: /users/{uid}")

asyncio.run(main())

Quick start

1. Install

pip install nodriver-proxy-mcp

Or from source:

git clone https://github.com/BobongKu/nodriver-proxy-mcp.git
cd nodriver-proxy-mcp
pip install .

2. Add to your AI agent

Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "nodriver-proxy-mcp": {
      "command": "nodriver-proxy-mcp"
    }
  }
}

Claude Code (settings.json or .claude/settings.local.json):

{
  "mcpServers": {
    "nodriver-proxy-mcp": {
      "command": "nodriver-proxy-mcp"
    }
  }
}

Cursor / other MCP clients (mcp_config.json):

{
  "mcpServers": {
    "nodriver-proxy-mcp": {
      "command": "nodriver-proxy-mcp"
    }
  }
}

3. Use it

Just tell your AI agent what to do. The tools are self-descriptive — the agent picks the right ones automatically.


All 39 tools

Proxy (18)

Tool Purpose
manage_proxy Start/stop mitmproxy. Chain to Burp via upstream. GUI via ui=True.
proxy_status Check running state, port, PID
set_scope Limit recording to specific domains
get_traffic_summary Paginated flow list with IDs, URLs, methods, status codes
inspect_flow Full request/response details — headers, body, metadata
search_traffic Filter by keyword, domain, method, status code
extract_from_flow Pull values via JSONPath, regex, or CSS selectors
extract_session_variable Save a value for {{placeholder}} reuse in replay
list_session_variables Show all extracted variables
generate_curl Export a flow as a copy-paste curl command
replay_flow Resend with regex replacements + {{var}} substitution (like Burp Repeater)
send_raw_request Craft arbitrary HTTP requests from raw text (SSRF-protected)
add_interception_rule Live proxy traffic manipulation: inject headers, replace body, block
list_interception_rules Show active proxy rules
remove_interception_rule Delete a proxy rule by ID
detect_auth_pattern Auto-detect JWT, Bearer, API key, session cookie, CSRF, OAuth2
fuzz_endpoint Concurrent fuzzing with baseline anomaly detection
clear_traffic Wipe the traffic database

Browser (20)

Tool Purpose
browser_open / browser_close Launch or kill a Chrome session (anti-bot bypass, headless by default)
browser_list_sessions Active sessions with PID, ports, uptime
browser_list_tabs Tabs in a session
browser_go / browser_back Navigate, wait for page load, SPA support via wait_for
browser_click Click by CSS selector or visible text. Returns JS alert dialogs (XSS detection).
browser_type Type into inputs — login forms, search boxes, payload injection
browser_get_dom Security-focused DOM: forms, scripts, iframes, comments, event handlers, data-* attributes
browser_get_text Text content from any CSS selector
browser_get_storage Dump localStorage + sessionStorage (invisible to proxy)
browser_get_console JS console output — stack traces, debug URLs, CSP violations
browser_screenshot Capture page as PNG — bot challenges, evidence, state verification
browser_set_cookie Set cookies via CDP (supports httpOnly — unlike document.cookie)
browser_js Execute arbitrary JavaScript in page context
browser_wait Wait for element/text to appear (SPA/AJAX support)
browser_intercept_request CDP Fetch: inject headers, block outgoing requests (instant)
browser_intercept_response CDP Fetch: replace response body, block responses (instant)
browser_intercept_disable Turn off all CDP Fetch interception
browser_list_intercept_rules Show active CDP Fetch rules

Code-mode (1)

Tool Purpose
execute_security_code Run AI-generated Python with NdpSDK — programmatic access to all 38 other tools. Sandboxed.

Burp Suite integration

Use upstream to chain mitmproxy through Burp for manual analysis alongside AI automation:

manage_proxy(action="start", upstream="localhost:8080")

Traffic flows: Chrome --> mitmproxy (:8082) --> Burp Suite (:8080) --> Target

Both tools see the same traffic. The AI automates; you analyze in Burp when you need to.


Workflows

Recon — browse, capture, analyze

manage_proxy(action="start")
set_scope(allowed_domains=["target.com", "api.target.com"])
browser_open(proxy_port=8082)
browser_go(url="https://target.com")

# Client-side data invisible to proxy
browser_get_dom()                    # forms, hidden inputs, CSRF tokens
browser_get_storage()                # localStorage / sessionStorage tokens
browser_get_console()                # debug messages, internal URLs

# Traffic analysis
get_traffic_summary()                # all captured requests
detect_auth_pattern()                # JWT, cookies, API keys

IDOR — two sessions, token swap

browser_open(session_name="victim", proxy_port=8082)
browser_go(url="https://target.com/login", session_name="victim")
# ... login as victim ...

browser_open(session_name="attacker", proxy_port=8082)
browser_go(url="https://target.com/login", session_name="attacker")
# ... login as attacker ...

extract_session_variable(flow_id="...", regex='token":"([^"]+)', name="victim_token")
replay_flow(flow_id="...", replacements=[{"regex": "victim_token_value", "replacement": "attacker_token_value"}])

XSS — payload injection + alert detection

browser_go(url="https://target.com/search?q=<script>alert(document.domain)</script>")
browser_click(selector="#search-btn")
# If XSS fires, the alert() dialog message is returned in the click result
browser_get_console()                # CSP violations

Business logic — price manipulation, coupon reuse, workflow bypass

# Capture a normal checkout flow
browser_go(url="https://target.com/checkout")
browser_click(selector="#place-order")

# Find the price parameter in traffic
search_traffic(query="price")
inspect_flow(flow_id="...")

# Replay with modified price / reused coupon code / skipped step
replay_flow(flow_id="...", replacements=[{"regex": '"price":99.99', "replacement": '"price":0.01'}])

# Or use code-mode for multi-step logic abuse
execute_security_code(script_content="""
# Apply same coupon 50 times, check if discount stacks
for i in range(50):
    resp = await sdk.replay_flow(coupon_flow_id)
    print(f"Attempt {i}: status={resp['status_code']}")
""", approved=True)

API fuzzing — automated anomaly detection

fuzz_endpoint(
    flow_id="abc",
    payloads=["' OR 1=1--", "<script>alert(1)</script>", "../../../etc/passwd"],
    target_pattern="FUZZ"
)
# Measures baseline, flags status code / length / latency anomalies

Troubleshooting

Problem Fix
Browser won't launch Install Chrome/Chromium. nodriver requires a real Chrome binary.
SSL certificate errors Trust the mitmproxy CA: ~/.mitmproxy/mitmproxy-ca-cert.pem
Port already in use manage_proxy(port=XXXX) — or restart, orphaned processes are auto-killed
Tools not showing Restart your Claude Code / Cursor session to reload the MCP server
uvx doesn't work Don't use uvx. Clone the repo and use uv run --directory instead.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nodriver_proxy_mcp-1.0.0.tar.gz (429.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nodriver_proxy_mcp-1.0.0-py3-none-any.whl (65.5 kB view details)

Uploaded Python 3

File details

Details for the file nodriver_proxy_mcp-1.0.0.tar.gz.

File metadata

  • Download URL: nodriver_proxy_mcp-1.0.0.tar.gz
  • Upload date:
  • Size: 429.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for nodriver_proxy_mcp-1.0.0.tar.gz
Algorithm Hash digest
SHA256 4bbe4e7bf5825f8376a951d74ffe618a83afc133b887ed72fbeeacb6c0cff318
MD5 783a27c210cb89bf500f4c2673d3b00e
BLAKE2b-256 f96728d263f4983c8a84795b1f90b8f90c635cebd44559af59b5a3cad1f5f8d4

See more details on using hashes here.

File details

Details for the file nodriver_proxy_mcp-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for nodriver_proxy_mcp-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 336fe13770b2ebdb23c6e5d8ed0adeeda4ae906c64f1028a0a729f6593bc9170
MD5 5eefe3c0a5bbd341d003684fb000704d
BLAKE2b-256 169dca7e9f17e5bc1184db27647e6e08595217c65a46f377540d740f98b30c94

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page