内容
# 施泰纳
[](https://github.com/HT88-exe/steiner/actions/workflows/ci.yml)
[](LICENSE)
[](https://go.dev/)
**MCP(模型上下文协议)的安全网关。** 施泰纳位于代理和MCP服务器之间,对每个工具调用强制执行策略:谁可以调用什么、完整的审计轨迹,以及在注入成功时的遏制。
存储库:[github.com/HT88-exe/steiner](https://github.com/HT88-exe/steiner)
提示注入检测是概率性的;没有分类器能捕获所有情况。施泰纳采取了另一种策略:**假设模型被注入,并使其在工具调用层面上不具灾难性** —— 这是唯一一个对代理实际操作具有完全可见性的地方。
```mermaid
flowchart LR
subgraph clients [代理]
a[Claude Desktop]
b[Cursor]
c[您的代理]
end
subgraph gw [施泰纳]
ingress[HTTP ingress + API 密钥]
pol[策略引擎:允许列表、污染、DLP、审批]
aud[(审计日志)]
end
subgraph up [上游 MCP 服务器]
fs[文件系统]
web[获取 / 网络]
saas[SaaS 服务器]
end
a --> ingress
b --> ingress
c --> ingress
ingress --> pol
pol --> fs
pol --> web
pol --> saas
pol --> aud
```
## 致命三要素
当以下三个条件同时成立时,代理是危险的:
1. 它可以读取**不受信任的内容**(网页、入站电子邮件),
2. 它有权访问**私有数据**,并且
3. 它可以**与外部通信**(发送邮件、发布、调用 webhook)。
隐藏在不受信任内容中的注入有效载荷可以将步骤 2 和 3 转换为数据泄露。您无法可靠地阻止模型被注入 —— 但数据路径中的网关可以阻止后果。施泰纳跟踪会话何时读取了不受信任的内容(它变得**污染**),并阻止污染的会话访问具有外部副作用的工具。
## 功能
- **透明代理** —— 一个 MCP 端点;上游工具暴露为 `<上游>_<工具>`。
- **治理** —— 按主体划分的 API 密钥、允许/拒绝列表、速率限制。
- **遏制** —— 会话污染跟踪、三要素规则、 outbound 参数的 DLP、自定义规则和敏感工具的审批。
- **检测作为信号** —— 启发式(编码 blob、新颖域名、注入措辞)为策略引擎提供信息;它们不取代它。
- **审计轨迹** —— 追加日志,带有秘密删除、CLI 查询、JSONL 导出和循环跟踪查看器。
- **凭证库** —— 上游令牌存储在施泰纳配置中;代理永远不会看到它们。
## 快速入门
需要 [Go 1.26+](https://go.dev/dl/) 或安装二进制文件:
```bash
go install github.com/HT88-exe/steiner/cmd/steiner@latest
```
```bash
steiner init # 写入 steiner.yaml
steiner keygen --name agent-a # 打印一个 API 密钥(仅显示一次)
steiner run # MCP 在 http://127.0.0.1:8385/mcp
```
将代理指向 `http://127.0.0.1:8385/mcp`,并带有标头 `Authorization: Bearer <密钥>`。打开 `http://127.0.0.1:8386/` 以查看跟踪查看器。
### 适用于 Cursor / Claude Desktop(stdio)
```json
{
"mcpServers": {
"steiner": {
"command": "steiner",
"args": ["run", "--stdio", "--config", "/绝对路径/to/steiner.yaml"]
}
}
}
```
stdio 模式使用 `default_principal`(本地)。管理 API 仍在循环端口上监听。
## 配置
`steiner init` 写入一个注释的启动配置:
```yaml
listen: 127.0.0.1:8385
admin_listen: 127.0.0.1:8386
上游:
- 名称: fs
传输: stdio
命令: npx
参数: ["-y", "@modelcontextprotocol/server-filesystem", "."]
主体:
- 名称: agent-a
允许: ["fs_*"]
拒绝: ["fs_write_file"]
速率限制: { 每分钟: 60, 每天: 2000 }
策略:
不信任来源: ["web_*", "fetch_*", "browser_*"]
外部接收者: ["mail_*", "slack_*", "*_send", "*_post"]
污染时阻止接收者: true
参数中阻止机密: true
需要审批: ["shell_*"]
```
## 命令
| 命令 | 目的 |
| --- | --- |
| `steiner init` | 编写启动 `steiner.yaml`。 |
| `steiner run [--stdio] [--verbose]` | 运行网关。 |
| `steiner keygen --name <主体>` | 发出 API 密钥。 |
| `steiner audit [--json]` | 查询审计日志。 |
| `steiner trace [--config path]` | 提供跟踪查看器(从磁盘读取审计数据库)。 |
| `steiner approvals list \| approve <id> \| deny <id>` | 解析待处理审批。 |
| `steiner policy test <文件>` | 运行攻击场景测试。 |
| `steiner version` | 打印版本。 |
## 遏制评估
存储库中附带了十个脚本场景:
```bash
steiner policy test examples/attacks/scenarios.yaml
```
参见 [examples/attacks/scenarios.yaml](examples/attacks/scenarios.yaml) 和 [examples/demo/injection-attack.md](examples/demo/injection-attack.md)。
## 执行管道
```
允许列表 -> 速率限制 -> 策略(污染 / DLP / 审批)-> 转发 -> 审计
```
被阻止的调用会返回一个**工具错误,附带原因**,以便模型可以解释拒绝而不是盲目重试。污染是会话范围的,与 MCP 协议会话无关(参见 [docs/spec-compat.md](docs/spec-compat.md))。
## 文档
| 文档 | 描述 |
| --- | --- |
| [CHANGELOG.md](CHANGELOG.md) | 发布历史 |
| [CONTRIBUTING.md](CONTRIBUTING.md) | 开发设置 |
| [SECURITY.md](SECURITY.md) | 漏洞报告 |
| [docs/spec-compat.md](docs/spec-compat.md) | MCP 规范兼容性 |
## 当前限制(v0.1.0)
- 资源读取被审计,但不受策略控制。
- 污染和速率限制状态是每个进程的内存状态。
- 上游凭证是静态配置值(无 OAuth 传递)。
- 检测器是启发式的,而不是基于机器学习的。
三要素规则在单个网关进程内对工具调用强制执行确定性。
## 作者
**胡扎伊法·萨卡尔** — [GitHub @HT88-exe](https://github.com/HT88-exe)
## 许可证
Apache 2.0。参见 [LICENSE](LICENSE)。