Cloud-Ops-Dev/janus
GitHub: Cloud-Ops-Dev/janus
Janus 是一个 MCP 网关和能力代理,通过统一的小型工具接口、策略引擎、凭证隔离和审计追踪,解决 agent 对接大量下游 MCP 服务器时的上下文膨胀与凭证管理问题。
Stars: 0 | Forks: 0
Janus
一个 MCP 网关和功能代理。
在每个下游 MCP 服务器前提供一个小巧、稳定的工具接口 ——
支持即时发现、默认拒绝策略、凭证隔离以及完整的审计追踪。
## 问题所在
每个强大的 agent 都通过连接到 MCP 服务器来加载其工具。随着运维人员添加服务器 —
问题追踪器、笔记/记忆、项目看板、数据库、计费、部署工具 — **每次会话都要承担
所有工具 schema 的全部上下文成本**,模型的工具选择准确率下降,
并且所有这些服务的凭证都分散在每个 agent 的配置中。
将 *N* 个服务器加载到*每个*会话中是无法扩展的。
## Janus 的作用
Agent 只加载 **一个** 服务器 — Janus — 它公开了一小部分固定的 **broker 工具**,
并将数十个下游工具作为注册中心、策略引擎、凭证代理、清理器和审计日志背后的实现细节:
```
capability.search(query) → a short, ranked list of relevant capabilities (no full schemas)
capability.describe(id) → the schema + risk tier + policy for one capability
capability.call(id, args) → a policy-checked, credential-injected, audited invocation
server.list / server.health → downstream inventory + liveness
policy.explain(id) → why an action is allowed / denied / needs confirmation
audit.recent(limit) → the recent invocation log
```
模型看到的是 **约 7 个 broker 工具,而不是 100 多个下游工具**。功能采用
*即时*发现(`search → describe → call`),而不是预先全部转储,并且每次调用都经过代理:
根据策略进行检查,提供模型永远看不到的凭证,限制大小并脱敏处理机密信息,
然后记录在案。
## 架构
客户端(Claude Code、Codex、SSH/REST 使用者)通过 **MCP** *或* **REST/CLI**
回退机制访问 Janus。在网关将每次请求触及下游服务器之前,它会通过五个协作的子系统对其进行解析:
| 子系统 | 职责 |
|---|---|
| **Registry** | 服务器和功能的事实来源目录(传输方式、信任级别、风险上限、env 范围)。对公开仓库安全的 YAML 种子;运行时状态位于本地 SQLite `SchemaStore` 中。 |
| **Policy engine** | 基于每个调用 `(profile, risk tier, environment)` 进行默认拒绝决策 → **允许 / 确认 / 拒绝**,并附带人类可读的原因。 |
| **Credential broker** | 在调用时解析密钥引用(例如 `op://...`),将它们注入到下游的 env/headers 中,利用 TTL 将它们缓存在内存中,并且**永远不会记录或返回它们**。 |
| **Sanitizer** | 限制输出大小,对机密信息进行脱敏,并在不可信的下游内容到达模型之前对其进行标记。 |
| **Audit + drift** | 仅可追加的 JSONL + SQLite 调用日志;descriptor/schema **漂移检测**,可将已更改的功能自动隔离,直到其被重新批准。 |
## 关键特性
- **小巧固定的工具接口** → 更低的上下文成本和更好的工具选择。
- **分阶段的即时发现** — `search → describe → call`,绝不是完整的 schema 转储。
- **默认拒绝策略**,具有风险等级(`read_only` ... `local_write` ...
`destructive` / `financial`)和环境门控(`dev` / `test` / `prod_safe` / `prod`),
按 **agent profile** 划分范围。
- **凭证由网关拥有**,在调用时从外部密钥管理器解析 —
永远不会暴露给模型或写入日志。
- **中和不可信的工具元数据** — 人工审查的摘要;检测并隔离 descriptor/schema 漂移。
- **每次调用都会被审计。**
- **双接口** — 针对强大宿主环境的 MCP,针对其他一切的 REST/CLI。
- **自给自足** — 作为 `systemd --user` 服务运行,在没有 shell 会话的情况下重启后依然存活;`--check` 会在缺少配置时发出明显的错误提示。
## 项目状态
Janus 分阶段构建 — 早期即交付价值;风险(写入工具、惰性生命周期)
仅在策略和审计稳固后才添加。
| 阶段 | 范围 | 状态 |
|---|---|---|
| **1** | 静态注册中心 · 7 个 broker 工具 · 策略引擎 · 凭证代理 · 审计 · REST/CLI · systemd | ✅ **已实现并部署** |
| **2** | 下游发现爬虫 · 审批工作流 · descriptor 漂移自动隔离 + 警报 | ✅ **已实现** |
| 3 | 完整的策略引擎 · 需确认的写入工具 · 致命三要素会话追踪 | ⏳ 计划中 |
| 4 | 惰性下游生命周期(按需启动、闲置时关闭、断路器) | ⏳ 计划中 |
| 5 | 语义功能搜索(基于脱敏摘要的 embeddings) | ⏳ 计划中 |
| 6 | 为支持 `tools/list_changed` 的宿主环境动态公开原生工具 | ⏳ 可选 |
目前的参考部署代理了 **Beads** 和 **Paperclip**(只读)。**Open Brain**
记忆下游正在等待多头部 HTTP 认证支持。
## 快速开始
```
# 环境 (Python 3.11+)
uv venv && uv pip install -e .
# 配置 — 复制 env 模板并填入 per-host token + downstream endpoint
cp config/janus.env.template janus.env # then edit; keep it out of git (gitignored)
# 验证配置 (systemd ExecStartPre gate — 出现问题时以非零值退出)
python -m janus --check
# 运行服务
python -m janus --serve # REST API + authenticated MCP at /mcp/
python -m janus --mcp-http # standalone authenticated MCP-over-HTTP
python -m janus --stdio # MCP over stdio (per-session spawn)
```
使用内置的 unit 作为托管服务运行它:
```
cp systemd/janus.service ~/.config/systemd/user/
systemctl --user enable --now janus.service
loginctl enable-linger # survive logout / reboot
```
## CLI
**`bin/janus`** — 基于 REST API 的轻量级客户端,适用于 SSH / 脚本使用。从环境中读取 `JANUS_URL`
(默认为 `http://127.0.0.1:8088`)和按主机的 `JANUS_TOKEN`:
```
bin/janus search "open issues assigned to me"
bin/janus describe
bin/janus call '{"arg": "value"}'
bin/janus servers # inventory + health
bin/janus explain
bin/janus audit --limit 20
```
网络化的 MCP 客户端通过 bearer token 连接到 `http://HOST:8088/mcp/`,
该 token 在 `JANUS_TOKENS` 中声明。每个 `Mcp-Session-Id` 都会获得一个独立的 broker、
audit/trifecta 身份和动态工具视图;闲置的会话状态将在
`JANUS_MCP_SESSION_TTL_SECONDS`(默认:一小时)后过期。缺失或未知的 token
会被拒绝。
**`bin/janus-admin`** — 主机本地管理(直接与注册中心 SQLite 通信,
不通过网络):
```
bin/janus-admin discover # crawl downstreams, refresh observations
bin/janus-admin list # every capability's lifecycle state
bin/janus-admin pending # capabilities awaiting first approval
bin/janus-admin approve # approve + lock the reviewed baseline
bin/janus-admin diff # baseline-vs-observed descriptor delta
bin/janus-admin quarantine-capability
bin/janus-admin quarantine-server
```
它的目标是**实时**注册中心 — 即正在运行的网关所服务的同一个注册中心 — 除非您自己指定
`JANUS_CONFIG_DIR` / `JANUS_DATA_DIR`,否则它会通过 source 网关 env(`JANUS_GATEWAY_ENV`,默认为 `~/.config/systemd/user/janus.env`)。每次运行都会在 stderr 上打印解析出的 `config_dir=` 和
`data_dir=`,并在目标是仓库本地副本时发出警告。在信任任何输出之前,请检查那一行:
早期版本默认为 `/data`,因此它报告了一个包含 27 个干净功能的注册中心,
而实时注册中心包含 134 个功能且存在实际的隔离 — 并且在那里写入的 `approve`
永远不会到达 broker。请参阅 `docs/operations.md` → “我正在编辑哪个注册中心?”。
## 配置
所有配置都位于 `config/` 中,并且**对公开仓库安全** — 它不包含任何机密信息、token、
`op://` 引用或内部端点。连接详细信息和凭证在
运行时通过凭证代理解析的指定环境变量提供。
| 文件 | 用途 |
|---|---|
| `servers.yaml` | 下游服务器注册中心 — 传输方式、信任级别、风险上限、env 范围。 |
| `capabilities.yaml` | 每个功能的摘要、标签和风险等级(可搜索的接口)。 |
| `profiles.yaml` | Agent profiles(例如 `default_assistant`、`infra_operator`) → 每个环境的允许 / 确认 / 拒绝风险等级。 |
| `janus.env.template` | 针对主机 env 文件的带有注释的模板(下游 URL + token,`JANUS_TOKENS`,可选警报 webhook)。 |
## 安全模型
- **任何机密信息都不会到达模型或审计日志** — 凭证代理在下游注入它们,
清理器在返回时对其进行脱敏。这已通过测试验证。
- **默认拒绝** — 在获得批准之前,功能是不可调用的,任何高于
profile 允许范围的风险等级都会被拒绝或在确认后放行,`policy.explain` 会给出原因。
- **抵御工具投毒** — 模型可见的文本来自人工审查的摘要,而非原始的
下游描述;descriptor/schema 的更改会自动隔离该功能,直到其被重新审查。
## 开发
```
uv run ruff check . # lint (includes bandit security rules)
uv run mypy src # strict type checking
uv run pytest # 108 tests
```
底层基础是官方的 [`modelcontextprotocol/python-sdk`](https://github.com/modelcontextprotocol/python-sdk)
(用于下游连接的 `ClientSessionGroup`)以及 [`fastmcp`](https://github.com/jlowin/fastmcp)
作为 broker 接口。Janus 在两者之上保留了轻量级的适配器,以使 SDK 的变动保持局部化。
## 仓库布局
```
janus/
├── bin/ janus (REST client) · janus-admin (local admin)
├── config/ servers · capabilities · profiles · env template
├── docs/ documentation + diagrams
├── src/janus/
│ ├── registry/ registry loader + SQLite SchemaStore
│ ├── downstream/ ClientSessionGroup manager (stdio + HTTP, tolerant connect)
│ ├── policy/ deny-by-default profile policy engine
│ ├── security/ credential broker · secret redactor · output sanitizer
│ ├── audit/ JSONL + SQLite invocation log
│ ├── discovery/ crawler · drift detection · alerts
│ ├── admin/ approval / quarantine CLI service
│ ├── broker.py the 7 broker tools' logic
│ ├── server_mcp.py FastMCP surface
│ ├── server_rest.py FastAPI REST mirror
│ └── gateway.py composition root
└── tests/ unit + integration (fake downstream MCP server)
```
## 许可证
待定。在添加许可证文件之前,所有权利均归作者所有。标签:AI代理管理, MCP网关, Python, Streamlit, 凭证隔离, 安全规则引擎, 审计日志, 无后门, 访问控制