内容
<p align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="docs/assets/logo-lockup-dark.svg">
<source media="(prefers-color-scheme: light)" srcset="docs/assets/logo-lockup.svg">
<img src="docs/assets/logo-lockup.svg" alt="水闸" width="280">
</picture>
</p>
<p align="center">
<em>记住代理已经看到的内容的MCP门。</em>
</p>
<p align="center">
<a href="https://pypi.org/project/sluice-taint/"><img src="https://img.shields.io/pypi/v/sluice-taint" alt="PyPI 版本"></a>
</p>
---
代理不仅回答问题。它们通过MCP进入文件、数据库、API和收件箱。每个跳跃都是另一个数据可能结束在您不打算的地方。
水闸是路径上的门。它读取发送到工具的内容和返回的内容,应用您的规则,并为对话的其余部分保留敏感值的短内存。如果模型尝试将相同的值发送到新的地方,门就会关闭。
## 工作原理
每个JSON-RPC消息都通过一个管道:回忆检查 → 检测器 → 策略 → 审计 → 路由。
```mermaid
flowchart LR
subgraph client [您的机器]
A[光标 / 克劳德 / 卷曲]
end
subgraph sluice [水闸进程]
T[传输\nstdio 或 HTTP]
P[管道\n扫描 + 策略 + 污染]
R[路由器\n选择上游]
D[仪表板 /_sluice/]
DB[(审计.db)]
end
subgraph tools [MCP 服务器]
F[文件系统]
G[GitHub]
M[模拟 / 其他]
end
A -->|JSON-RPC| T
T --> P
P -->|允许| R
P -->|阻止| T
P --> DB
R --> F
R --> G
R --> M
F --> R
G --> R
M --> R
R --> P
P --> T
T --> A
D --> DB
```
| 组件 | 角色 |
|---|---|
| `config.yaml` | 上游、策略规则、污染、审计路径 |
| **传输** | 桌面客户端的stdio;服务器和Docker的HTTP |
| **管道** | 污染回忆、检测器扫描、策略操作、审计写入 |
| **路由器** | 将允许的消息转发到正确的MCP上游 |
| **检测器** | 机密、个人身份信息、工具中毒、提示注入 |
| **污染存储** | 按会话记住敏感值;阻止重用(`taint_leak`) |
| **审计 / 仪表板** | SQLite日志 + `_sluice/`处的浏览器UI |
**桌面(stdio):** `光标 → 水闸stdio → MCP服务器子进程` · **服务器(HTTP):** `curl / 代理 → :4444 → 管道 → 上游MCP`
## 这是什么(以及这不是什么)
大多数MCP安全工具都像邮件箱扫描器一样工作。它们打开一个信封,寻找信用卡或API密钥,并决定是否允许该消息通过。
水闸像一个带有记忆的门。它仍然扫描每个消息,但它也记得在会话中已经输入了什么敏感数据。第二个问题是不同的:这个确切的值是否已经在会话中,并且现在尝试通过另一个工具离开?
第二个问题是重点。`read_file`响应中的机密可以是合法的。在后来的`send_email`调用中,相同的机密是一个泄漏。水闸阻止第二个时刻,而不是第一个。
这不是一个托管服务,不是LLM裁判,也不是身份或网络访问控制的替代品。它是一个本地运行时,位于MCP线路上,强制执行YAML策略,将审计日志写入磁盘,并为一个配置提供多个工具服务器。
## 一个具体的案例
您的代理调用`read_file`,响应中包含`AKIAIOSFODNN7EXAMPLE`。这是可以的。文件中确实包含它。
两回合后,它调用`send_email`,正文包含相同的字符串。水闸对第一次调用没有意见。由于该值已经出现在本次会话中,并且现在尝试再次传输,因此它停止了第二次调用。
<video controls playsinline width="100%" src="docs/assets/demo_new.mov"></video>
自己运行:`bash scripts/demo.sh`
## v0.3.0
此版本新增:
- 文件系统、GitHub、Slack、Postgres、Brave-Search的策略预设(`sluice presets`)
- `_sluice/`处的只读HTML仪表板
- 用于HTTP部署的Docker镜像(`Dockerfile`)
- CI中针对模拟MCP服务器的集成测试
- 审计日志中的JSON路径来源 + 传播图
- 工具响应中的提示注入检测器
- 可选的OpenTelemetry导出器(`pip install sluice-taint[otel]`)
- 使用`Last-Event-Id`的完整可流式HTTP SSE重新连接
**完整设置和验证指南:** [docs/guide.md](docs/guide.md)
### 演示
```bash
bash scripts/demo.sh
```
显示第1部分(出站阻止的机密)和第2部分(`read_file` → `send_email`被`taint_leak`阻止)。参见上面的视频,或[docs/demo-recording.md](docs/demo-recording.md)记录您自己的。
### Docker(HTTP模式)
```bash
sluice init
# 编辑config.yaml — 将audit.sqlite.path设置为/var/lib/sluice/audit.db以实现持久性
docker compose up --build
# 水闸在http://localhost:4444,仪表板在http://localhost:4444/_sluice/
```
预构建镜像(推送标签后):`ghcr.io/krishyaid-coder/sluice:latest`
```bash
docker run --rm -p 4444:4444 \
-v "$PWD/config.yaml:/etc/sluice/config.yaml:ro" \
-v sluice-audit:/var/lib/sluice \
ghcr.io/krishyaid-coder/sluice:latest serve --config /etc/sluice/config.yaml --host 0.0.0.0
```
桌面客户端(光标、克劳德)使用`pip install sluice-taint`和`sluice stdio`,而不是Docker。
## v0.1.0
此版本发布:
- 带有流式HTTP(MCP 2025-03-26)的stdio和HTTP传输,用于远程上游
- 跨工具调用的延续内存(`taint_leak`)
- 机密、个人身份信息和工具中毒检测器
- 按上游和工具的YAML策略
- SQLite审计日志和`sluice logs`
- CLI:`init`、`serve`、`stdio`、`logs`、`doctor`、`version`
- 旧配置迁移到`config.yaml.upgraded`
- 配置值中的`${VAR}`扩展
快速演示脚本:
```bash
bash scripts/demo.sh
```
开发人员笔记本上的性能(仅限管道,1 KB消息):
```
clean p50=0.02 毫秒 p95=0.02 毫秒
secret p50=0.61 毫秒 p95=0.85 毫秒
```
使用`python -m sluice.bench.latency`重现。
## 安装
```bash
pip install sluice-taint
```
PyPI 包:[sluice-taint](https://pypi.org/project/sluice-taint/)。CLI 命令仍为 `sluice`。
## 入门
```bash
sluice init
sluice serve
```
代理监听 `127.0.0.1:4444`。在将任何真实内容指向它之前,请编辑 `config.yaml`。
### 从源代码
```bash
git clone https://github.com/krishyaid-coder/sluice
cd sluice
pip install -e ".[dev]"
sluice init
sluice serve
```
## 连接克劳德桌面或光标
将水闸作为MCP命令运行,而不是直接运行工具服务器:
```json
{
"mcpServers": {
"filesystem": {
"command": "sluice",
"args": ["stdio", "--config", "/absolute/path/to/config.yaml"]
}
}
}
```
水闸启动您的上游,并在stdin/stdout上使用MCP进行通信。
## 验证其有效性
在默认策略下,这应该会以JSON-RPC错误返回:
```bash
curl -s -X POST http://127.0.0.1:4444 \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "write_file",
"arguments": {"content": "key=AKIAIOSFODNN7EXAMPLE"}
}
}' | jq
```
## 运行多个工具服务器
HTTP模式可以支持多个上游。向`POST /u/<upstream-name>`或`POST /`发送流量,以使用`config.yaml`中的默认路由。
## 工具
`sluice init` 搭建配置。
`sluice serve` 启动 HTTP 网关。
`sluice stdio` 通过stdio桥接一个上游,适用于桌面客户端。
`sluice logs --since 1h` 打印本地SQLite日志中的最近决策。
`sluice doctor` 加载您的配置并报告明显的问题。
`sluice version` 打印构建版本。
`sluice presets list|show|apply` 管理捆绑的策略预设。
在运行`sluice serve`时,打开`http://127.0.0.1:4444/_sluice/`处的仪表板。
## 规则和结果
您声明当模式触发时要执行的操作:拒绝消息(`block`),剥夺匹配项并继续(`redact`),或允许但记住该值以供以后使用(`flag`)。
内置的匹配器知道常见的API密钥、令牌、PEM块、电子邮件和电话形状、卡片和政府ID、高熵字符串以及隐藏在`tools/list`有效负载中的可疑文本。
当记住的值在出站调用中再次出现时,拒绝原因是`taint_leak`。
所有操作都在您的机器上运行。审计行存储在`~/.sluice/audit.db`中,除非您将它们指向其他位置。
## 架构
参见 [Architecture.md](Architecture.md) 获取完整请求路径和模块映射。
## 许可证
Apache 2.0