Skip to main content
Glama
README.md
# pentest-kb MCP Server

渗透测试经验库 MCP 服务器。基于 [MCP (Model Context Protocol)](https://modelcontextprotocol.io) 提供检索、新增、列出等工具,用于沉淀和复用渗透测试实战经验。

## 这个项目解决了什么问题

**背景痛点:**
- 渗透测试经验分散在笔记、聊天记录、个人记忆里,难以检索和复用,遇到同类问题(如 WAF 绕过、403 绕过)常常要重新搜索
- Agent 默认没有访问个人经验库的能力,回答渗透测试问题时只能依赖通用知识,缺少实战经验支撑,容易给出泛泛而谈的建议
- 经验无法沉淀、无法跨场景复用,个人或团队积累的知识难以形成体系

**本项目解决:**
- 把渗透测试经验统一沉淀到 PostgreSQL(Supabase)数据库,结构化存储
- 通过 MCP 协议把经验库接入 Agent,让 Agent 能直接**检索**(`search_experience`)、**新增**(`add_experience`)、**列出**(`list_all_experiences`)经验
- 检索基于 **BM25 相关性排序**(jieba 中文分词),比简单模糊匹配更准确
- 让 Agent 在实战场景下基于个人经验库作答,而不是只靠通用知识

## 功能

- `search_experience(keyword, tags_filter)`:基于 BM25 相关性排序检索经验库(仅已审批记录),支持中文分词,返回 Top 10;`tags_filter` 可按场景标签精确过滤(如 `["WAF绕过"]`)
- `add_experience(title, detail, scenario_tags, tool_code, tool_type, status)`:新增经验。`status='draft'` 存为待审批草稿(默认),`status='approved'` 直接入库;写入前自动做**脱敏校验**(检测真实 IP、域名、凭据、云厂商 AccessKey、JWT、私钥、手机号,命中则拒绝)
- `list_all_experiences(limit, offset)`:分页列出经验库中所有已审批记录的标题(默认每页 50 条,最大 200)
- `find_similar(title, detail)`:查重,查找与给定内容相似的已入库记录
- `get_experience(experience_id)`:按 id 获取一条经验的完整内容(标题、详情、标签、工具代码、状态等)
- `update_experience(experience_id, title, detail, scenario_tags, tool_code, tool_type, status)`:更新一条经验的字段(只更新传入字段,未传字段保持不变;修改前自动脱敏校验)
- `list_pending_experiences()`:列出待审批草稿,并提示每条草稿可能重复的已入库记录
- `approve_experience(experience_id, merge_with_id)`:审批通过草稿;提供 `merge_with_id` 时合并进指定记录(详情追加、标签合并、工具信息补全)后删除草稿
- `reject_experience(experience_id)`:拒绝草稿(**软删除**,记录保留为 `rejected`,可恢复)
- `delete_experience(experience_id)`:软删除已审批经验(状态置为 `deleted`,不参与检索,可恢复)
- `restore_experience(experience_id)`:恢复软删除记录(被拒草稿→`draft`,被删经验→`approved`)
- `list_deleted_experiences()`:列出所有软删除记录(回收站),便于恢复或彻底清理
- `purge_experiences(days)`:物理删除软删除超过指定天数的记录(默认 30 天,不可恢复,请谨慎)

## 经验沉淀与审批

为避免自动沉淀产生冗长内容和敏感信息泄露,采用"**半自动沉淀 + 强制脱敏 + 人工审批**"流程:

```
实战结束 → Agent 生成经验草稿(status='draft',结构化 + 限长 + 脱敏)
        → 草稿进入待审批状态(不直接入库,不参与检索)
        → 用户审批(list_pending 查看 → approve / reject / merge)
        → 通过后才正式入库(status='approved')
```

**脱敏防线**:`add_experience` 写入前自动检测真实 IP 地址、域名、邮箱、凭据(含中文"密码/口令/密钥/账号"等)、云厂商 AccessKey(AWS/Aliyun/Tencent)、JWT、私钥块、手机号,命中即拒绝写入,要求替换为占位符(如 `<目标URL>`、`<目标域名>`)。私网/回环/链路本地等特殊 IP 与白名单域名(`example.com` 等)允许入库。

**查重防线**:审批时 `list_pending_experiences` 自动提示每条草稿可能重复的已入库记录,用户可选择跳过、合并或仍新增。

> **直接入库 vs 草稿审批**:`add_experience` 支持 `status='approved'` 直接入库,仅用于用户手动确认的录入场景;AI 工作流(见 SKILL.md)一律要求生成 `draft` 草稿并经审批,不得直接入库。

## 依赖

- Python 3.10+
- `mcp`(MCP Python SDK)
- `psycopg2`(PostgreSQL 驱动)
- `jieba`(中文分词,启动时自动加载根目录 `pentest_dict.txt` 领域词典)
- `rank_bm25`(BM25 检索算法)
- 一个 PostgreSQL 数据库(如 Supabase)

安装依赖:

```bash
pip install -r requirements.txt
```

依赖清单见 `requirements.txt`(已锁定版本区间,注意 `mcp` 需为 2.x)。

## 数据库初始化

在 PostgreSQL(如 Supabase)中执行仓库根目录的 `schema.sql`(幂等,可重复执行):

```bash
# 方式一:Supabase 控制台 → SQL Editor → 粘贴 schema.sql 内容执行
# 方式二:命令行(需已配置 psql)
psql "$PENTEST_KB_DB_CONNECTION_STRING" -f schema.sql
```

表结构如下(`schema.sql` 为唯一维护来源,README 不再重复贴 SQL):

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `id` | uuid PK | 主键,默认 `gen_random_uuid()` |
| `created_at` | timestamptz | 创建时间 |
| `title` | text | 经验标题 |
| `scenario_tags` | jsonb | 场景标签数组,如 `["WAF绕过","SQL注入"]` |
| `experience_detail` | text | 经验详情 |
| `tool_code` | text | 利用/工具代码 |
| `tool_type` | text | 工具类型,如 sqlmap、burp |
| `status` | text | `approved`(已审批)/ `draft`(待审批草稿)/ `rejected`(被拒,软删)/ `deleted`(软删) |
| `deleted_at` | timestamptz | 软删除时间(`rejected`/`deleted` 时记录,用于保留期清理) |

> **可选:语义检索列**(当前代码未使用,预留)
> 如需接入向量语义检索,取消 `schema.sql` 末尾注释并执行(需先启用 pgvector 扩展)。

## 配置

数据库连接信息通过环境变量注入,**请勿在代码中硬编码凭据**:

| 环境变量 | 说明 |
| --- | --- |
| `PENTEST_KB_DB_HOST` | 数据库主机地址 |
| `PENTEST_KB_DB_PORT` | 端口(默认 5432) |
| `PENTEST_KB_DB_NAME` | 数据库名(默认 postgres) |
| `PENTEST_KB_DB_USER` | 数据库用户名 |
| `PENTEST_KB_DB_PASSWORD` | 数据库密码 |
| `PENTEST_KB_DB_MAXCONN` | 连接池最大连接数(可选,默认 10) |

### MCP 客户端配置

在 MCP 客户端中注册服务器,参考 `mcp.example.json`:

```json
{
  "mcpServers": {
    "pentest-kb": {
      "command": "python",
      "args": ["/absolute/path/to/pentest_kb_mcp.py"],
      "env": {
        "PENTEST_KB_DB_HOST": "your-supabase-host.pooler.supabase.com",
        "PENTEST_KB_DB_PORT": "5432",
        "PENTEST_KB_DB_NAME": "postgres",
        "PENTEST_KB_DB_USER": "postgres.your-project-ref",
        "PENTEST_KB_DB_PASSWORD": "your-database-password"
      }
    }
  }
}
```

## 使用

在 MCP 客户端中调用工具即可,例如:

```
搜索:search_experience(keyword="WAF绕过")   # BM25 相关性排序
搜索+标签过滤:search_experience(keyword="绕过", tags_filter=["WAF绕过"])   # 只看 WAF 相关
新增(直接入库,仅手动操作):add_experience(title="Nginx 403 绕过", detail="...", scenario_tags=["WAF绕过"], tool_type="burp", status="approved")
新增草稿:add_experience(title="...", detail="...")   # 默认 status='draft',待审批
查重:find_similar(title="...", detail="...")
查看单条:get_experience(experience_id="...")
修改:update_experience(experience_id="...", detail="...")   # 只更新传入字段
查看草稿:list_pending_experiences()
审批:approve_experience(experience_id="...")   # 或 merge_with_id 合并
拒绝:reject_experience(experience_id="...")   # 软删除,可恢复
删除:delete_experience(experience_id="...")   # 软删除已审批经验
恢复:restore_experience(experience_id="...")
回收站:list_deleted_experiences()
清理:purge_experiences(days=30)   # 物理删除超期软删记录
列出:list_all_experiences(limit=50, offset=0)   # 分页
```

## Skill 封装

已封装为自定义 Skill,文件位于项目根目录 `SKILL.md`,按执行流程组织为六个阶段加一个任务收尾动作:

- 阶段一:意图判断
- 阶段二:信息收集优先
- 阶段三:查库触发
- 阶段四:结果引用与回答
- 阶段五:执行与豁免规范(贯穿全流程:`[阶段X|CP-NN]` 进度自检、阶段检查点、工具/文件操作分级、全局删除禁令、UTF-8 追加式写入等)
- 阶段六:经验沉淀
- 任务收尾:终止检查点、汇报 `unknown/` 与 `trash/`、原样保留工作目录

配套**任务档案制度**:每个目标在 `<工作目录>/<目标标识>/` 下维护 `notes.md`(唯一事实源,含授权与范围、目标信息、JS 提取物、OSINT、文件登记、检查点流水等固定章节),并配套 `scripts/`、`downloads/`、`unknown/`、`trash/` 四个目录。核心约束:追加式写入(UTF-8)、文件产出必登记、删除只移不删、来历不明文件先溯源再处置。

将 `SKILL.md` 放入自定义 Skill 目录即可加载。

## 安全说明

- 数据库凭据仅通过环境变量注入,仓库中不包含任何真实连接信息
- 请定期轮换数据库密码,避免使用弱口令

TDQS

A3.7/5.0

Scored across 13 tools

Disambiguation4/5

Most tools have clearly distinct purposes: the three list_* tools are scoped by status (all/pending/deleted), and search vs. list vs. find_similar are distinguishable. However, update_experience can also set status to approved/rejected, overlapping with the dedicated approve_experience and reject_experience tools, and the delete/reject/purge triad requires careful reading to tell apart.

Naming Consistency5/5

All 13 tools follow a consistent snake_case verb_noun pattern (list_*, get_*, add_*, update_*, delete_*, restore_*, approve_*, reject_*, search_experience, find_similar, purge_experiences). No convention mixing.

Tool Count5/5

13 tools is well-scoped for a knowledge base with CRUD, search, moderation workflow, dedup, and soft-delete lifecycle. Each tool earns its place with a distinct role.

Completeness5/5

Full lifecycle is covered: create/add, get, update, search, paginated listing, approval/rejection moderation, dedup checking, soft-delete, restore, and physical purge. No obvious dead ends for the stated domain.

Maintenance

ActivityMaintained
ResponsivenessNo issues