BurpMCP-Ultra
The most powerful MCP server for Burp Suite Professional.
Drop a single JAR into Burp, connect Claude Code (or any MCP client), and drive every part of Burp Suite programmatically through AI agents.
150 Tools • 8 Resources • 17 Event Types • Real-time Dashboard • Hardened Localhost Security
Quick Start • Tools • Features • Security • Dashboard • Setup Guides • Contact
BurpMCP-Ultra is a native Kotlin Burp Suite extension with an embedded MCP (Model Context Protocol) server. It exposes Burp's Montoya API as 150 structured tools over a token-secured local SSE transport, so an AI agent can run proxy history analysis, active scans, fuzzing, race conditions, OOB testing, custom scan checks, and guided exploitation — all from natural language.
Why BurpMCP-Ultra?
Competitor counts are indicative, based on each project's public tool list.
Quick Start
1. Build
git clone https://github.com/Cy-S3c/BurpMCP-Ultra.git
cd BurpMCP-Ultra
./gradlew shadowJar
Output: build/libs/burpmcp-ultra-2.3.1.jar (~13 MB). A JDK 17–21 must be installed —
see Building from Source. Pre-built JARs are on the
Releases page.
2. Load into Burp
- Burp Suite Pro → Extensions → Add
- Select the JAR
- The BurpMCP-Ultra tab appears with a green "Running" status and your connection token
3. Connect Claude Code
{
"mcpServers": {
"burp": {
"type": "sse",
"url": "http://127.0.0.1:9876/",
"headers": {
"Authorization": "Bearer PASTE_TOKEN_FROM_SERVER_TAB"
}
}
}
}
Add to ~/.claude.json or your project's .mcp.json.
⚠️ The token is required, and the endpoint is the root path
/— not/sse. Copy the token from the Server tab of the BurpMCP-Ultra panel in Burp. Without it the server returns401, and clients like Claude Code then fall back to OAuth discovery and fail withSDK auth failed: HTTP 404: Invalid OAuth error response.
💡 MCP client can't set headers? Use the token-in-path URL — no
headersblock needed (GitHub issue #11). Copy it with "Copy No-Headers Config" on the Server tab:{ "mcpServers": { "burp": { "type": "sse", "url": "http://127.0.0.1:9876/PASTE_TOKEN_FROM_SERVER_TAB/" } } }Keep the trailing slash — it is what makes the token survive onto the SSE back-channel. A
?token=…query does not work for MCP: the SDK advertises its POST endpoint as the relative reference?sessionId=…, which per RFC 3986 §5.3 replaces the query (so the token is dropped and every message401s) while preserving the path. Note the token becomes part of the URL, so prefer the header form when your client supports it.
4. Open Dashboard
Browse to http://127.0.0.1:9878 for the real-time web dashboard.
Tools
150 MCP tools across 37 categories. Names are stable; the authoritative count is
server.tools.size, surfaced in the Server tab.
Proxy (13)
HTTP (13)
Scanner (13)
Collaborator (7)
Intruder & Repeater (4)
WebSocket (7)
Offensive & Recon (11)
Offensive tools that issue live requests are scope-gated (see Security).
Analysis (7)
Advanced Analysis (3)
Utilities (12)
Custom Scan Checks — BCheck (5) + Script (5)
Scope & Sitemap (8)
Config & Burp (16)
Platform (25)
Resources (8)
Read-only MCP resources an agent can fetch without a tool call:
burp://proxy/history · burp://proxy/websocket/history · burp://scanner/issues ·
burp://sitemap · burp://scope · burp://config/project · burp://config/user ·
burp://organizer/items
Highlight Features
Guided Injection Probe
injection_probe(
request: "GET /item?id=FUZZ HTTP/1.1\r\nHost: shop.com\r\n\r\n",
host: "shop.com", port: 443,
classes: ["sqli", "ssti", "lfi"] # optional; default all
)
Marks the injection point with FUZZ, then confirms vulnerabilities with deterministic
oracles — SQL error fingerprints, time-delay analysis, template math-evaluation
(1337*1337 → 1787569), and file-content markers — returning only confirmed findings with
the triggering payload. For blind/OOB classes, pair collaborator_* with http_fuzz.
JWT Attacks
jwt_attack(token: "eyJ...", mode: "crack", wordlist: ["secret", "changeme", ...])
alg:none forgery, RS→HS algorithm-confusion forging, weak-secret dictionary cracking,
and full structural analysis.
Access-Control Sweep
auth_diff / access_control_sweep
request: "GET /api/users/1 HTTP/1.1\r\nHost: api.com\r\n\r\n",
auth_levels: [
{"name": "admin", "header_name": "Authorization", "header_value": "Bearer admin"},
{"name": "user", "header_name": "Authorization", "header_value": "Bearer user"},
{"name": "none"}
]
Replays the same request(s) across identities, diffs the responses, and flags IDOR, privilege escalation, and missing authorization.
Race Condition Testing
http_race(request: "POST /api/transfer HTTP/1.1\r\nHost: bank.com\r\n\r\n{\"amount\":100}",
host: "bank.com", port: 443, count: 20)
Fires 20 identical requests simultaneously via Burp's parallel engine and analyzes status/length distributions to detect TOCTOU, double-spend, and limit-bypass bugs.
Inline Fuzzer (3 modes)
# FUZZ keyword
http_fuzz(request: "GET /api?id=FUZZ HTTP/1.1\r\nHost: api.com\r\n\r\n", host: "api.com",
port: 443, payloads: ["1", "admin", "../../etc/passwd"])
# §section§ markers (like Intruder) | # byte offsets: positions: [[12, 15]]
# built-in payload libraries via: payload_library: "xss" | "sqli" | "lfi" | ...
Custom Scan Checks
# BCheck DSL
bcheck_create(name: "AWS Key Leak", type: "passive_response",
match_pattern: "AKIA[0-9A-Z]{16}", severity: "high", confidence: "firm")
# Script mode — multi-step active check
scancheck_create_active(name: "SSTI", steps: [
{"payload": "{{7*7}}", "response_conditions": [
{"location": "response_body", "pattern": "49", "condition_type": "contains"}]}])
API Schema Import
api_import_openapi(spec_json: "<swagger/openapi JSON>", auth_header: "Authorization",
auth_value: "Bearer …", send_requests: true, add_to_sitemap: true)
Parses OpenAPI 3.x / Swagger 2.0 (resolving $ref), generates real requests with sample
parameters/bodies for every endpoint, and optionally sends them — populating proxy history
and sitemap. Out-of-scope sends are skipped and reported.
Passive Intelligence Extraction
passive_intel(max_items: 2000, in_scope_only: true)
Scans captured traffic for 30+ patterns with entropy de-noising to cut false positives:
- Cloud credentials — AWS keys, Google/Slack/Stripe/GitHub tokens
- Tokens & secrets — JWTs, Bearer/Basic auth, private keys
- Personal data — emails, internal IPs, phone numbers
- Cloud resources — S3/Azure/GCS buckets
- Infrastructure — internal URLs, GraphQL endpoints, API paths
- Errors & fingerprints — stack traces, SQL errors, server/framework versions
- Sensitive paths —
/admin,/.env,/.git,/debug,/actuator
Security Model
BurpMCP-Ultra runs three local servers (SSE 9876/9877, dashboard 9878). Binding to
127.0.0.1 is not a trust boundary, so the transport is hardened and offensive tools are
governed by operator-only controls the agent cannot change.
Port already in use? PortSwigger's own MCP Server extension also defaults to 9876, so running both at once clashes. Move this extension with the
mcp_sse_port/mcp_http_port/mcp_dashboard_portpreferences (or-Dburpmcp.ssePort=…), then reload. On a clash the extension now says so explicitly in the Errors tab — it is not the JDK-version problem.
Transport hardening
- Host-header allowlist — defeats DNS rebinding.
- Origin lockdown — rejects cross-origin browser requests; CORS only advertises loopback.
- Per-session token — required on every request (
Authorization: Bearer,mcp_tokencookie,?token=, or the first URL path segment/<token>/for header-less MCP clients). The dashboard uses anHttpOnlycookie, so the token never lives in a URL there. A back-channelPOST ?sessionId=…may instead present a live session id — a 122-bit capability the server discloses only over an already-authenticated stream, never a bypass.
Operator governance (configured in Burp, not via MCP)
mcp_scope_mode—off/warn/enforce. Every live-request tool passes through a central scope gate (http_*,auth_diff,api_import_openapi,recon_*,graphql_probe,cors_probe,access_control_sweep,injection_probe).mcp_allow_destructive— default false; blocksburp_shutdownand config import.- Append-only audit log of security-relevant tool calls (
~/.burpmcp-ultra-audit.jsonl).
Additional defenses: ReDoS-safe regex, CRLF header validation, and response/WebSocket size caps.
Web Dashboard
Open http://127.0.0.1:9878 for the real-time dashboard:
- Live Activity Stream with noise filtering (auto-hides Google/Apple/Microsoft connectivity checks)
- Attack Vector Detection — badges for AUTH, API, PARAMS, UPLOAD, ADMIN, DATA endpoints
- Request Detail Panel — click any item for full request info + send-to-tool actions
- Stats Bar — live counters for events, in-scope hosts, and attack-vector categories
- Filter Controls — type filters, URL search, noise toggle
- Active Rules — view all proxy, traffic, and session rules
- Connection Info — transport URLs and a ready-to-paste MCP client config
Setup Guides
{
"mcpServers": {
"burp": {
"type": "sse",
"url": "http://127.0.0.1:9876/",
"headers": { "Authorization": "Bearer PASTE_TOKEN_FROM_SERVER_TAB" }
}
}
}
The token comes from the Server tab. The endpoint is the root path / (not /sse). If your
client cannot set headers, drop the headers block and put the token in the path instead —
"url": "http://127.0.0.1:9876/<token>/" (keep the trailing slash). Config locations:
~/.claude.json (global) or .mcp.json (per-project).
Caddy prevents SSE timeout disconnections and provides reliable buffering.
sudo apt install caddy
/etc/caddy/Caddyfile:
:9900 {
reverse_proxy 127.0.0.1:9876 {
transport http { read_timeout 0 write_timeout 0 response_header_timeout 0 }
flush_interval -1
header_up Connection {>Connection}
header_up Upgrade {>Upgrade}
}
}
sudo systemctl restart caddy
Then point your config at port 9900:
{
"mcpServers": {
"burp": {
"type": "sse",
"url": "http://127.0.0.1:9900/",
"headers": { "Authorization": "Bearer PASTE_TOKEN_FROM_SERVER_TAB" }
}
}
}
Pre-built Caddyfile: configs/Caddyfile
Claude Desktop only supports stdio transport. Bridge it with supergateway:
{
"mcpServers": {
"burp": {
"command": "npx",
"args": ["-y", "supergateway", "--sse", "http://127.0.0.1:9876/", "--header", "Authorization: Bearer PASTE_TOKEN_FROM_SERVER_TAB"]
}
}
}
chmod +x configs/setup.sh
./configs/setup.sh
Builds the JAR, optionally configures Caddy, and prints the MCP config to add.
Architecture
+---------------------------------------------------+
| BURP SUITE PRO |
| +---------------------------------------------+ |
| | BurpMCP-Ultra Extension | |
| | | |
| | Montoya API --> Bridge Layer (32 bridges) | |
| | | | | |
| | Event Bus Tool Registry (150 tools) | |
| | | | | |
| | +------- MCP Server Core -------+ | |
| | (Kotlin SDK 0.8.3) | | |
| | | | | |
| | +----------+----------+ | | |
| | SSE :9876 SSE :9877 Dashboard | | |
| | :9878 | | |
| +---------------------------------------------+ |
+---------------------------------------------------+
Tech Stack
Requirements
To run (inside Burp):
- Burp Suite Professional 2025.x or later
- Java 17+ — provided by Burp's bundled JRE (nothing to install)
To build from source:
- A JDK 17–21 (LTS) installed. Building under Java 22+ (including Burp's bundled Java 25)
is incompatible with the Kotlin 2.1.20 / Ktor 3.2.3 / MCP SDK toolchain and yields a JAR
whose MCP SSE ports silently fail to bind. You do not need JDK 17 as your default,
though: the build pins both compilation and the Gradle daemon to a JDK 17 toolchain
(
gradle/gradle-daemon-jvm.properties), so./gradlewauto-runs under JDK 17 as long as one is installed and discoverable. - Gradle 8.x — included via the committed wrapper (
./gradlew/gradlew.bat).
Building from Source
The Gradle wrapper is committed, so no separate Gradle install is needed.
Linux / macOS
git clone https://github.com/Cy-S3c/BurpMCP-Ultra.git
cd BurpMCP-Ultra
# Gradle auto-selects an installed JDK 17 for the build daemon, so this works even if your
# default `java` is Burp's Java 25. If no JDK 17 is discoverable, install one (or set JAVA_HOME).
./gradlew shadowJar
# Output: build/libs/burpmcp-ultra-2.3.1.jar
Windows (PowerShell / cmd)
git clone https://github.com/Cy-S3c/BurpMCP-Ultra.git
cd BurpMCP-Ultra
:: Gradle auto-selects an installed JDK 17 for the build daemon, so this works even if your
:: default java is Burp's Java 25. If no JDK 17 is discoverable, install one (or set JAVA_HOME).
gradlew.bat shadowJar
:: Output: build\libs\burpmcp-ultra-2.3.1.jar
If no JDK 17 is found, Gradle fails with a clear "no compatible daemon JVM" error instead of silently producing a broken JAR. Kotlin 2.1.20 cannot even compile the Gradle build scripts under Java 22+, which is why the daemon is pinned to JDK 17.
Project Structure
BurpMCP-Ultra/
├── build.gradle.kts # Build configuration
├── gradle/ # Wrapper + daemon-JVM pin (JDK 17)
├── configs/ # Ready-to-use config files (Caddyfile, MCP JSON, setup.sh)
├── src/main/kotlin/com/burpmcp/ultra/
│ ├── core/ # Extension entry point + helpers
│ ├── bridge/ # 32 Montoya API bridges
│ ├── tools/ # 37 tool category modules (150 tools)
│ ├── safety/ # Scope gate, action policy, ReDoS-safe regex
│ ├── transport/ # MCP server + dashboard + security
│ ├── events/ # Unified event bus
│ ├── state/ # State management
│ └── ui/ # Swing UI tab
├── src/test/ # 105 unit tests
└── docs/ # Tool catalog + capability review
Contact & Support
- 🐛 Bugs & feature requests: GitHub Issues
- 📦 Releases & changelog: GitHub Releases
- 💬 Quick reach: Telegram @D4RK_V0RT3X