diff --git a/.agents/plugins/marketplace.json b/.agents/plugins/marketplace.json
index c02fbd2f..945825eb 100644
--- a/.agents/plugins/marketplace.json
+++ b/.agents/plugins/marketplace.json
@@ -856,6 +856,21 @@
"description": "Manage Bitbucket repos, PRs, branches, issues, webhooks, and pipelines for Data Center and Cloud.",
"icon": "./plugins/avivsinai/bitbucket-cli/assets/bkt-icon.svg"
},
+ {
+ "name": "burpsuite-mcp-bridge",
+ "displayName": "BurpSuite MCP Bridge",
+ "source": {
+ "source": "local",
+ "path": "./plugins/6jeffr3y/burpsuite-mcp-bridge"
+ },
+ "policy": {
+ "installation": "AVAILABLE",
+ "authentication": "ON_INSTALL"
+ },
+ "category": "Tools & Integrations",
+ "description": "Bridge Burp Suite traffic, replay, rewrite rules, and evidence export into Codex through MCP for WSL, Windows, and macOS workflows.",
+ "icon": "./plugins/6jeffr3y/burpsuite-mcp-bridge/assets/icon.svg"
+ },
{
"name": "calle",
"displayName": "Call-E",
diff --git a/README.md b/README.md
index 7ce8c43f..9f7b012f 100644
--- a/README.md
+++ b/README.md
@@ -194,6 +194,7 @@ Third-party plugins built by the community. [PRs welcome](#contributing)!
- [Apple Productivity](https://github.com/matk0shub/apple-productivity-mcp) - Local Apple Calendar and Reminders tooling for macOS with Codex plugin adapters.
- [AxonFlow](https://github.com/getaxonflow/axonflow-codex-plugin) - Runtime governance for Codex with policy enforcement on terminal commands, advisory checks for non-terminal tools via skills, PII/secret detection, and compliance-grade audit trails. Self-hosted via Docker.
- [Bitbucket CLI](https://github.com/avivsinai/bitbucket-cli) - Manage Bitbucket repos, PRs, branches, issues, webhooks, and pipelines for Data Center and Cloud.
+- [BurpSuite MCP Bridge](https://github.com/6jeffr3y/burpsuite-mcp-bridge) - Bridge Burp Suite traffic, replay, rewrite rules, and evidence export into Codex through MCP for WSL, Windows, and macOS workflows.
- [Call-E](https://github.com/CALLE-AI/call-e-integrations) - Plan, run, and inspect Call-E phone call workflows from Codex through the calle CLI.
- [Canvas Apps Plugin Codex](https://github.com/Ratnam-Mishra/canvas-apps-plugin-codex) - Build and edit Microsoft Power Apps Canvas Apps using natural language and Canvas Authoring MCP server.
- [Chrome DevTools](https://github.com/win4r/chrome-devtools-codex-plugin) - One-click Codex plugin wrapper for chrome-devtools-mcp.
diff --git a/plugins.json b/plugins.json
index dfeebe7b..81a34f0e 100644
--- a/plugins.json
+++ b/plugins.json
@@ -2,8 +2,8 @@
"$schema": "https://json-schema.org/draft/2020-12/schema",
"name": "awesome-codex-plugins",
"version": "1.0.0",
- "last_updated": "2026-06-04",
- "total": 98,
+ "last_updated": "2026-06-06",
+ "total": 99,
"categories": [
"Development & Workflow",
"Tools & Integrations"
@@ -589,6 +589,16 @@
"source": "awesome-codex-plugins",
"install_url": "https://raw.githubusercontent.com/avivsinai/bitbucket-cli/HEAD/.codex-plugin/plugin.json"
},
+ {
+ "name": "BurpSuite MCP Bridge",
+ "url": "https://github.com/6jeffr3y/burpsuite-mcp-bridge",
+ "owner": "6jeffr3y",
+ "repo": "burpsuite-mcp-bridge",
+ "description": "Bridge Burp Suite traffic, replay, rewrite rules, and evidence export into Codex through MCP for WSL, Windows, and macOS workflows.",
+ "category": "Tools & Integrations",
+ "source": "awesome-codex-plugins",
+ "install_url": "https://raw.githubusercontent.com/6jeffr3y/burpsuite-mcp-bridge/HEAD/.codex-plugin/plugin.json"
+ },
{
"name": "Call-E",
"url": "https://github.com/CALLE-AI/call-e-integrations",
diff --git a/plugins/6jeffr3y/burpsuite-mcp-bridge/.codex-plugin/plugin.json b/plugins/6jeffr3y/burpsuite-mcp-bridge/.codex-plugin/plugin.json
new file mode 100755
index 00000000..1f7bb513
--- /dev/null
+++ b/plugins/6jeffr3y/burpsuite-mcp-bridge/.codex-plugin/plugin.json
@@ -0,0 +1,45 @@
+{
+ "name": "burpsuite-mcp-bridge",
+ "version": "1.1.0",
+ "description": "Burp Suite MCP bridge for target-centric traffic triage, replay, rewrite automation, UI selection handoff, BCheck/Bambda import, and evidence export across WSL/Windows/macOS clients.",
+ "author": {
+ "name": "BurpSuite MCP Bridge",
+ "email": "6jeffr3y@users.noreply.github.com",
+ "url": "https://github.com/6jeffr3y/burpsuite-mcp-bridge"
+ },
+ "homepage": "https://github.com/6jeffr3y/burpsuite-mcp-bridge",
+ "repository": "https://github.com/6jeffr3y/burpsuite-mcp-bridge",
+ "license": "Proprietary Runtime Distribution",
+ "keywords": [
+ "burp",
+ "mcp",
+ "codex",
+ "wsl",
+ "windows",
+ "montoya",
+ "proxy",
+ "agent-ai"
+ ],
+ "mcpServers": "./.mcp.json",
+ "interface": {
+ "displayName": "BurpSuite MCP Bridge",
+ "shortDescription": "Bridge Burp Suite traffic, replay, and rewrite workflows into MCP clients and IDEs",
+ "longDescription": "Expose Burp Suite proxy, history, logger-like internal tool traffic, and UI-selected messages to MCP clients. Supports target-centric overview, low-noise polling, replay with mutation, request/response rewrite rules with modify/drop/spoof actions, Repeater handoff, BCheck/Bambda import, and exportable raw evidence.",
+ "developerName": "BurpSuite MCP Bridge",
+ "category": "Coding",
+ "capabilities": [
+ "Read",
+ "Write",
+ "Interactive"
+ ],
+ "websiteURL": "https://github.com/6jeffr3y/burpsuite-mcp-bridge",
+ "brandColor": "#f97316",
+ "composerIcon": "./assets/icon.svg",
+ "logo": "./assets/logo.svg",
+ "defaultPrompt": [
+ "Use BurpSuite MCP Bridge to build a target overview for the current host and pick high-value candidate flows.",
+ "Use BurpSuite MCP Bridge to inspect a selected Burp message, replay one controlled mutation, and export the raw evidence bundle.",
+ "Use BurpSuite MCP Bridge to create a temporary scoped rewrite rule, verify its effect, then delete or disable it."
+ ]
+ }
+}
diff --git a/plugins/6jeffr3y/burpsuite-mcp-bridge/.codexignore b/plugins/6jeffr3y/burpsuite-mcp-bridge/.codexignore
new file mode 100755
index 00000000..8b8d8016
--- /dev/null
+++ b/plugins/6jeffr3y/burpsuite-mcp-bridge/.codexignore
@@ -0,0 +1,4 @@
+artifacts/
+**/__pycache__/
+*.pyc
+*.log
diff --git a/plugins/6jeffr3y/burpsuite-mcp-bridge/.mcp.json b/plugins/6jeffr3y/burpsuite-mcp-bridge/.mcp.json
new file mode 100755
index 00000000..56566f49
--- /dev/null
+++ b/plugins/6jeffr3y/burpsuite-mcp-bridge/.mcp.json
@@ -0,0 +1,13 @@
+{
+ "mcpServers": {
+ "burpsuite-mcp-bridge": {
+ "command": "python3",
+ "args": [
+ "./wsl-mcp/server.py"
+ ],
+ "env": {
+ "BURP_MCP_BRIDGE_URL": "http://127.0.0.1:9639"
+ }
+ }
+ }
+}
diff --git a/plugins/6jeffr3y/burpsuite-mcp-bridge/CHANGELOG.md b/plugins/6jeffr3y/burpsuite-mcp-bridge/CHANGELOG.md
new file mode 100755
index 00000000..9179d1f1
--- /dev/null
+++ b/plugins/6jeffr3y/burpsuite-mcp-bridge/CHANGELOG.md
@@ -0,0 +1,31 @@
+# Changelog
+
+## 1.1.0
+
+### Highlights
+- Added target-centric traffic overview via `burp_target_overview`.
+- Added staged MCP help via `burp_mcp_list`.
+- Implemented real rewrite-rule actions: `modify`, `drop`, and `spoof`.
+- Added rule scope control: `proxy`, `tool`, and `all`.
+- Added Burp 2026.4.x runtime-detected integrations:
+ - command palette / HotKey selection capture
+ - official internal-tool request drop/spoof when available
+ - BCheck import
+ - Bambda import
+- Added Burp UI diagnostics, command copy helpers, and improved rewrite-rule UX.
+- Simplified configuration: examples directly start `wsl-mcp/server.py` and set `BURP_MCP_BRIDGE_URL`; wrapper scripts were removed from the release package.
+
+### Stability / Compatibility
+- Compile baseline remains `montoya-api 2025.10`.
+- Optional 2026.4.x features are detected at runtime.
+- JSON detail responses keep preview-first body handling; full raw evidence is exported via bundle files.
+
+### Tested Baseline
+- Burp Suite Professional 2026.4.2
+
+## 1.0.0
+
+### Highlights
+- Initial release for Windows Burp ↔ WSL Codex / Agent AI / MCP CLI / IDE communication.
+- Reads Burp Proxy traffic and logger-like internal HTTP tool traffic.
+- Supports replay, rewrite rules, Repeater handoff, and raw bundle export.
diff --git a/plugins/6jeffr3y/burpsuite-mcp-bridge/CHANGELOG_CN.md b/plugins/6jeffr3y/burpsuite-mcp-bridge/CHANGELOG_CN.md
new file mode 100755
index 00000000..e811d157
--- /dev/null
+++ b/plugins/6jeffr3y/burpsuite-mcp-bridge/CHANGELOG_CN.md
@@ -0,0 +1,31 @@
+# 更新日志
+
+## 1.1.0
+
+### 重点更新
+- 新增目标视角流量画像:`burp_target_overview`。
+- 新增分级 MCP 帮助:`burp_mcp_list`。
+- 改写规则动作真正落地:`modify`、`drop`、`spoof`。
+- 规则作用面支持:`proxy`、`tool`、`all`。
+- 接入 Burp 2026.4.x 运行时检测能力:
+ - command palette / HotKey selection 捕获
+ - 可用时使用官方 internal-tool request drop/spoof
+ - BCheck 导入
+ - Bambda 导入
+- 增强 Burp UI:自检、命令复制、规则 UX。
+- 简化配置:示例直接启动 `wsl-mcp/server.py` 并设置 `BURP_MCP_BRIDGE_URL`;release 包移除 wrapper 脚本。
+
+### 稳定性 / 兼容性
+- 编译基线保持 `montoya-api 2025.10`。
+- 2026.4.x 可选能力运行时检测。
+- JSON 详情接口继续使用 preview-first body;完整原始证据通过 bundle 文件导出。
+
+### 测试基线
+- Burp Suite Professional 2026.4.2
+
+## 1.0.0
+
+### 重点更新
+- 初始发布,支持 Windows Burp ↔ WSL Codex / Agent AI / MCP CLI / IDE 通信。
+- 支持 Burp Proxy 流量与 logger-like 内部工具流量读取。
+- 支持重放、改写规则、Repeater 联动和原始包导出。
diff --git a/plugins/6jeffr3y/burpsuite-mcp-bridge/NOTICE.txt b/plugins/6jeffr3y/burpsuite-mcp-bridge/NOTICE.txt
new file mode 100755
index 00000000..90ecd124
--- /dev/null
+++ b/plugins/6jeffr3y/burpsuite-mcp-bridge/NOTICE.txt
@@ -0,0 +1,7 @@
+BurpSuite MCP Bridge
+
+Distribution notes:
+- review homepage / repository / support URLs before public release
+- review organization branding and contact information
+- verify the default bridge URL matches your target release environment
+- verify Python runtime availability for directly starting wsl-mcp/server.py
diff --git a/plugins/6jeffr3y/burpsuite-mcp-bridge/NOTICE_CN.txt b/plugins/6jeffr3y/burpsuite-mcp-bridge/NOTICE_CN.txt
new file mode 100755
index 00000000..cd643a47
--- /dev/null
+++ b/plugins/6jeffr3y/burpsuite-mcp-bridge/NOTICE_CN.txt
@@ -0,0 +1,7 @@
+BurpSuite MCP Bridge
+
+发布前建议检查:
+- homepage / repository / support URL 是否替换为正式地址
+- 品牌信息与联系方式是否符合你的发布环境
+- 默认 Bridge URL 是否符合目标环境
+- Python 运行环境是否可以直接启动 wsl-mcp/server.py
diff --git a/plugins/6jeffr3y/burpsuite-mcp-bridge/README.md b/plugins/6jeffr3y/burpsuite-mcp-bridge/README.md
new file mode 100755
index 00000000..a398482a
--- /dev/null
+++ b/plugins/6jeffr3y/burpsuite-mcp-bridge/README.md
@@ -0,0 +1,190 @@
+# BurpSuite MCP Bridge
+
+English | [简体中文](./README_CN.md)
+
+**MCP bridge for Burp Suite traffic, replay, rewrite automation, UI selection handoff, and evidence export.**
+
+This release is designed for real mixed-environment workflows: Burp can run on Windows while Codex/AI agents run in WSL, Windows, or macOS. The default setup uses stdio MCP and points the Python MCP server at the Burp extension bridge with one explicit URL.
+
+---
+
+## What's new in v1.1.0
+
+- Unified MCP response/error shape.
+- Rewrite rules now support real `modify`, `drop`, and `spoof` actions.
+- Rule scope supports `proxy`, `tool`, and `all`.
+- Burp 2026.4.x runtime-detected integrations:
+ - command palette / HotKey selection capture
+ - official internal-tool request drop/spoof when available
+ - BCheck import
+ - Bambda import
+- New target-centric workflow: `burp_target_overview(host=...)`.
+- New staged help: `burp_mcp_list(section=..., topic=...)`.
+- Better Burp UI diagnostics, quick MCP command copy panel, and rewrite-rule UX.
+- Simplified configuration: no wrapper scripts are required.
+
+Tested with **Burp Suite Professional 2026.4.2**. Compile baseline remains `montoya-api 2025.10`; newer features are runtime-detected for compatibility.
+
+---
+
+## Included files
+
+```text
+burp-plugin/
+ burpsuite-mcp-bridge-1.1.0-all.jar
+ burpsuite-mcp-bridge-latest.jar
+wsl-mcp/
+ server.py
+config-examples/
+ codex-wsl-mirrored.toml
+ codex-wsl-nat.toml
+ codex-windows.toml
+ codex-macos.toml
+requirements-wsl.txt
+```
+
+---
+
+## Quick start
+
+### 1) Load the Burp extension
+
+In Burp Suite, load:
+
+```text
+burp-plugin/burpsuite-mcp-bridge-latest.jar
+```
+
+Recommended bridge settings:
+
+```text
+Bind host: 127.0.0.1
+Port: 9639
+Max live/logger entries: 1500
+Max body preview bytes: 32768
+Ignore static: on
+```
+
+For WSL NAT, bind Burp Bridge to the Windows LAN IP or `0.0.0.0`, then use that LAN IP in `BURP_MCP_BRIDGE_URL`.
+
+### 2) Install MCP runtime dependency
+
+```bash
+python3 -m pip install -r requirements-wsl.txt
+```
+
+On Windows, use your normal Python installation and install the same requirement.
+
+### 3) Configure Codex / MCP
+
+Default stdio setup directly starts `wsl-mcp/server.py`; no wrapper script is required.
+
+WSL mirrored / local loopback:
+
+```toml
+[mcp_servers.burpsuite-mcp-bridge]
+command = "python3"
+args = ["/mnt/d/AI_project/burpsuite-mcp-bridge-release/wsl-mcp/server.py"]
+
+[mcp_servers.burpsuite-mcp-bridge.env]
+BURP_MCP_BRIDGE_URL = "http://127.0.0.1:9639"
+```
+
+WSL NAT example:
+
+```toml
+[mcp_servers.burpsuite-mcp-bridge]
+command = "python3"
+args = ["/mnt/d/AI_project/burpsuite-mcp-bridge-release/wsl-mcp/server.py"]
+
+[mcp_servers.burpsuite-mcp-bridge.env]
+BURP_MCP_BRIDGE_URL = "http://192.168.1.100:9639"
+```
+
+See `config-examples/` for WSL mirrored, WSL NAT, Windows, and macOS variants.
+
+---
+
+## Codex plugin marketplace readiness
+
+This repository ships a valid `.codex-plugin/plugin.json`, icon assets, release JARs, and direct MCP configuration examples. It is suitable for submission to community Codex plugin directories such as `awesome-codex-plugins` for discovery, while remaining installable directly from this repository.
+
+---
+
+## Core MCP tools
+
+### Status and help
+
+- `burp_bridge_status`
+- `burp_config_get`
+- `burp_mcp_list`
+
+### Target and traffic
+
+- `burp_target_overview`
+- `burp_live_poll`
+- `burp_live_overview`
+- `burp_history_search`
+- `burp_logger_poll`
+- `burp_logger_overview`
+- `burp_extension_activity_overview`
+- `burp_selection_poll`
+- `burp_flow_get`
+- `burp_logger_flow_get`
+- `burp_selection_get`
+
+### Replay and evidence
+
+- `burp_replay_flow`
+- `burp_send_raw_request`
+- `burp_send_to_repeater`
+- `burp_export_flow`
+- `burp_export_flow_bundle`
+
+### Automation
+
+- `burp_rules_list`
+- `burp_rule_upsert`
+- `burp_rule_delete`
+- `burp_bcheck_import`
+- `burp_bambda_import`
+
+---
+
+## Recommended workflow
+
+1. Start with `burp_target_overview(host="target.example")`.
+2. Inspect one candidate flow with the matching getter:
+ - `burp_flow_get(..., source="history" | "live")`
+ - `burp_logger_flow_get(...)`
+ - `burp_selection_get(...)`
+3. Replay one controlled mutation with `burp_replay_flow`.
+4. Export decisive raw evidence with `burp_export_flow_bundle`.
+5. If a behavior is reusable, promote it to a rewrite rule, BCheck, or Bambda.
+
+---
+
+## Body handling
+
+JSON detail calls inline body previews only. Large bodies are capped to avoid MCP context bloat and Burp/UI pressure. For full raw request/response bytes, use:
+
+```python
+burp_export_flow_bundle(flow_id=123, source="history")
+```
+
+---
+
+## Optional Streamable HTTP MCP
+
+The default release examples use stdio MCP. If you need Streamable HTTP, start it manually:
+
+```bash
+BURP_MCP_BRIDGE_URL=http://127.0.0.1:9639 \
+python3 wsl-mcp/server.py --transport streamable-http --host 127.0.0.1 --port 9640 --path /mcp
+```
+
+Default URL:
+
+```text
+http://127.0.0.1:9640/mcp
+```
diff --git a/plugins/6jeffr3y/burpsuite-mcp-bridge/README_CN.md b/plugins/6jeffr3y/burpsuite-mcp-bridge/README_CN.md
new file mode 100755
index 00000000..cbbd95ff
--- /dev/null
+++ b/plugins/6jeffr3y/burpsuite-mcp-bridge/README_CN.md
@@ -0,0 +1,190 @@
+# BurpSuite MCP Bridge
+
+[English](./README.md) | 简体中文
+
+**把 Burp Suite 的流量、重放、改写规则、UI 选中消息和证据导出能力接入 MCP / Codex / AI Agent。**
+
+本项目面向真实混合环境:Burp 可以跑在 Windows,Codex/AI Agent 可以跑在 WSL、Windows 或 macOS。默认使用 stdio MCP,并在 TOML 中用一个完整 URL 指向 Burp 扩展 bridge。
+
+---
+
+## v1.1.0 新增内容
+
+- 统一 MCP 返回和错误结构。
+- 改写规则动作真正落地:`modify`、`drop`、`spoof`。
+- 规则作用面支持:`proxy`、`tool`、`all`。
+- 接入 Burp 2026.4.x 运行时能力:
+ - command palette / HotKey 捕获 UI selection
+ - 可用时使用官方 internal-tool request drop/spoof
+ - BCheck 导入
+ - Bambda 导入
+- 新增目标视角工作流:`burp_target_overview(host=...)`。
+- 新增分级帮助:`burp_mcp_list(section=..., topic=...)`。
+- 增强 Burp UI:自检状态、MCP 命令速查复制、规则 UX。
+- 简化配置:不再需要 wrapper 脚本。
+
+已用 **Burp Suite Professional 2026.4.2** 测试。编译基线仍保持 `montoya-api 2025.10`,新版能力运行时检测,尽量保持兼容。
+
+---
+
+## 包含文件
+
+```text
+burp-plugin/
+ burpsuite-mcp-bridge-1.1.0-all.jar
+ burpsuite-mcp-bridge-latest.jar
+wsl-mcp/
+ server.py
+config-examples/
+ codex-wsl-mirrored.toml
+ codex-wsl-nat.toml
+ codex-windows.toml
+ codex-macos.toml
+requirements-wsl.txt
+```
+
+---
+
+## 快速开始
+
+### 1)加载 Burp 扩展
+
+在 Burp Suite 中加载:
+
+```text
+burp-plugin/burpsuite-mcp-bridge-latest.jar
+```
+
+推荐设置:
+
+```text
+Bind host: 127.0.0.1
+Port: 9639
+Max live/logger entries: 1500
+Max body preview bytes: 32768
+Ignore static: on
+```
+
+如果是 WSL NAT,需要把 Burp Bridge 绑定到 Windows 局域网 IP 或 `0.0.0.0`,然后在 `BURP_MCP_BRIDGE_URL` 里使用这个局域网 IP。
+
+### 2)安装 MCP runtime 依赖
+
+```bash
+python3 -m pip install -r requirements-wsl.txt
+```
+
+Windows 环境使用本机 Python 安装同样依赖即可。
+
+### 3)配置 Codex / MCP
+
+默认 stdio 配置直接启动 `wsl-mcp/server.py`,不需要 wrapper 脚本。
+
+WSL mirrored / 本机 loopback:
+
+```toml
+[mcp_servers.burpsuite-mcp-bridge]
+command = "python3"
+args = ["/mnt/d/AI_project/burpsuite-mcp-bridge-release/wsl-mcp/server.py"]
+
+[mcp_servers.burpsuite-mcp-bridge.env]
+BURP_MCP_BRIDGE_URL = "http://127.0.0.1:9639"
+```
+
+WSL NAT 示例:
+
+```toml
+[mcp_servers.burpsuite-mcp-bridge]
+command = "python3"
+args = ["/mnt/d/AI_project/burpsuite-mcp-bridge-release/wsl-mcp/server.py"]
+
+[mcp_servers.burpsuite-mcp-bridge.env]
+BURP_MCP_BRIDGE_URL = "http://192.168.1.100:9639"
+```
+
+更多环境参考 `config-examples/`。
+
+---
+
+## Codex 插件市场准备状态
+
+本仓库已经包含有效的 `.codex-plugin/plugin.json`、图标资源、发布版 JAR 和直接启动 MCP 的配置示例。它可以提交到 `awesome-codex-plugins` 这类社区 Codex 插件目录获取曝光,同时也可以直接从本仓库安装使用。
+
+---
+
+## 主要 MCP 工具
+
+### 状态与帮助
+
+- `burp_bridge_status`
+- `burp_config_get`
+- `burp_mcp_list`
+
+### 目标和流量
+
+- `burp_target_overview`
+- `burp_live_poll`
+- `burp_live_overview`
+- `burp_history_search`
+- `burp_logger_poll`
+- `burp_logger_overview`
+- `burp_extension_activity_overview`
+- `burp_selection_poll`
+- `burp_flow_get`
+- `burp_logger_flow_get`
+- `burp_selection_get`
+
+### 重放和证据
+
+- `burp_replay_flow`
+- `burp_send_raw_request`
+- `burp_send_to_repeater`
+- `burp_export_flow`
+- `burp_export_flow_bundle`
+
+### 自动化
+
+- `burp_rules_list`
+- `burp_rule_upsert`
+- `burp_rule_delete`
+- `burp_bcheck_import`
+- `burp_bambda_import`
+
+---
+
+## 推荐工作流
+
+1. 先用 `burp_target_overview(host="target.example")` 做目标画像。
+2. 挑一个候选 flow 拉完整详情:
+ - `burp_flow_get(..., source="history" | "live")`
+ - `burp_logger_flow_get(...)`
+ - `burp_selection_get(...)`
+3. 用 `burp_replay_flow` 一次只改一个变量验证。
+4. 用 `burp_export_flow_bundle` 导出决定性原始证据。
+5. 如果模式可复用,再沉淀成 rewrite rule、BCheck 或 Bambda。
+
+---
+
+## Body 处理
+
+JSON 详情接口只内联 body preview,避免撑爆 MCP 上下文和拖慢 Burp/UI。完整原始请求/响应请使用:
+
+```python
+burp_export_flow_bundle(flow_id=123, source="history")
+```
+
+---
+
+## 可选 Streamable HTTP MCP
+
+默认示例使用 stdio MCP。如需 Streamable HTTP,可手工启动:
+
+```bash
+BURP_MCP_BRIDGE_URL=http://127.0.0.1:9639 \
+python3 wsl-mcp/server.py --transport streamable-http --host 127.0.0.1 --port 9640 --path /mcp
+```
+
+默认 URL:
+
+```text
+http://127.0.0.1:9640/mcp
+```
diff --git a/plugins/6jeffr3y/burpsuite-mcp-bridge/RELEASE_NOTES_v1.1.0.md b/plugins/6jeffr3y/burpsuite-mcp-bridge/RELEASE_NOTES_v1.1.0.md
new file mode 100755
index 00000000..91579570
--- /dev/null
+++ b/plugins/6jeffr3y/burpsuite-mcp-bridge/RELEASE_NOTES_v1.1.0.md
@@ -0,0 +1,37 @@
+# BurpSuite MCP Bridge v1.1.0
+
+## Highlights
+
+- Target-centric overview for real testing workflows: `burp_target_overview(host=...)`.
+- Staged tool help: `burp_mcp_list(section=..., topic=..., detail=true)`.
+- Rewrite rules now support real `modify`, `drop`, and `spoof` actions.
+- Rule scope can target `proxy`, `tool`, or `all`.
+- Burp 2026.4.x integrations:
+ - command palette / HotKey selection capture
+ - official internal-tool drop/spoof when available
+ - BCheck import
+ - Bambda import
+- Improved Burp UI for diagnostics, MCP command copy, and rewrite-rule management.
+- Simplified configs: direct `python3 wsl-mcp/server.py` plus `BURP_MCP_BRIDGE_URL`; no wrapper scripts in release.
+
+## Included assets
+
+- `burp-plugin/burpsuite-mcp-bridge-1.1.0-all.jar`
+- `burp-plugin/burpsuite-mcp-bridge-latest.jar`
+- `wsl-mcp/server.py`
+- Four config examples:
+ - WSL mirrored
+ - WSL NAT
+ - Windows
+ - macOS
+
+## Tested baseline
+
+- Burp Suite Professional `2026.4.2`
+- Compile baseline: `montoya-api 2025.10`
+
+## Upgrade notes
+
+- Replace the old Burp JAR with `burpsuite-mcp-bridge-latest.jar`.
+- Update MCP config to start `wsl-mcp/server.py` directly.
+- Use `BURP_MCP_BRIDGE_URL` instead of separate host/port values for clearer WSL NAT and multi-host setups.
diff --git a/plugins/6jeffr3y/burpsuite-mcp-bridge/assets/icon.svg b/plugins/6jeffr3y/burpsuite-mcp-bridge/assets/icon.svg
new file mode 100755
index 00000000..f47d97e4
--- /dev/null
+++ b/plugins/6jeffr3y/burpsuite-mcp-bridge/assets/icon.svg
@@ -0,0 +1,10 @@
+
diff --git a/plugins/6jeffr3y/burpsuite-mcp-bridge/assets/logo.svg b/plugins/6jeffr3y/burpsuite-mcp-bridge/assets/logo.svg
new file mode 100755
index 00000000..f47d97e4
--- /dev/null
+++ b/plugins/6jeffr3y/burpsuite-mcp-bridge/assets/logo.svg
@@ -0,0 +1,10 @@
+
diff --git a/plugins/6jeffr3y/burpsuite-mcp-bridge/burp-plugin/burpsuite-mcp-bridge-1.1.0-all.jar b/plugins/6jeffr3y/burpsuite-mcp-bridge/burp-plugin/burpsuite-mcp-bridge-1.1.0-all.jar
new file mode 100755
index 00000000..fbeea11f
Binary files /dev/null and b/plugins/6jeffr3y/burpsuite-mcp-bridge/burp-plugin/burpsuite-mcp-bridge-1.1.0-all.jar differ
diff --git a/plugins/6jeffr3y/burpsuite-mcp-bridge/burp-plugin/burpsuite-mcp-bridge-latest.jar b/plugins/6jeffr3y/burpsuite-mcp-bridge/burp-plugin/burpsuite-mcp-bridge-latest.jar
new file mode 100755
index 00000000..fbeea11f
Binary files /dev/null and b/plugins/6jeffr3y/burpsuite-mcp-bridge/burp-plugin/burpsuite-mcp-bridge-latest.jar differ
diff --git a/plugins/6jeffr3y/burpsuite-mcp-bridge/config-examples/codex-macos.toml b/plugins/6jeffr3y/burpsuite-mcp-bridge/config-examples/codex-macos.toml
new file mode 100755
index 00000000..a537883b
--- /dev/null
+++ b/plugins/6jeffr3y/burpsuite-mcp-bridge/config-examples/codex-macos.toml
@@ -0,0 +1,9 @@
+# macOS local setup
+# Burp and MCP server both run on macOS, so loopback is enough.
+# Replace the path with your local clone path.
+[mcp_servers.burpsuite-mcp-bridge]
+command = "python3"
+args = ["/Users/you/burpsuite-mcp-bridge-release/wsl-mcp/server.py"]
+
+[mcp_servers.burpsuite-mcp-bridge.env]
+BURP_MCP_BRIDGE_URL = "http://127.0.0.1:9639"
diff --git a/plugins/6jeffr3y/burpsuite-mcp-bridge/config-examples/codex-windows.toml b/plugins/6jeffr3y/burpsuite-mcp-bridge/config-examples/codex-windows.toml
new file mode 100755
index 00000000..898a4748
--- /dev/null
+++ b/plugins/6jeffr3y/burpsuite-mcp-bridge/config-examples/codex-windows.toml
@@ -0,0 +1,8 @@
+# Native Windows Codex/MCP
+# Burp and MCP server both run on Windows, so loopback is enough.
+[mcp_servers.burpsuite-mcp-bridge]
+command = "python"
+args = ["D:\\AI_project\\burpsuite-mcp-bridge-release\\wsl-mcp\\server.py"]
+
+[mcp_servers.burpsuite-mcp-bridge.env]
+BURP_MCP_BRIDGE_URL = "http://127.0.0.1:9639"
diff --git a/plugins/6jeffr3y/burpsuite-mcp-bridge/config-examples/codex-wsl-mirrored.toml b/plugins/6jeffr3y/burpsuite-mcp-bridge/config-examples/codex-wsl-mirrored.toml
new file mode 100755
index 00000000..e3b0833e
--- /dev/null
+++ b/plugins/6jeffr3y/burpsuite-mcp-bridge/config-examples/codex-wsl-mirrored.toml
@@ -0,0 +1,8 @@
+# WSL mirrored networking (recommended for current setup)
+# Burp runs on Windows, Codex/MCP runs inside WSL, and 127.0.0.1 reaches Windows Burp.
+[mcp_servers.burpsuite-mcp-bridge]
+command = "python3"
+args = ["/mnt/d/AI_project/burpsuite-mcp-bridge-release/wsl-mcp/server.py"]
+
+[mcp_servers.burpsuite-mcp-bridge.env]
+BURP_MCP_BRIDGE_URL = "http://127.0.0.1:9639"
diff --git a/plugins/6jeffr3y/burpsuite-mcp-bridge/config-examples/codex-wsl-nat.toml b/plugins/6jeffr3y/burpsuite-mcp-bridge/config-examples/codex-wsl-nat.toml
new file mode 100755
index 00000000..18a3080c
--- /dev/null
+++ b/plugins/6jeffr3y/burpsuite-mcp-bridge/config-examples/codex-wsl-nat.toml
@@ -0,0 +1,10 @@
+# WSL NAT networking
+# Burp runs on Windows, Codex/MCP runs inside WSL, but 127.0.0.1 is WSL itself.
+# Replace 192.168.1.100 with the Windows LAN IP reachable from WSL.
+# In Burp MCP Bridge UI, bindHost should be that LAN IP or 0.0.0.0, not only 127.0.0.1.
+[mcp_servers.burpsuite-mcp-bridge]
+command = "python3"
+args = ["/mnt/d/AI_project/burpsuite-mcp-bridge-release/wsl-mcp/server.py"]
+
+[mcp_servers.burpsuite-mcp-bridge.env]
+BURP_MCP_BRIDGE_URL = "http://192.168.1.100:9639"
diff --git a/plugins/6jeffr3y/burpsuite-mcp-bridge/requirements-wsl.txt b/plugins/6jeffr3y/burpsuite-mcp-bridge/requirements-wsl.txt
new file mode 100755
index 00000000..c413b608
--- /dev/null
+++ b/plugins/6jeffr3y/burpsuite-mcp-bridge/requirements-wsl.txt
@@ -0,0 +1 @@
+mcp>=1.0.0
diff --git a/plugins/6jeffr3y/burpsuite-mcp-bridge/wsl-mcp/server.py b/plugins/6jeffr3y/burpsuite-mcp-bridge/wsl-mcp/server.py
new file mode 100755
index 00000000..9f0d7e8f
--- /dev/null
+++ b/plugins/6jeffr3y/burpsuite-mcp-bridge/wsl-mcp/server.py
@@ -0,0 +1,1251 @@
+from __future__ import annotations
+
+import argparse
+import json
+import os
+import re
+import time
+import urllib.error
+import urllib.parse
+import urllib.request
+from collections import Counter, defaultdict
+from pathlib import Path
+from typing import Any
+
+from mcp.server.fastmcp import FastMCP
+
+_NO_PROXY_OPENER = urllib.request.build_opener(urllib.request.ProxyHandler({}))
+DEFAULT_HOST = os.environ.get("BURP_MCP_BRIDGE_HOST", "127.0.0.1")
+DEFAULT_PORT = int(os.environ.get("BURP_MCP_BRIDGE_PORT", "9639"))
+MCP_TRANSPORT = os.environ.get("BURP_MCP_TRANSPORT", "stdio")
+MCP_SERVER_HOST = os.environ.get("BURP_MCP_SERVER_HOST", "127.0.0.1")
+MCP_SERVER_PORT = int(os.environ.get("BURP_MCP_SERVER_PORT", "9640"))
+MCP_SERVER_PATH = os.environ.get("BURP_MCP_SERVER_PATH", "/mcp")
+PLUGIN_ROOT = Path(os.environ.get("BURP_MCP_PLUGIN_ROOT", Path(__file__).resolve().parent.parent))
+ARTIFACT_ROOT = PLUGIN_ROOT / "artifacts"
+
+mcp = FastMCP(
+ "BurpSuite MCP Bridge",
+ instructions=(
+ "Use these tools to read and operate Burp proxy traffic from Windows Burp in WSL mirrored mode. "
+ "Prefer burp_target_overview(host=...) when working one target, or burp_live_overview/burp_live_poll for incremental triage, then burp_flow_get for a decisive request/response pair. "
+ "Use burp_replay_flow or burp_send_raw_request when you need AI-driven request mutation and replay. "
+ "Use burp_rule_upsert to install automatic request/response rewrite rules for proxied traffic; rule action is modify, drop, or spoof."
+ ),
+ host=MCP_SERVER_HOST,
+ port=MCP_SERVER_PORT,
+ streamable_http_path=MCP_SERVER_PATH,
+)
+
+
+def resolve_bridge_base() -> str:
+ explicit = os.environ.get("BURP_MCP_BRIDGE_URL")
+ if explicit:
+ return explicit.rstrip("/")
+ return f"http://{DEFAULT_HOST}:{DEFAULT_PORT}"
+
+
+def _request_json(path: str, method: str = "GET", payload: dict[str, Any] | None = None, query: dict[str, Any] | None = None) -> Any:
+ url = resolve_bridge_base() + path
+ if query:
+ filtered = {k: v for k, v in query.items() if v is not None}
+ if filtered:
+ url += "?" + urllib.parse.urlencode(filtered)
+
+ body = None
+ headers = {"Accept": "application/json"}
+ if payload is not None:
+ body = json.dumps(payload).encode("utf-8")
+ headers["Content-Type"] = "application/json"
+
+ request = urllib.request.Request(url, data=body, method=method, headers=headers)
+ try:
+ with _NO_PROXY_OPENER.open(request, timeout=30) as response:
+ data = json.loads(response.read().decode("utf-8"))
+ except urllib.error.HTTPError as exc:
+ response_body = exc.read().decode("utf-8", errors="ignore")
+ try:
+ parsed = json.loads(response_body)
+ error = parsed.get("error") if isinstance(parsed, dict) else None
+ if isinstance(error, dict):
+ detail = f"{error.get('code', 'error')}: {error.get('message', response_body)}"
+ else:
+ detail = parsed.get("message", response_body) if isinstance(parsed, dict) else response_body
+ except Exception:
+ detail = response_body
+ raise RuntimeError(f"bridge HTTP {exc.code}: {detail}") from exc
+ except urllib.error.URLError as exc:
+ raise RuntimeError(
+ "无法连接 Burp MCP Bridge。请确认:1) Windows Burp 已加载扩展;2) Burp 扩展已启用;"
+ f"3) WSL mirrored 下可访问 {resolve_bridge_base()}/health。底层错误:{exc.reason}"
+ ) from exc
+
+ if isinstance(data, dict) and data.get("ok") is False:
+ error = data.get("error")
+ if isinstance(error, dict):
+ raise RuntimeError(f"{error.get('code', 'error')}: {error.get('message', 'bridge returned failure')}")
+ raise RuntimeError(data.get("message") or error or "bridge returned failure")
+ return data
+
+
+def _timestamp() -> str:
+ return time.strftime("%Y%m%d-%H%M%S")
+
+
+_STATIC_PATH_RE = re.compile(r"(?i)\.(?:css|js|mjs|map|png|jpe?g|gif|svg|ico|woff2?|ttf|eot|mp4|webm|mp3|wav|pdf|zip|gz|br|wasm)(?:$|[?#])")
+_UUID_RE = re.compile(r"(?i)^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$")
+_HEX_ID_RE = re.compile(r"(?i)^[0-9a-f]{16,}$")
+_LONG_TOKEN_RE = re.compile(r"(?i)^[a-z0-9_-]{24,}$")
+_TARGET_SOURCE_ORDER = ("history", "live", "logger", "selection")
+
+
+def _parse_source_csv(sources: str | None, default: tuple[str, ...] = _TARGET_SOURCE_ORDER) -> list[str]:
+ if not sources:
+ return list(default)
+ requested = [part.strip().lower() for part in sources.split(",") if part.strip()]
+ if not requested or "all" in requested:
+ return list(default)
+ allowed = set(default)
+ unknown = [source for source in requested if source not in allowed]
+ if unknown:
+ raise ValueError(f"sources 只支持 {', '.join(default)} 或 all;未知值:{', '.join(unknown)}")
+ return [source for source in default if source in requested]
+
+
+def _path_no_query(path: Any) -> str:
+ value = str(path or "")
+ if not value:
+ return ""
+ return value.split("?", 1)[0] or "/"
+
+
+def _is_static_path(path: Any) -> bool:
+ return bool(path and _STATIC_PATH_RE.search(str(path)))
+
+
+def _normalize_endpoint_path(path: Any) -> str:
+ raw = _path_no_query(path)
+ if raw in {"", ""}:
+ return ""
+ leading = raw.startswith("/")
+ parts = [part for part in raw.split("/") if part]
+ normalized: list[str] = []
+ for part in parts:
+ lower = part.lower()
+ if part.isdigit():
+ normalized.append("{int}")
+ elif _UUID_RE.match(part):
+ normalized.append("{uuid}")
+ elif _HEX_ID_RE.match(part):
+ normalized.append("{hex}")
+ elif _LONG_TOKEN_RE.match(part) and any(ch.isdigit() for ch in part) and not any(ch in lower for ch in (".", "-")):
+ normalized.append("{id}")
+ else:
+ normalized.append(part)
+ if not normalized:
+ return "/"
+ return ("/" if leading else "") + "/".join(normalized)
+
+
+def _counter_key(value: Any, default: str = "") -> str:
+ if value is None:
+ return default
+ text = str(value)
+ return text if text else default
+
+
+def _flow_card(item: dict[str, Any], source: str | None = None, reasons: list[str] | None = None, score: int | None = None) -> dict[str, Any]:
+ actual_source = source or item.get("source") or "unknown"
+ flow_id = item.get("flowId")
+ if flow_id is None:
+ flow_id = item.get("historyId")
+ card = {
+ "source": actual_source,
+ "flowId": flow_id,
+ "method": item.get("method"),
+ "host": item.get("host"),
+ "path": item.get("path"),
+ "endpoint": _normalize_endpoint_path(item.get("path")),
+ "statusCode": item.get("statusCode"),
+ "mimeType": item.get("mimeType"),
+ "toolType": item.get("toolType"),
+ "tags": item.get("tags") or [],
+ }
+ if score is not None:
+ card["score"] = score
+ if reasons is not None:
+ card["reasons"] = reasons
+ return card
+
+
+def _score_target_flow(item: dict[str, Any]) -> tuple[int, list[str]]:
+ score = 0
+ reasons: list[str] = []
+
+ def add(delta: int, reason: str) -> None:
+ nonlocal score
+ score += delta
+ if reason not in reasons:
+ reasons.append(reason)
+
+ method = str(item.get("method") or "").upper()
+ path = str(item.get("path") or "").lower()
+ url = str(item.get("url") or "").lower()
+ haystack = f"{path} {url}"
+ tags = {str(tag).lower() for tag in (item.get("tags") or [])}
+ status = item.get("statusCode")
+ try:
+ status_int = int(status) if status is not None else None
+ except Exception:
+ status_int = None
+
+ if tags:
+ for tag in sorted(tags):
+ if tag in {"auth", "upload", "api"}:
+ add(8, f"tag:{tag}")
+ elif tag not in {"static"}:
+ add(3, f"tag:{tag}")
+
+ if any(k in haystack for k in ("login", "auth", "oauth", "sso", "cas", "saml", "token", "session", "signin", "logout")):
+ add(12, "auth/session endpoint")
+ if any(k in haystack for k in ("/api/", "/apis/", "/graphql", "/rpc", "/v1/", "/v2/", "/rest/")):
+ add(8, "api/rpc endpoint")
+ if any(k in haystack for k in ("upload", "import", "attach", "avatar", "file", "multipart")):
+ add(10, "upload/import/file endpoint")
+ if any(k in haystack for k in ("download", "export", "report", "excel", "pdf", "template")):
+ add(7, "download/export endpoint")
+ if any(k in haystack for k in ("admin", "manage", "permission", "role", "user", "config", "setting")):
+ add(7, "admin/permission/config endpoint")
+ if any(k in haystack for k in ("swagger", "openapi", "api-docs", "actuator", "debug", "trace")):
+ add(9, "metadata/debug endpoint")
+ if any(k in haystack for k in ("redirect", "callback", "returnurl", "return_url", "next=", "url=")):
+ add(5, "redirect/callback parameter")
+ if method in {"POST", "PUT", "PATCH", "DELETE"}:
+ add(6, "state-changing method")
+ if status_int in {401, 403}:
+ add(5, "authz boundary status")
+ elif status_int is not None and 500 <= status_int <= 599:
+ add(6, "server error status")
+ elif status_int is not None and 300 <= status_int <= 399:
+ add(2, "redirect status")
+ if item.get("toolType"):
+ tool = str(item.get("toolType"))
+ if tool.lower() in {"scanner", "extensions", "intruder", "repeater"}:
+ add(3, f"burp tool:{tool}")
+
+ return score, reasons
+
+
+def _edits_payload(
+ method: str | None = None,
+ path: str | None = None,
+ target_host: str | None = None,
+ target_port: int | None = None,
+ use_https: bool | None = None,
+ headers: dict[str, str] | None = None,
+ add_headers: dict[str, str] | None = None,
+ remove_headers: list[str] | None = None,
+ body: str | None = None,
+ path_replace_from: str | None = None,
+ path_replace_to: str | None = None,
+ body_replace_from: str | None = None,
+ body_replace_to: str | None = None,
+ status_code: int | None = None,
+ reason_phrase: str | None = None,
+) -> dict[str, Any]:
+ return {
+ "method": method,
+ "path": path,
+ "targetHost": target_host,
+ "targetPort": target_port,
+ "useHttps": use_https,
+ "headers": headers,
+ "addHeaders": add_headers,
+ "removeHeaders": remove_headers,
+ "body": body,
+ "pathReplaceFrom": path_replace_from,
+ "pathReplaceTo": path_replace_to,
+ "bodyReplaceFrom": body_replace_from,
+ "bodyReplaceTo": body_replace_to,
+ "statusCode": status_code,
+ "reasonPhrase": reason_phrase,
+ }
+
+
+@mcp.tool()
+def burp_bridge_status() -> dict[str, Any]:
+ """检查 Windows Burp 侧桥接状态、Burp 版本、实时缓冲区容量、规则数量与当前监听地址。"""
+ return _request_json("/health")
+
+
+@mcp.tool()
+def burp_config_get() -> dict[str, Any]:
+ """读取 Burp 扩展当前配置。适合确认端口、body 截断、scope-only、静态资源过滤和规则数量。"""
+ return _request_json("/api/config")
+
+
+@mcp.tool()
+def burp_live_poll(
+ after_seq: int = 0,
+ limit: int = 20,
+ text: str | None = None,
+ host: str | None = None,
+ path: str | None = None,
+ method: str | None = None,
+ has_response: bool | None = None,
+ in_scope: bool | None = None,
+ include_bodies: bool = False,
+) -> dict[str, Any]:
+ """从实时 ring buffer 增量读取 Burp Proxy 流量。优先用这个做低噪声轮询,再按 flowId 拉详情。"""
+ return _request_json(
+ "/api/flows",
+ query={
+ "afterSeq": after_seq,
+ "limit": limit,
+ "text": text,
+ "host": host,
+ "path": path,
+ "method": method,
+ "hasResponse": has_response,
+ "inScope": in_scope,
+ "includeBodies": include_bodies,
+ },
+ )
+
+
+@mcp.tool()
+def burp_flow_get(flow_id: int, source: str = "live", include_bodies: bool = True) -> dict[str, Any]:
+ """读取单条流量的完整细节。source=live/history/logger/selection。"""
+ if source not in {"live", "history", "logger", "selection"}:
+ raise ValueError("source 必须是 live、history、logger 或 selection")
+ if source == "live":
+ path = f"/api/flows/{flow_id}"
+ elif source == "history":
+ path = f"/api/history/{flow_id}"
+ elif source == "logger":
+ path = f"/api/logger/flows/{flow_id}"
+ else:
+ path = f"/api/selection/flows/{flow_id}"
+ return _request_json(path, query={"includeBodies": include_bodies})
+
+
+@mcp.tool()
+def burp_logger_poll(
+ after_seq: int = 0,
+ limit: int = 20,
+ text: str | None = None,
+ host: str | None = None,
+ path: str | None = None,
+ method: str | None = None,
+ tool_type: str | None = None,
+ has_response: bool | None = None,
+ in_scope: bool | None = None,
+ include_bodies: bool = False,
+) -> dict[str, Any]:
+ """读取 Burp 内部 HTTP 工具流量(logger-like)。适合看 Repeater/Intruder/Scanner/插件 fuzz 等非 Proxy 面板流量。"""
+ return _request_json(
+ "/api/logger/flows",
+ query={
+ "afterSeq": after_seq,
+ "limit": limit,
+ "text": text,
+ "host": host,
+ "path": path,
+ "method": method,
+ "toolType": tool_type,
+ "hasResponse": has_response,
+ "inScope": in_scope,
+ "includeBodies": include_bodies,
+ },
+ )
+
+
+@mcp.tool()
+def burp_logger_flow_get(flow_id: int, include_bodies: bool = True) -> dict[str, Any]:
+ """读取单条 Burp 内部 HTTP 工具流量详情。"""
+ return _request_json(f"/api/logger/flows/{flow_id}", query={"includeBodies": include_bodies})
+
+
+@mcp.tool()
+def burp_selection_poll(
+ after_seq: int = 0,
+ limit: int = 20,
+ text: str | None = None,
+ host: str | None = None,
+ path: str | None = None,
+ method: str | None = None,
+ has_response: bool | None = None,
+ include_bodies: bool = False,
+) -> dict[str, Any]:
+ """读取 Burp HotKey/command-palette 捕获的选中流量。人在 Burp 中选中后触发 Capture selection for AI,再由 AI 拉取。"""
+ return _request_json(
+ "/api/selection/flows",
+ query={
+ "afterSeq": after_seq,
+ "limit": limit,
+ "text": text,
+ "host": host,
+ "path": path,
+ "method": method,
+ "hasResponse": has_response,
+ "includeBodies": include_bodies,
+ },
+ )
+
+
+@mcp.tool()
+def burp_selection_get(flow_id: int, include_bodies: bool = True) -> dict[str, Any]:
+ """读取一条由 Burp HotKey/command-palette 捕获的 selection flow 详情。"""
+ return burp_flow_get(flow_id=flow_id, source="selection", include_bodies=include_bodies)
+
+
+@mcp.tool()
+def burp_history_search(
+ query: str | None = None,
+ regex: bool = False,
+ limit: int = 20,
+ offset: int = 0,
+ host_contains: str | None = None,
+ path_contains: str | None = None,
+ method: str | None = None,
+ in_scope: bool | None = None,
+ has_response: bool | None = None,
+ status_min: int | None = None,
+ status_max: int | None = None,
+ include_bodies: bool = False,
+ ignore_static: bool | None = True,
+) -> dict[str, Any]:
+ """搜索 Burp 全量 Proxy 历史。适合查旧流量、按关键字回溯登录/API/upload 等关键链路。"""
+ return _request_json(
+ "/api/history/search",
+ method="POST",
+ payload={
+ "query": query,
+ "regex": regex,
+ "limit": limit,
+ "offset": offset,
+ "hostContains": host_contains,
+ "pathContains": path_contains,
+ "method": method,
+ "inScope": in_scope,
+ "hasResponse": has_response,
+ "statusMin": status_min,
+ "statusMax": status_max,
+ "includeBodies": include_bodies,
+ "ignoreStatic": ignore_static,
+ },
+ )
+
+
+@mcp.tool()
+def burp_send_to_repeater(flow_id: int, source: str = "live", tab_name: str = "AI review") -> dict[str, Any]:
+ """把选中的请求发到 Burp Repeater,方便继续手工验证或配合 AI 给出的下一步变体。"""
+ if source not in {"live", "history", "logger", "selection"}:
+ raise ValueError("source 必须是 live、history、logger 或 selection")
+ return _request_json(
+ "/api/actions/send-to-repeater",
+ method="POST",
+ payload={"id": flow_id, "source": source, "tabName": tab_name},
+ )
+
+
+@mcp.tool()
+def burp_clear_live_buffer() -> dict[str, Any]:
+ """清空实时流量缓冲区,适合开始一个新的验证阶段前先降噪。"""
+ return _request_json("/api/actions/clear-buffer", method="POST", payload={})
+
+
+@mcp.tool()
+def burp_clear_logger_buffer() -> dict[str, Any]:
+ """清空 Burp 内部工具/logger-like 流量缓冲区。适合在 fuzz、重放或规则联调前先降噪。"""
+ return _request_json("/api/actions/clear-logger-buffer", method="POST", payload={})
+
+
+@mcp.tool()
+def burp_clear_selection_buffer() -> dict[str, Any]:
+ """清空 HotKey/command-palette selection buffer。"""
+ return _request_json("/api/actions/clear-selection-buffer", method="POST", payload={})
+
+
+@mcp.tool()
+def burp_export_flow_bundle(flow_id: int, source: str = "history") -> dict[str, Any]:
+ """导出一条 flow 的完整原始 request/response 到 bridge 所在主机的临时目录。适合超大包场景下安全取证。"""
+ if source not in {"live", "history", "logger", "selection"}:
+ raise ValueError("source 必须是 live、history、logger 或 selection")
+ return _request_json(
+ "/api/actions/export-flow-bundle",
+ method="POST",
+ payload={"id": flow_id, "source": source},
+ )
+
+
+@mcp.tool()
+def burp_live_overview(after_seq: int = 0, limit: int = 80) -> dict[str, Any]:
+ """快速汇总最近实时流量,按主机、状态码、标签统计,便于 AI 先做渗透流量定向。"""
+ data = burp_live_poll(after_seq=after_seq, limit=limit, include_bodies=False)
+ items = data.get("items", [])
+ host_counter: Counter[str] = Counter()
+ status_counter: Counter[str] = Counter()
+ tag_counter: Counter[str] = Counter()
+ interesting_by_host: dict[str, list[dict[str, Any]]] = defaultdict(list)
+
+ for item in items:
+ host = item.get("host") or ""
+ host_counter[host] += 1
+ status = item.get("statusCode")
+ status_counter[str(status) if status is not None else "pending"] += 1
+ for tag in item.get("tags", []):
+ tag_counter[tag] += 1
+ if len(interesting_by_host[host]) < 5:
+ interesting_by_host[host].append(
+ {
+ "flowId": item.get("flowId"),
+ "method": item.get("method"),
+ "path": item.get("path"),
+ "statusCode": item.get("statusCode"),
+ "tags": item.get("tags"),
+ "requestRuleHits": item.get("requestRuleHits", []),
+ "responseRuleHits": item.get("responseRuleHits", []),
+ }
+ )
+
+ return {
+ "ok": True,
+ "item": {
+ "count": len(items),
+ "latestCursor": data.get("latestCursor"),
+ "byHost": host_counter.most_common(),
+ "byStatus": status_counter.most_common(),
+ "byTag": tag_counter.most_common(),
+ "interestingByHost": dict(interesting_by_host),
+ },
+ }
+
+
+@mcp.tool()
+def burp_logger_overview(after_seq: int = 0, limit: int = 80) -> dict[str, Any]:
+ """快速汇总 Burp 内部工具流量,尤其适合看 fuzz 插件/Repeater/Intruder/Scanner 的请求响应。"""
+ data = burp_logger_poll(after_seq=after_seq, limit=limit, include_bodies=False)
+ items = data.get("items", [])
+ host_counter: Counter[str] = Counter()
+ status_counter: Counter[str] = Counter()
+ tool_counter: Counter[str] = Counter()
+ interesting_by_tool: dict[str, list[dict[str, Any]]] = defaultdict(list)
+
+ for item in items:
+ host = item.get("host") or ""
+ host_counter[host] += 1
+ status = item.get("statusCode")
+ status_counter[str(status) if status is not None else "pending"] += 1
+ tool = item.get("toolType") or ""
+ tool_counter[tool] += 1
+ if len(interesting_by_tool[tool]) < 5:
+ interesting_by_tool[tool].append(
+ {
+ "flowId": item.get("flowId"),
+ "method": item.get("method"),
+ "path": item.get("path"),
+ "statusCode": item.get("statusCode"),
+ "host": item.get("host"),
+ }
+ )
+
+ return {
+ "ok": True,
+ "item": {
+ "count": len(items),
+ "latestCursor": data.get("latestCursor"),
+ "byHost": host_counter.most_common(),
+ "byStatus": status_counter.most_common(),
+ "byToolType": tool_counter.most_common(),
+ "interestingByToolType": dict(interesting_by_tool),
+ },
+ }
+
+
+@mcp.tool()
+def burp_target_overview(
+ host: str | None = None,
+ text: str | None = None,
+ path: str | None = None,
+ sources: str = "all",
+ limit: int = 80,
+ include_static: bool = False,
+ include_extensions: bool = True,
+ candidate_limit: int = 20,
+) -> dict[str, Any]:
+ """按被测目标聚合 live/history/logger/selection 流量。适合 AI 围绕一个 host 做入口、接口、状态码和高价值候选请求画像。"""
+ selected_sources = _parse_source_csv(sources)
+ per_source_limit = max(1, min(limit, 200))
+ max_candidates = max(1, min(candidate_limit, 50))
+ collected: list[dict[str, Any]] = []
+ source_errors: dict[str, str] = {}
+
+ if "history" in selected_sources:
+ try:
+ data = burp_history_search(
+ query=text,
+ limit=per_source_limit,
+ host_contains=host,
+ path_contains=path,
+ include_bodies=False,
+ ignore_static=not include_static,
+ )
+ collected.extend(data.get("items", []))
+ except Exception as exc:
+ source_errors["history"] = str(exc)
+
+ if "live" in selected_sources:
+ try:
+ data = burp_live_poll(
+ limit=per_source_limit,
+ text=text,
+ host=host,
+ path=path,
+ include_bodies=False,
+ )
+ items = data.get("items", [])
+ if not include_static:
+ items = [item for item in items if not _is_static_path(item.get("path"))]
+ collected.extend(items)
+ except Exception as exc:
+ source_errors["live"] = str(exc)
+
+ if "logger" in selected_sources:
+ try:
+ data = burp_logger_poll(
+ limit=per_source_limit,
+ text=text,
+ host=host,
+ path=path,
+ include_bodies=False,
+ )
+ items = data.get("items", [])
+ if not include_extensions:
+ items = [item for item in items if str(item.get("toolType") or "").lower() != "extensions"]
+ if not include_static:
+ items = [item for item in items if not _is_static_path(item.get("path"))]
+ collected.extend(items)
+ except Exception as exc:
+ source_errors["logger"] = str(exc)
+
+ if "selection" in selected_sources:
+ try:
+ data = burp_selection_poll(
+ limit=per_source_limit,
+ text=text,
+ host=host,
+ path=path,
+ include_bodies=False,
+ )
+ items = data.get("items", [])
+ if not include_static:
+ items = [item for item in items if not _is_static_path(item.get("path"))]
+ collected.extend(items)
+ except Exception as exc:
+ source_errors["selection"] = str(exc)
+
+ by_source: Counter[str] = Counter()
+ by_host: Counter[str] = Counter()
+ by_status: Counter[str] = Counter()
+ by_method: Counter[str] = Counter()
+ by_tool_type: Counter[str] = Counter()
+ by_tag: Counter[str] = Counter()
+ by_endpoint: Counter[str] = Counter()
+ endpoint_samples: dict[str, dict[str, Any]] = {}
+ interesting: list[dict[str, Any]] = []
+ seen_candidate_keys: set[tuple[str, Any]] = set()
+
+ for item in collected:
+ source = _counter_key(item.get("source"))
+ by_source[source] += 1
+ by_host[_counter_key(item.get("host"))] += 1
+ by_method[_counter_key(item.get("method"))] += 1
+ by_status[_counter_key(item.get("statusCode"), "pending")] += 1
+ tool_type = item.get("toolType")
+ if tool_type:
+ by_tool_type[str(tool_type)] += 1
+ for tag in item.get("tags") or []:
+ by_tag[str(tag)] += 1
+
+ endpoint_key = f"{_counter_key(item.get('method'), '?')} {_normalize_endpoint_path(item.get('path'))}"
+ by_endpoint[endpoint_key] += 1
+ endpoint_samples.setdefault(endpoint_key, _flow_card(item))
+
+ score, reasons = _score_target_flow(item)
+ if score > 0:
+ key = (source, item.get("flowId"))
+ if key in seen_candidate_keys:
+ continue
+ seen_candidate_keys.add(key)
+ interesting.append(_flow_card(item, source=source, reasons=reasons, score=score))
+
+ interesting.sort(key=lambda card: (-int(card.get("score") or 0), str(card.get("source")), int(card.get("flowId") or 0)))
+ top_endpoints = [
+ {
+ "endpoint": endpoint,
+ "count": count,
+ "sample": endpoint_samples.get(endpoint),
+ }
+ for endpoint, count in by_endpoint.most_common(40)
+ ]
+
+ next_steps = [
+ "Pick a highValueCandidate and inspect exact request/response with the matching getter: source=history/live -> burp_flow_get, source=logger -> burp_logger_flow_get, source=selection -> burp_selection_get.",
+ "Replay only one variable at a time with burp_replay_flow(source=...) after confirming the baseline response.",
+ "If a pattern is reusable, promote it into burp_rule_upsert, burp_bcheck_import, or burp_bambda_import instead of keeping ad-hoc manual steps.",
+ ]
+ if not host:
+ next_steps.insert(0, "Pass host='target.example' for a tighter per-unit view; without host this is only a broad recent/history snapshot.")
+
+ return {
+ "ok": True,
+ "item": {
+ "purpose": "Target-centric traffic map across Proxy history, live Proxy buffer, Burp tool/logger traffic and UI selection.",
+ "filters": {
+ "host": host,
+ "text": text,
+ "path": path,
+ "sources": selected_sources,
+ "perSourceLimit": per_source_limit,
+ "includeStatic": include_static,
+ "includeExtensions": include_extensions,
+ },
+ "count": len(collected),
+ "sourceErrors": source_errors,
+ "bySource": by_source.most_common(),
+ "byHost": by_host.most_common(30),
+ "byStatus": by_status.most_common(),
+ "byMethod": by_method.most_common(),
+ "byToolType": by_tool_type.most_common(),
+ "byTag": by_tag.most_common(),
+ "topEndpoints": top_endpoints,
+ "highValueCandidates": interesting[:max_candidates],
+ "nextSteps": next_steps,
+ },
+ }
+
+
+@mcp.tool()
+def burp_extension_activity_overview(
+ after_seq: int = 0,
+ limit: int = 80,
+ host: str | None = None,
+ path: str | None = None,
+ text: str | None = None,
+ include_sample_details: bool = False,
+ sample_limit: int = 5,
+) -> dict[str, Any]:
+ """聚合其他 Burp 扩展产生的 HTTP 流量,帮助 AI 从已加载插件的探测手法中提取线索;不直接调用插件内部接口。"""
+ data = burp_logger_poll(
+ after_seq=after_seq,
+ limit=limit,
+ text=text,
+ host=host,
+ path=path,
+ tool_type="Extensions",
+ include_bodies=False,
+ )
+ items = data.get("items", [])
+ host_counter: Counter[str] = Counter()
+ path_counter: Counter[str] = Counter()
+ status_counter: Counter[str] = Counter()
+ method_counter: Counter[str] = Counter()
+ candidates: list[dict[str, Any]] = []
+
+ for item in items:
+ item_host = item.get("host") or ""
+ item_path = item.get("path") or ""
+ host_counter[item_host] += 1
+ path_counter[f"{item.get('method') or '?'} {item_path}"] += 1
+ method_counter[item.get("method") or ""] += 1
+ status = item.get("statusCode")
+ status_counter[str(status) if status is not None else "pending"] += 1
+ if len(candidates) < max(1, min(sample_limit, 20)):
+ candidates.append(
+ {
+ "flowId": item.get("flowId"),
+ "method": item.get("method"),
+ "host": item_host,
+ "path": item_path,
+ "statusCode": item.get("statusCode"),
+ "mimeType": item.get("mimeType"),
+ "tags": item.get("tags"),
+ }
+ )
+
+ sample_details: list[dict[str, Any]] = []
+ if include_sample_details:
+ for candidate in candidates[: max(1, min(sample_limit, 10))]:
+ flow_id = candidate.get("flowId")
+ if flow_id is None:
+ continue
+ try:
+ detail = burp_logger_flow_get(flow_id=int(flow_id), include_bodies=False).get("item", {})
+ request = detail.get("request") or {}
+ response = detail.get("response") or {}
+ sample_details.append(
+ {
+ "flowId": flow_id,
+ "requestStartLine": request.get("startLine"),
+ "requestHeaderCount": request.get("headerCount"),
+ "requestBodyBytes": request.get("bodyBytes"),
+ "responseStartLine": response.get("startLine") if response else None,
+ "responseContentType": response.get("contentType") if response else None,
+ "responseBodyBytes": response.get("bodyBytes") if response else None,
+ }
+ )
+ except Exception as exc:
+ sample_details.append({"flowId": flow_id, "error": str(exc)})
+
+ return {
+ "ok": True,
+ "item": {
+ "purpose": "Infer useful testing ideas from HTTP traffic generated by other loaded Burp extensions.",
+ "directPluginInvocationSupported": False,
+ "count": len(items),
+ "latestCursor": data.get("latestCursor"),
+ "byHost": host_counter.most_common(),
+ "byPath": path_counter.most_common(30),
+ "byStatus": status_counter.most_common(),
+ "byMethod": method_counter.most_common(),
+ "candidateFlows": candidates,
+ "sampleDetails": sample_details if include_sample_details else None,
+ "nextSteps": [
+ "Use burp_logger_flow_get(flowId) on candidate flows to inspect exact plugin-generated requests.",
+ "Replay promising requests with burp_replay_flow(source='logger') or convert patterns into rewrite rules/BChecks/Bambdas.",
+ "For interface-level control, add a specific adapter only for plugins that expose a stable API or local endpoint."
+ ],
+ },
+ }
+
+
+@mcp.tool()
+def burp_export_flow(flow_id: int, source: str = "live", include_bodies: bool = True, label: str | None = None) -> dict[str, Any]:
+ """导出一条关键流量为本地 JSON 证据文件,便于归档、复盘或拼接正式漏洞报告。"""
+ if source == "logger":
+ detail = burp_logger_flow_get(flow_id=flow_id, include_bodies=include_bodies)
+ elif source == "selection":
+ detail = burp_selection_get(flow_id=flow_id, include_bodies=include_bodies)
+ else:
+ detail = burp_flow_get(flow_id=flow_id, source=source, include_bodies=include_bodies)
+ ARTIFACT_ROOT.mkdir(parents=True, exist_ok=True)
+ safe_label = (label or f"{source}-{flow_id}").replace("/", "_").replace(" ", "-")
+ output_path = ARTIFACT_ROOT / f"burp-flow-{safe_label}-{_timestamp()}.json"
+ output_path.write_text(json.dumps(detail, ensure_ascii=False, indent=2), encoding="utf-8")
+ return {"ok": True, "message": "flow exported", "flowId": flow_id, "source": source, "path": str(output_path)}
+
+
+@mcp.tool()
+def burp_replay_flow(
+ flow_id: int,
+ source: str = "history",
+ method: str | None = None,
+ path: str | None = None,
+ target_host: str | None = None,
+ target_port: int | None = None,
+ use_https: bool | None = None,
+ headers: dict[str, str] | None = None,
+ add_headers: dict[str, str] | None = None,
+ remove_headers: list[str] | None = None,
+ body: str | None = None,
+ path_replace_from: str | None = None,
+ path_replace_to: str | None = None,
+ body_replace_from: str | None = None,
+ body_replace_to: str | None = None,
+ apply_rules: bool = False,
+ send_to_repeater: bool = False,
+ repeater_tab_name: str = "AI replay",
+ include_bodies: bool = True,
+) -> dict[str, Any]:
+ """基于 live/history 里的已有请求进行改包重发。适合 AI 修改 token、body、header、path 后快速验证。"""
+ if source not in {"live", "history", "logger", "selection"}:
+ raise ValueError("source 必须是 live、history、logger 或 selection")
+ payload = {
+ "id": flow_id,
+ "source": source,
+ "applyRules": apply_rules,
+ "sendToRepeater": send_to_repeater,
+ "repeaterTabName": repeater_tab_name,
+ "includeBodies": include_bodies,
+ }
+ payload.update(
+ _edits_payload(
+ method=method,
+ path=path,
+ target_host=target_host,
+ target_port=target_port,
+ use_https=use_https,
+ headers=headers,
+ add_headers=add_headers,
+ remove_headers=remove_headers,
+ body=body,
+ path_replace_from=path_replace_from,
+ path_replace_to=path_replace_to,
+ body_replace_from=body_replace_from,
+ body_replace_to=body_replace_to,
+ )
+ )
+ return _request_json("/api/replay/flow", method="POST", payload=payload)
+
+
+@mcp.tool()
+def burp_send_raw_request(
+ raw_request: str,
+ target_host: str,
+ target_port: int,
+ use_https: bool = False,
+ apply_rules: bool = False,
+ send_to_repeater: bool = False,
+ repeater_tab_name: str = "AI raw replay",
+ include_bodies: bool = True,
+) -> dict[str, Any]:
+ """直接发送原始 HTTP 请求文本。适合 AI 组合完整数据包后通过 Burp 内部 HTTP 栈重放。"""
+ return _request_json(
+ "/api/replay/raw",
+ method="POST",
+ payload={
+ "rawRequest": raw_request,
+ "targetHost": target_host,
+ "targetPort": target_port,
+ "useHttps": use_https,
+ "applyRules": apply_rules,
+ "sendToRepeater": send_to_repeater,
+ "repeaterTabName": repeater_tab_name,
+ "includeBodies": include_bodies,
+ },
+ )
+
+
+@mcp.tool()
+def burp_rules_list() -> dict[str, Any]:
+ """列出当前启用/禁用的自动请求/响应改写规则,包含 actionSchema 说明 modify/drop/spoof 与 applyTo 语义。"""
+ return _request_json("/api/rules")
+
+
+@mcp.tool()
+def burp_rule_upsert(
+ direction: str,
+ action: str = "modify",
+ apply_to: str = "proxy",
+ name: str | None = None,
+ rule_id: str | None = None,
+ enabled: bool = True,
+ match_host_contains: str | None = None,
+ match_path_contains: str | None = None,
+ match_method: str | None = None,
+ match_body_contains: str | None = None,
+ match_status_min: int | None = None,
+ match_status_max: int | None = None,
+ method: str | None = None,
+ path: str | None = None,
+ target_host: str | None = None,
+ target_port: int | None = None,
+ use_https: bool | None = None,
+ headers: dict[str, str] | None = None,
+ add_headers: dict[str, str] | None = None,
+ remove_headers: list[str] | None = None,
+ body: str | None = None,
+ path_replace_from: str | None = None,
+ path_replace_to: str | None = None,
+ body_replace_from: str | None = None,
+ body_replace_to: str | None = None,
+ status_code: int | None = None,
+ reason_phrase: str | None = None,
+) -> dict[str, Any]:
+ """新增或更新自动规则。action=modify 改写并放行;action=drop 丢弃匹配消息;action=spoof 用规则字段构造替代响应;apply_to=proxy/tool/all 控制作用面。"""
+ if direction not in {"request", "response"}:
+ raise ValueError("direction 必须是 request 或 response")
+ if action not in {"modify", "drop", "spoof"}:
+ raise ValueError("action 必须是 modify、drop 或 spoof")
+ if apply_to not in {"proxy", "tool", "all"}:
+ raise ValueError("apply_to 必须是 proxy、tool 或 all")
+ payload = {
+ "id": rule_id,
+ "name": name,
+ "direction": direction,
+ "action": action,
+ "applyTo": apply_to,
+ "enabled": enabled,
+ "matchHostContains": match_host_contains,
+ "matchPathContains": match_path_contains,
+ "matchMethod": match_method,
+ "matchBodyContains": match_body_contains,
+ "matchStatusMin": match_status_min,
+ "matchStatusMax": match_status_max,
+ }
+ payload.update(
+ _edits_payload(
+ method=method,
+ path=path,
+ target_host=target_host,
+ target_port=target_port,
+ use_https=use_https,
+ headers=headers,
+ add_headers=add_headers,
+ remove_headers=remove_headers,
+ body=body,
+ path_replace_from=path_replace_from,
+ path_replace_to=path_replace_to,
+ body_replace_from=body_replace_from,
+ body_replace_to=body_replace_to,
+ status_code=status_code,
+ reason_phrase=reason_phrase,
+ )
+ )
+ return _request_json("/api/rules", method="POST", payload=payload)
+
+
+@mcp.tool()
+def burp_rule_delete(rule_id: str) -> dict[str, Any]:
+ """删除一条自动改写规则。"""
+ return _request_json(f"/api/rules/{urllib.parse.quote(rule_id, safe='')}", method="DELETE")
+
+
+@mcp.tool()
+def burp_bcheck_import(content: str | None = None, path: str | None = None, replace_existing: bool = True) -> dict[str, Any]:
+ """导入 AI 生成或本地文件中的 BCheck,自定义扩展 Burp Scanner 检查项。content/path 二选一;导入后由 Burp Scanner 官方流程执行。"""
+ if not content and not path:
+ raise ValueError("content 或 path 必须提供一个")
+ if content and path:
+ raise ValueError("content 和 path 只能提供一个")
+ if path:
+ content = Path(path).read_text(encoding="utf-8")
+ return _request_json(
+ "/api/scanner/bchecks/import",
+ method="POST",
+ payload={"content": content, "replaceExisting": replace_existing},
+ )
+
+
+@mcp.tool()
+def burp_bambda_import(content: str | None = None, path: str | None = None) -> dict[str, Any]:
+ """导入 AI 生成或本地文件中的 Bambda 到 Burp Bambda Library。适合把自定义行动/列/过滤器脚本交给 Burp UI 管理和执行。"""
+ if not content and not path:
+ raise ValueError("content 或 path 必须提供一个")
+ if content and path:
+ raise ValueError("content 和 path 只能提供一个")
+ if path:
+ content = Path(path).read_text(encoding="utf-8")
+ return _request_json(
+ "/api/bambdas/import",
+ method="POST",
+ payload={"content": content},
+ )
+
+
+@mcp.tool()
+def burp_mcp_list(section: str = "index", topic: str | None = None, detail: bool = False) -> dict[str, Any]:
+ """分级列出 BurpSuite MCP Bridge 的工具用法。先 section=index 获取目录,再按 section/topic 拉取小块说明,避免一次性占满上下文。"""
+ catalog = _mcp_help_catalog()
+ if section in {"", "index", "root"}:
+ return {
+ "ok": True,
+ "item": {
+ "usage": "Call burp_mcp_list(section='') for topics, then burp_mcp_list(section='', topic='', detail=true) for focused usage.",
+ "sections": [
+ {"section": key, "summary": value["summary"], "topics": list(value["topics"].keys())}
+ for key, value in catalog.items()
+ ],
+ },
+ }
+ if section not in catalog:
+ return {"ok": False, "message": f"unknown section: {section}", "availableSections": list(catalog.keys())}
+ section_data = catalog[section]
+ if not topic:
+ return {
+ "ok": True,
+ "item": {
+ "section": section,
+ "summary": section_data["summary"],
+ "topics": [
+ {"topic": key, "summary": value["summary"]}
+ for key, value in section_data["topics"].items()
+ ],
+ },
+ }
+ topics = section_data["topics"]
+ if topic not in topics:
+ return {"ok": False, "message": f"unknown topic: {topic}", "availableTopics": list(topics.keys())}
+ topic_data = topics[topic]
+ item = {"section": section, "topic": topic, "summary": topic_data["summary"]}
+ if detail:
+ item.update(topic_data)
+ else:
+ item["hint"] = "Set detail=true for parameters and examples."
+ return {"ok": True, "item": item}
+
+
+def _mcp_help_catalog() -> dict[str, Any]:
+ return {
+ "traffic": {
+ "summary": "Read low-noise target-centric, Proxy live/history/logger-like traffic.",
+ "topics": {
+ "target": {
+ "summary": "Target-centric map across history/live/logger/selection, grouped by host/status/method/tool/endpoint with high-value candidates.",
+ "tools": ["burp_target_overview", "burp_flow_get", "burp_logger_flow_get", "burp_selection_get"],
+ "params": {"host": "recommended target host filter", "sources": "all or comma-separated history,live,logger,selection", "include_extensions": "keep plugin-generated target traffic in the same target view"},
+ "example": "burp_target_overview(host='example.com', sources='all', limit=80) -> inspect one highValueCandidate",
+ },
+ "live": {
+ "summary": "Incremental Proxy buffer triage.",
+ "tools": ["burp_live_overview", "burp_live_poll", "burp_flow_get"],
+ "params": {"after_seq": "cursor from latestCursor", "include_bodies": "default false for triage"},
+ "example": "burp_live_overview(after_seq=0, limit=80) -> burp_flow_get(flow_id, source='live')",
+ },
+ "history": {
+ "summary": "Search persisted Proxy history without replaying traffic.",
+ "tools": ["burp_history_search", "burp_flow_get"],
+ "params": {"query": "plain text or regex", "host_contains/path_contains/status_min/status_max": "narrow filters"},
+ "example": "burp_history_search(host_contains='example.com', path_contains='/api', limit=20)",
+ },
+ "logger": {
+ "summary": "Read Burp internal HTTP tool traffic captured after extension load.",
+ "tools": ["burp_logger_overview", "burp_logger_poll", "burp_logger_flow_get"],
+ "params": {"tool_type": "Repeater/Intruder/Scanner/Extensions etc."},
+ "example": "burp_logger_poll(tool_type='Repeater', limit=20)",
+ },
+ "selection": {
+ "summary": "Read items captured from Burp UI selection via command palette/hotkey.",
+ "tools": ["burp_selection_poll", "burp_selection_get", "burp_flow_get"],
+ "params": {"source": "Use source='selection' with flow_get/replay/export/send_to_repeater."},
+ "example": "Trigger 'Burp MCP Bridge: Capture selection for AI' in Burp, then burp_selection_poll(limit=20)",
+ },
+ },
+ },
+ "replay": {
+ "summary": "Replay captured or raw requests with controlled mutations.",
+ "topics": {
+ "flow": {
+ "summary": "Replay live/history request with method/path/header/body edits.",
+ "tools": ["burp_replay_flow"],
+ "params": {"apply_rules": "run rewrite rules before/after replay", "send_to_repeater": "also open request in Repeater"},
+ "example": "burp_replay_flow(flow_id=123, source='history', path_replace_from='id=1', path_replace_to='id=2')",
+ },
+ "raw": {
+ "summary": "Send a fully assembled raw HTTP request through Burp HTTP stack.",
+ "tools": ["burp_send_raw_request"],
+ "params": {"target_host/target_port/use_https": "required target service"},
+ "example": "burp_send_raw_request(raw_request='GET / HTTP/1.1\\r\\nHost: example.com\\r\\n\\r\\n', target_host='example.com', target_port=443, use_https=True)",
+ },
+ },
+ },
+ "rules": {
+ "summary": "Automatic request/response controls with proxy/tool/all scope.",
+ "topics": {
+ "actions": {
+ "summary": "modify/drop/spoof semantics.",
+ "tools": ["burp_rules_list", "burp_rule_upsert", "burp_rule_delete"],
+ "params": {"action": "modify|drop|spoof", "direction": "request|response", "apply_to": "proxy|tool|all"},
+ "example": "burp_rule_upsert(direction='request', action='spoof', apply_to='proxy', match_host_contains='example.com', body='mock')",
+ },
+ "scope": {
+ "summary": "apply_to controls where rules run.",
+ "details": [
+ "proxy: default; only browser/client traffic through Burp Proxy.",
+ "tool: Burp internal tools such as Repeater/Intruder/Scanner when Montoya runtime supports it; extension self-replay is skipped to avoid double-apply.",
+ "all: proxy + supported internal tools."
+ ],
+ },
+ },
+ },
+ "evidence": {
+ "summary": "Export decisive flows without stuffing large bodies into MCP context.",
+ "topics": {
+ "export": {
+ "summary": "Write JSON or raw request/response bundles to disk.",
+ "tools": ["burp_export_flow", "burp_export_flow_bundle"],
+ "params": {"source": "live|history|logger", "include_bodies": "use false for huge flows unless needed"},
+ },
+ },
+ },
+ "official": {
+ "summary": "Runtime-detected Montoya 2026.4.x integrations.",
+ "topics": {
+ "selection": {
+ "summary": "Command palette / HotKey bridge from Burp UI selection to MCP.",
+ "tools": ["burp_selection_poll", "burp_selection_get"],
+ "details": [
+ "Registers 'Burp MCP Bridge: Capture selection for AI' where supported.",
+ "Captured items become source=selection so existing replay/export/repeater tools can operate on them.",
+ "Default hotkey is Ctrl+Alt+M; command palette discovery is preferred if a shortcut conflicts."
+ ],
+ },
+ "compat": {
+ "summary": "Check which optional official APIs are available in the loaded Burp runtime.",
+ "tools": ["burp_bridge_status", "burp_config_get"],
+ "details": [
+ "montoyaCompat.runtimeOptionalFeatures.httpHandlerRequestDropSpoof: official internal-tool request drop/spoof.",
+ "hotKeyApi / hotKeySelectedRequestResponses: command-palette/hotkey groundwork for later selected-row workflows."
+ ],
+ },
+ },
+ },
+ "scanner": {
+ "summary": "Lightweight Scanner control-plane helpers; leave heavy scanning to Burp official Scanner.",
+ "topics": {
+ "bcheck": {
+ "summary": "Import AI-generated or local BCheck content into Burp Scanner custom checks.",
+ "tools": ["burp_bcheck_import"],
+ "params": {"content": "BCheck source text", "path": "local MCP-side .bcheck file", "replace_existing": "default true"},
+ "example": "burp_bcheck_import(path='/tmp/check.bcheck', replace_existing=True)",
+ },
+ },
+ },
+ "bambda": {
+ "summary": "Import scripts into Burp Bambda Library; Burp UI remains the execution surface.",
+ "topics": {
+ "import": {
+ "summary": "Import AI-generated or local Bambda content for custom actions, columns, filters, match/replace, or scan checks.",
+ "tools": ["burp_bambda_import"],
+ "params": {"content": "Bambda script text", "path": "local MCP-side Bambda file"},
+ "example": "burp_bambda_import(path='/tmp/custom-action.bambda')",
+ },
+ "strategy": {
+ "summary": "Use MCP as a script delivery/control plane, not a duplicate Bambda executor.",
+ "details": [
+ "Custom actions in Repeater are Bambda-backed workflows; import the script, then run it in Burp where the selected message/context exists.",
+ "For quick AI automation on captured traffic, prefer MCP replay/rules/selection. For reusable UI workflows, import a Bambda.",
+ "Bambda scripts can execute code, so keep imports explicit and review generated scripts before enabling them broadly."
+ ],
+ },
+ },
+ },
+ "plugins": {
+ "summary": "Observe and learn from other loaded Burp extensions without pretending to call their private APIs.",
+ "topics": {
+ "activity": {
+ "summary": "Cluster HTTP traffic generated by other extensions and return candidate flowIds for AI analysis.",
+ "tools": ["burp_extension_activity_overview", "burp_logger_flow_get", "burp_replay_flow"],
+ "params": {"tool_type": "Internally uses logger-like ToolType=Extensions", "include_sample_details": "small metadata only, no large bodies"},
+ "example": "burp_extension_activity_overview(limit=80, include_sample_details=True)",
+ },
+ "adapters": {
+ "summary": "Interface-level plugin control is only realistic for known/cooperating plugins.",
+ "details": [
+ "Generic Montoya does not expose a stable API to enumerate and call arbitrary extension internals.",
+ "Best generic path: observe extension-generated traffic and convert useful behavior into MCP replay/rules/BChecks/Bambdas.",
+ "For specific plugins that expose local HTTP/RPC/config files, add explicit adapter tools instead of unsafe reflection."
+ ],
+ },
+ },
+ },
+ }
+
+
+if __name__ == "__main__":
+ try:
+ parser = argparse.ArgumentParser(description="BurpSuite MCP Bridge server")
+ parser.add_argument("--transport", choices=["stdio", "streamable-http", "sse"], default=MCP_TRANSPORT)
+ parser.add_argument("--host", default=MCP_SERVER_HOST, help="Host for HTTP MCP transports")
+ parser.add_argument("--port", type=int, default=MCP_SERVER_PORT, help="Port for HTTP MCP transports")
+ parser.add_argument("--path", default=MCP_SERVER_PATH, help="Path for Streamable HTTP MCP transport")
+ args = parser.parse_args()
+
+ mcp.settings.host = args.host
+ mcp.settings.port = args.port
+ mcp.settings.streamable_http_path = args.path
+ mcp.run(transport=args.transport)
+ except Exception as exc: # pragma: no cover
+ print(f"[burpsuite-mcp-bridge] fatal: {exc}", file=os.sys.stderr)
+ raise
diff --git a/scripts/generate_plugins_json.py b/scripts/generate_plugins_json.py
index 0923e96f..a739b1ad 100644
--- a/scripts/generate_plugins_json.py
+++ b/scripts/generate_plugins_json.py
@@ -52,6 +52,9 @@
"mturac/everything-openai-codex",
}
EXTRA_MIRROR_PATHS = {
+ # BurpSuite MCP Bridge needs its Python MCP runtime and Burp extension JARs
+ # mirrored with the plugin manifest so marketplace installs are usable.
+ "6jeffr3y/burpsuite-mcp-bridge": ("wsl-mcp", "burp-plugin"),
# Staff Engineer Mode exposes one router skill and loads routed specialist
# files from a top-level specialists/ directory at runtime.
"sirmarkz/staff-engineer-mode": ("specialists",),