Cloud-Ops-Dev/janus

GitHub: Cloud-Ops-Dev/janus

Janus 是一个 MCP 网关和能力代理,通过统一的小型工具接口、策略引擎、凭证隔离和审计追踪,解决 agent 对接大量下游 MCP 服务器时的上下文膨胀与凭证管理问题。

Stars: 0 | Forks: 0

Janus — MCP Gateway & Capability Broker

Janus

一个 MCP 网关和功能代理。
在每个下游 MCP 服务器前提供一个小巧、稳定的工具接口 —— 支持即时发现、默认拒绝策略、凭证隔离以及完整的审计追踪。

Python 3.11+ MCP Tests mypy strict Status

## 问题所在 每个强大的 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`),而不是预先全部转储,并且每次调用都经过代理: 根据策略进行检查,提供模型永远看不到的凭证,限制大小并脱敏处理机密信息, 然后记录在案。 ## 架构

Janus architecture: clients → gateway (registry · policy · credentials · sanitizer · audit · drift) → downstream services

客户端(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, 凭证隔离, 安全规则引擎, 审计日志, 无后门, 访问控制