fncreator22/sentinel-mcp
GitHub: fncreator22/sentinel-mcp
一款通过 MCP 协议与 LLM 编程助手集成的三阶段安全护栏代理,在 AI 执行操作前进行分级风险评估与拦截。
Stars: 3 | Forks: 0
# Sentinel






**一个专为 LLM 驱动的编程助手设计的三阶段护栏代理。**
Sentinel 部署在 LLM 代理与其执行环境之间,在执行每一个拟议的操作前进行审查。它通过 Model Context Protocol (MCP) 与 Claude Code、Cursor 和 CodeX 等工具集成,充当一个始终在线的安全层,可以拦截破坏性命令、标记范围蔓延,并维护每个决策的完整审计跟踪。
为了实现最大的兼容性,支持 **Stdio(本地进程)和 SSE(Web endpoint)** 两种 MCP 传输方式。
## 🎬 演示

## 问题所在
自主的 LLM 编程代理可以执行 shell 命令、修改文件、推送到远程仓库以及发起网络请求。这种能力伴随着实际风险:一个范围界定不清的 prompt 或一个幻觉产生的操作就可能导致数据丢失、暴露凭证,或对生产系统造成不可逆的更改。
现有的解决方案都是二元的——要么代理在没有审查的情况下运行所有内容,要么必须由人工手动批准每一个步骤。这两种方式都无法扩展。
## 解决方案
Sentinel 实现了一个**多阶段决策 pipeline**,使用在每个阶段最快、最合适的工具,处理从明显安全到极度危险的操作的全谱系:
**阶段 1 — 规则引擎**:基于可配置的 YAML 规则集进行模式匹配。在微秒级处理明确的案例(递归删除、凭证暴露、根目录写入),且零网络依赖。
**阶段 2 — 训练的分类器**:TF-IDF 向量器和 Logistic Regression 分类器,在标注过的代理操作数据集上训练。完全离线运行,耗时仅几毫秒,并产生具有置信区间的可解释风险评分。
**阶段 3 — LLM 审查器**:对于统计模型无法可靠解决的模糊操作,由大型语言模型结合用户陈述任务的上下文对其进行评估。这是唯一进行网络调用的阶段,且仅在前几个阶段不确定时才会激活。支持 Ollama(本地)、OpenAI、Anthropic 和 Google Gemini。
## 架构
```
MCP Client (Claude Code / Cursor / CodeX)
|
+-- stdio transport (mcp_server/server.py)
+-- SSE transport (mcp_server/sse_server.py)
|
v
| HTTP POST /review
v
api/main.py (FastAPI) <- REST API, audit log, config management
|
v
sentinel_core/orchestrator.py
|
+-- Stage 1: sentinel_core/rules_engine.py (config/rules.yaml)
+-- Stage 2: sentinel_core/classifier.py (model_artifacts/model.pkl)
+-- Stage 3: sentinel_core/llm_reviewer.py (sentinel_core/model_manager.py)
|
v
sentinel.db (SQLite) <- append-only audit log
```
## 分类器性能
| 指标 | 数值 |
|---|---|
| 训练样本 | 828(人工标注 + 合成生成) |
| 类别分布 | 58% 安全 / 42% 风险 |
| 5 折交叉验证准确率 | 76.3% ± 3.0% |
| 交叉验证 Macro-F1 分数 | 75.9% ± 3.1% |
| 留出测试集准确率 | 75.2% |
| 风险类别准确率 | 70% |
| 安全类别准确率 | 79% |
| 高置信度预测(由阶段 2 直接处理) | 占流量的 40% |
| 阶段 3 LLM 升级率 | 占流量的 60% |
分类器的置信度阈值设定为 80%。高于此阈值的预测由阶段 2 解决,无需调用阶段 3 LLM,从而降低了平均延迟,并为 40% 的受审查操作省去了 API 成本。
**与风险操作相关的前 5 个特征**:`bash`、`delete`、`iptables`、`exec`、`secret`
**与安全操作相关的前 5 个特征**:`version`、`list`、`describe`、`test`、`check`
## 项目结构
```
sentinel/
├── api/
│ └── main.py FastAPI application, all HTTP endpoints
├── sentinel_core/
│ ├── orchestrator.py Three-stage pipeline coordinator
│ ├── rules_engine.py Stage 1: YAML rule matching
│ ├── classifier.py Stage 2: sklearn inference
│ ├── llm_reviewer.py Stage 3: LLM reasoning
│ ├── model_manager.py Provider abstraction (Ollama / OpenAI / Anthropic / Gemini)
│ ├── audit_log.py SQLite decision logger
│ └── model_artifacts/ model.pkl + vectorizer.pkl (gitignored)
├── mcp_server/
│ ├── server.py MCP stdio server
│ └── sse_server.py MCP SSE server (port 8002)
├── dashboard/
│ ├── index.html Single-page control panel
│ ├── app.js Dashboard logic
│ └── style.css Dashboard styles
├── config/
│ ├── rules.yaml Stage 1 allow/block patterns
│ ├── model_config.yaml Active provider and model selection
│ └── model_config.local.yaml API keys (gitignored, never committed)
├── data/
│ └── training_examples.csv Labeled dataset for Stage 2 training
├── train/
│ ├── train_classifier.py Training script (scikit-learn)
│ └── generate_training_data.py Synthetic training data generation
├── docs/
│ └── ARCHITECTURE.md Internal design notes and rationale
├── start.bat Windows one-click launcher
├── Dockerfile Container image definition
└── requirements.txt
```
## 设计决策
### 为什么是三个阶段而不是一个?
设计目标是在处理常见情况时最小化延迟和成本,同时在处理模糊情况时保持高准确性的判断。绝大多数代理操作要么明显安全(`git status`、`npm install`),要么明显具有风险(`rm -rf /`、`git push --force`)。将这两者都通过 LLM 路由会既慢又昂贵。而将两者都仅通过规则引擎路由则会漏掉大量的中间地带。
三阶段级联解决了这个问题:
- **阶段 1** 确定性地处理明确的案例,耗时在微秒级,且没有模型参与循环。对已知危险字符串的模式匹配不会产生幻觉。这是防范灾难性命令的最后一道防线。
- **阶段 2** 离线处理统计上的中间地带,耗时在毫秒级,使用基于系数的可解释模型。我们有意选择 TF-IDF + Logistic Regression:该模型在 CPU 上几秒钟即可完成训练,产生可检查的系数,非常适合风险集中在特定关键词和 n-gram 上的短操作文本。神经网络只会增加不透明度,而不能有效地改善这个问题。
- **阶段 3** 处理真正的模糊性——即上下文(用户陈述的任务、会话的范围)比表面级别的 token 更重要的情况。这是 LLM 的推理能力真正增加价值的地方,也是唯一需要支付模型调用的延迟和成本的阶段。
### 为什么阶段 3 优先本地化?
我们将阶段 3 的默认实现设为 Ollama,以确保除非用户明确配置了云提供商,否则任何操作文本都不会离开用户的机器。这对于可能包含专有逻辑、内部主机名或敏感文件路径的代码库非常重要。`model_manager.py` 中的提供商抽象使得切换到云端 LLM 变得非常简单,且无需更改任何阶段 3 的逻辑。
### 为什么要有置信度阈值?
阶段 2 并不会将每个预测都传递给阶段 3——仅传递低于 80% 置信度阈值的预测。这将昂贵的网络调用置于统计信号的控制之下。高于阈值的预测由阶段 2 直接解决,在实际应用中约占所有流量的 40%。剩下的 60% 升级到阶段 3,此时 LLM 的推理能提供最大的边际价值。
## 设置与快速开始
### 步骤 1:启动 Sentinel 后端与仪表板
**Windows(一键启动)**:
双击项目根目录中的 `start.bat`。该脚本将自动:
1. 如果缺失则创建 Python 虚拟环境 (`venv`)
2. 从 `requirements.txt` 安装所需的包
3. 如果缺失模型 pickle 文件,则训练阶段 2 的 ML 分类器
4. 在 `http://localhost:8000` 启动 FastAPI 后端
5. 在 `http://localhost:8002` 启动 SSE 服务器
6. 在您的默认浏览器中打开 `http://localhost:8080` 启动实时仪表板
**手动 / Linux / macOS 设置**:
```
# 1. 创建并激活 virtual environment
python -m venv venv
source venv/bin/activate # macOS/Linux (use venv\Scripts\activate on Windows)
# 2. 安装依赖
pip install -r requirements.txt
# 3. 训练 classifier model(仅首次运行)
python train/train_classifier.py
# 4. 运行 API Server(终端 1)
python -m uvicorn api.main:app --port 8000 --reload
# 5. 运行 SSE MCP Server(终端 2)
python mcp_server/sse_server.py --port 8002
# 6. 运行 Dashboard UI(终端 3)
python -m http.server 8080 --directory dashboard
```
## 分步客户端集成指南
Sentinel 可无缝连接到任何兼容 MCP 的 AI 助手。请根据您的平台遵循以下详细的分步指南:
### 1. Claude Desktop (Windows / macOS)
1. **启动 Sentinel**:确保 `start.bat` 或后端服务正在运行。
2. **打开配置文件**:
- **Windows**:在记事本或 VS Code 中打开 `%APPDATA%\Claude\claude_desktop_config.json`。
- **macOS**:打开 `~/Library/Application Support/Claude/claude_desktop_config.json`。
3. **粘贴配置**:
在 `mcpServers` 下添加 `sentinel`,并附带您的 Python 虚拟环境可执行文件和 `mcp_server/server.py` 的绝对路径:
{
"mcpServers": {
"sentinel": {
"command": "C:\\path\\to\\sentinel\\venv\\Scripts\\python.exe",
"args": [
"C:\\path\\to\\sentinel\\mcp_server\\server.py"
],
"env": {
"PYTHONPATH": "C:\\path\\to\\sentinel"
}
}
}
}
4. **重启 Claude Desktop**:完全关闭并重新启动 Claude Desktop。
5. **验证连接**:
- 在 Claude Desktop 中,点击聊天窗口右下角的 **Hammer 🔨 / 设置** 图标,或前往 **设置 > 开发者**。
- 您会看到一个蓝色的徽章,显示 **`sentinel running`**,并带有活跃工具 `review_action` 和 `get_recent_decisions`。
### 2. Cursor IDE (Stdio & SSE Transport)
1. **打开 Cursor 设置**:打开 Cursor IDE,点击右上角的 **设置(齿轮图标)** 或按 `Ctrl + ,` / `Cmd + ,`。
2. **导航到 MCP**:从侧边栏选择 **功能**,然后向下滚动到 **MCP 服务器**。
3. **添加新服务器**:
- 点击 **+ 添加新的 MCP 服务器**。
- **名称**:`sentinel`
- **类型**:选择 `SSE`(推荐,以实现零子进程开销)或 `stdio`。
- **URL / 命令**:
- 对于 **SSE**:输入 `http://localhost:8002/sse`。
- 对于 **stdio**:将 `command` 设置为您的 `python.exe`,将 `args` 设置为 `mcp_server/server.py`。
4. **验证**:状态指示器将变为 **绿色(已连接)**。
### 3. Claude Code CLI
1. **定位配置**:打开 `~/.claude/claude_code_config.json`(或项目级别的 `.claude/config.json`)。
2. **添加 MCP 服务器**:
{
"mcpServers": {
"sentinel": {
"command": "python",
"args": ["mcp_server/server.py"],
"cwd": "/path/to/sentinel"
}
}
}
3. **运行 prompt**:当 Claude Code 提议命令时,它会在执行前自动调用 `review_action`。
### 4. 基于 Web 的 IDE 和自定义 HTTP 客户端 (SSE)
对于 Web 平台、远程代理或使用 **MCP Inspector** 进行测试:
- **SSE Endpoint**:`http://localhost:8002/sse`
- **消息 Endpoint**:`http://localhost:8002/messages/`
- **使用 Inspector 测试**:
npx -y @modelcontextprotocol/inspector sse http://localhost:8002/sse
### 5. 仪表板中的快速连接工具
仪表板提供了一个内置的交互式复制工具:
1. 在浏览器中打开 `http://localhost:8080`。
2. 点击右上角顶部的 **连接** 按钮。
3. 在 **Stdio** 和 **SSE** 标签页之间切换,以生成根据您的本地文件路径自动填充的配置代码片段。
4. 点击 **复制配置到剪贴板**,并直接将其粘贴到您客户端的配置文件中!
## 配置
### 阶段 3 模型提供商
在 `http://localhost:8080` 打开仪表板并导航到 **模型设置**。
**本地**:选择从您本地 Ollama 安装中检测到的任何模型。无需互联网。在选择之前,请使用 `ollama pull ` 拉取模型。
**API 提供商**:选择 Google Gemini、OpenAI、Anthropic 或自定义的 OpenAI 兼容 endpoint。输入您的 API key 并点击 **保存模型设置**。保存后,仪表板会自动调用提供商实时的 `/models` endpoint,并使用您的 key 有权访问的每个模型填充模型下拉列表。然后您可以从列表中进行选择,或手动输入任何模型名称。如果将模型字段留空,Sentinel 会自动选择该提供商推荐的默认模型。key 存储在磁盘上的 `config/model_config.local.yaml` 中,从不写入审计日志,也从不通过 API 完整返回(仪表板中仅显示最后 4 个字符)。
随时点击模型字段旁边的 **↻ 刷新**,即可重新获取实时模型列表,而无需再次保存。
### 阶段 1 规则
在仪表板中导航到 **规则** 标签页,以添加、编辑或删除模式匹配规则。规则支持精确的子字符串匹配和正则表达式。更改立即生效,无需重启服务器。
## MCP 集成与工具初始化
Sentinel 通过 Model Context Protocol (MCP) 向编程助手公开其功能。服务器使用 `FastMCP` 初始化工具并处理传输层(同时支持 `stdio` 和 `sse`)。
### 工具初始化
当 MCP 服务器启动时,它会初始化以下工具并将其提供给连接的客户端:
| 工具 | 初始化与参数 | 描述 |
|---|---|---|
| `review_action` | `action_text` (str), `user_task` (str) 在执行前审查拟议的代理操作。返回 `ALLOW`、`BLOCK` 或 `REVIEW` 的裁决。 |
| `get_recent_decisions` | `limit` (int, 默认为 20) | 从审计日志中返回最近的条目,以向代理提供过去裁决的上下文。 |
## API 参考
FastAPI 后端公开了以下 endpoint。当服务器运行时,可在 `http://localhost:8000/docs` 获取完整的交互式文档。
| 方法 | 路径 | 描述 |
|---|---|---|
| GET | `/health` | 健康检查,返回暂停状态和项目路径 |
| GET | `/status` | 轻量级的暂停/认证状态 |
| POST | `/review` | 提交操作以供审查 |
| POST | `/pause` | 暂停护栏 pipeline |
| POST | `/resume` | 恢复护栏 pipeline |
| GET | `/log` | 检索最近的审计日志条目 |
| GET | `/rules` | 获取当前阶段 1 规则集 |
| POST | `/rules` | 更新阶段 1 规则集 |
| GET | `/models/local` | 列出本地可用的 Ollama 模型 |
| GET | `/models/config` | 获取当前的模型提供商配置 |
| POST | `/models/config` | 更新模型提供商配置 |
| POST | `/models/test` | 测试活动的模型提供商连接 |
| GET | `/models/available` | 获取已保存 API key 上可用的模型实时列表 |
| GET | `/mcp/servers` | 列出已注册的 MCP 服务器 |
| POST | `/mcp/servers` | 注册新的 MCP 服务器 |
| DELETE | `/mcp/servers/{name}` | 删除已注册的 MCP 服务器 |
### 示例:审查操作
```
curl -X POST http://localhost:8000/review \
-H "Content-Type: application/json" \
-d '{"action_text": "rm -rf /tmp/build", "user_task": "Clean up build artifacts"}'
```
响应:
```
{
"action_text": "rm -rf /tmp/build",
"verdict": "ALLOW",
"decided_by_stage": "classifier",
"reason": "Classifier predicted 'safe' with 89% confidence.",
"log_id": 42
}
```
## 阶段 2 分类器 — 训练
分类器在 `data/training_examples.csv` 上进行训练,这是一个经过人工筛选和合成增强的数据集,包含被标记为 `safe`(安全)或 `risky`(有风险)的 shell 命令、SQL 语句、git 操作和 API 调用。
要生成额外的合成训练数据:
```
python train/generate_training_data.py
```
在修改或扩充数据集后重新训练:
```
python train/train_classifier.py
```
该脚本会输出完整的分类报告以及与风险相关的前 15 个特征,允许对模型学习到的信号进行验证和理解,而不是将其视为一个黑盒。
## 安全说明
- API key 仅存储在 `config/model_config.local.yaml` 中,该文件默认被 gitignore 忽略。
- 审计日志 (`sentinel.db`) 记录操作文本和审查决策,但从不存储 API key。
- 如果在启动服务器之前将 `SENTINEL_API_KEY` 设置为环境变量,则所有变更型 endpoint(规则更新、模型配置更新、暂停/恢复)都需要通过 `X-Sentinel-Key` 标头提供该 key。
- 护栏可以从仪表板中暂停。在暂停模式下,所有操作均返回 `REVIEW`,需要人工签字确认。这是出于保守考虑的设计。
## 许可证
MIT 许可证。有关详细信息,请参见 `LICENSE`。
标签:AI风险缓解, 请求拦截, 逆向工具