关于 janee
Janee 是面向 AI Agent 的密钥管理代理,Agent 通过 MCP 调用 API 时无需接触原始凭证。它把凭证加密保存在本地,并对请求执行策略校验与日志记录,适合希望控制 Agent 访问权限的开发者。
主要功能
- 01本地加密保存 API 密钥
- 02Agent 无需获取原始凭证即可调用 API
- 03按能力设置允许或拒绝策略
- 04带时间限制的会话与即时撤销
- 05完整的请求审计日志
- 06exec 模式注入凭证运行命令行工具
适用场景
- 01让 Agent 调用 Stripe 等服务但不暴露密钥
- 02为自主 Agent 提供 GitHub App 短期令牌
- 03为容器内 Agent 提供受控的 API 访问
MCP 相关
Janee 是一个 MCP 服务,向 MCP 客户端暴露 list_services、execute、exec、manage_credential 和 reload_config 等工具,由服务端代为注入凭证并转发请求。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
Janee 🔐
通过 MCP 为 AI Agent 管理密钥
AI Agent 需要 API 访问权限才能发挥作用,但不应该拿到你的原始 API 密钥。 Janee 位于 Agent 和 API 之间,负责注入凭据、执行策略并记录所有操作。
✨ 功能
| 🔒 零知识 Agent | Agent 调用 API 时始终无法看到密钥 |
| 📋 完整审计跟踪 | 记录每个请求的时间戳、方法、路径和状态 |
| 🛡️ 请求策略 | 按功能设置允许/拒绝规则(例如,只读访问 Stripe) |
| ⏱️ 会话 TTL | 提供限时访问,并支持即时撤销 |
| 🔌 兼容任何 MCP 客户端 | Claude Desktop、Cursor、OpenClaw 等 |
| 🏠 本地优先 | 密钥在你的设备上加密,绝不会发送到云端 |
| 🖥️ Exec 模式 | 通过注入的凭据运行 CLI 工具,Agent 始终无法看到密钥 |
| 🤖 GitHub App 身份验证 | 为自主 Agent 提供短期令牌,无需静态 PAT |
| 🐦 Twitter/X OAuth 1.0a | 按请求进行 OAuth 签名,4 个密钥均保持加密 |
| ☁️ AWS SigV4 | 在服务端为 AWS API 请求签名,支持 SES、S3 等 |
| 🔧 自动 Git 身份验证 | 凭据包含 GitHub 令牌时,git push/pull 即可正常工作 |
问题
AI Agent 需要 API 访问权限才能发挥作用。目前的做法是把密钥交给它们,然后祈祷它们行为得当。
- 🔓 Agent 可以完全访问 Stripe、Gmail 和数据库
- 📊 无法审计访问了什么,也不知道原因
- 🚫 出现问题时没有紧急停止开关
- 💉 一次提示词注入就可能酿成灾难
解决方案
Janee 是一个用于管理 AI Agent API 密钥的 MCP 服务:
- 存储 API 密钥 — 在本地加密,存放于
~/.janee/ - 运行
janee serve— 启动 MCP 服务 - Agent 请求访问权限 — 通过
executeMCP 工具 - Janee 注入真实密钥 — Agent 始终无法看到密钥
- 记录所有操作 — 保留完整审计跟踪
密钥保留在你的设备上。Agent 始终无法看到。你始终掌握控制权。
配置一次,随处使用
只需在 Janee 中配置一次 API:
services:
stripe:
baseUrl: https://api.stripe.com
auth: { type: bearer, key: sk_live_xxx }
github:
baseUrl: https://api.github.com
auth: { type: bearer, key: ghp_xxx }
openai:
baseUrl: https://api.openai.com
auth: { type: bearer, key: sk-xxx }
现在,每个连接到 Janee 的 Agent 都能使用这些 API:
- Claude Desktop — 访问你的 API
- Cursor — 访问你的 API
- OpenClaw — 访问你的 API
- 任何 MCP 客户端 — 访问你的 API
不必再在工具之间复制密钥,也不必再纠结“哪个 Agent 配置了哪个 API?”添加新 Agent?它已经可以访问所有内容。撤销密钥?只需在 Janee 中更新一次。
一份配置。所有 Agent。完整审计跟踪。
快速开始
安装
npm install -g @true-and-useful/janee
初始化
janee init
这会创建包含示例服务的 ~/.janee/config.yaml。
添加服务
选项 1:交互式配置(推荐首次使用者)
janee add
Janee 会引导你添加服务:
Service name: stripe
Base URL: https://api.stripe.com
Auth type: bearer
API key: sk_live_xxx
✓ Added service "stripe"
Create a capability for this service? (Y/n): y
Capability name (default: stripe):
TTL (e.g., 1h, 30m): 1h
Auto-approve? (Y/n): y
✓ Added capability "stripe"
Done! Run 'janee serve' to start.
使用 AI Agent? 若要通过标志跳过提示,请参阅非交互式设置,也可以查看下方的特定 Agent 指南。
选项 2:直接编辑配置
编辑 ~/.janee/config.yaml:
services:
stripe:
baseUrl: https://api.stripe.com
auth:
type: bearer
key: sk_live_xxx
capabilities:
stripe:
service: stripe
ttl: 1h
autoApprove: true
添加命令行工具(exec 模式)
有些工具需要通过环境变量(而非 HTTP 标头)传递凭据。exec 模式可以处理这种情况:
janee add twitter --exec \
--key "tvly-xxx" \
--allow-commands "bird,tweet-cli" \
--env-map "TWITTER_API_KEY={{credential}}"
现在,Agent 可以通过 Janee 运行命令行工具,而无需看到 API 密钥:
// Agent calls janee_exec tool
janee_exec({
capability: "twitter",
command: ["bird", "post", "Hello world!"],
cwd: "/home/agent/project", // optional working directory
reason: "User asked to post a tweet"
})
Janee 会启动进程并注入 TWITTER_API_KEY,运行命令,然后返回 stdout/stderr。凭据不会进入 Agent 的上下文。
关键标志:
--exec— 配置为 exec 模式(命令行包装器,而非 HTTP 代理)--allow-commands— 允许执行文件的白名单(安全措施)--env-map— 将凭据映射到环境变量--work-dir— 子进程的工作目录--timeout— 最长执行时间(默认:30s)
Git 操作(自动进行 HTTPS 身份验证)
在使用 GitHub 凭据的 exec 模式下,Janee 会自动处理 Git 身份验证。无需额外配置,git push、git pull 和 git clone 都可直接使用:
capabilities:
- name: git-ops
service: github
mode: exec
allowCommands: [git]
env:
GH_TOKEN: "{{credential}}"
// Agent can push code without ever seeing the token
janee_exec({
capability: "git-ops",
command: ["git", "push", "origin", "main"],
cwd: "/workspace/my-repo"
})
Janee 会检测环境中带有 GH_TOKEN/GITHUB_TOKEN 的 git 命令,并创建临时 askpass 脚本以进行 HTTPS 身份验证。命令完成后,脚本会自动清理。
添加 GitHub App 身份验证(适用于自主 Agent)
静态令牌对于长时间运行的 Agent 来说风险较高。GitHub App 身份验证会按需生成短期安装令牌,无需长期有效的 PAT。
选项 1:使用 create-gh-app(推荐)
npx @true-and-useful/create-gh-app create my-agent --owner @me
# Opens browser → creates app → saves credentials locally
# Install the app on your repos
# https://github.com/apps/my-agent/installations/new
# Register with Janee in one command
npx @true-and-useful/create-gh-app janee-add my-agent
完成。现在,你的 Agent 可以通过 Janee 的 MCP 代理获取短期 GitHub 令牌。
选项 2:手动设置
janee add github-app \
--auth-type github-app \
--app-id 123456 \
--pem-file /path/to/private-key.pem \
--installation-id 789
也可以通过配置进行设置:
services:
github:
baseUrl: https://api.github.com
auth:
type: github-app
appId: "123456"
pemFile: /path/to/private-key.pem
installationId: "789"
工作原理: 当 Agent 请求访问权限时,Janee 会使用 App 的私钥签署 JWT,通过 GitHub API 将其兑换为有效期为 1 小时的安装令牌,并缓存令牌直至过期。Agent 永远不会看到私钥,只有短期令牌会发送到 API。
启动 MCP 服务
janee serve
与 Agent 配合使用
支持 MCP 的 Agent(Claude Desktop、Cursor、OpenClaw)现在可以调用 execute 工具,通过 Janee 发起 API 请求:
// Agent calls the execute tool
execute({
capability: "stripe",
method: "GET",
path: "/v1/balance",
reason: "User asked for account balance"
})
Janee 会解密密钥、发起请求、记录所有操作并返回响应。
集成
可与任何支持 MCP 的 Agent 配合使用:
- OpenClaw — 原生插件(
@true-and-useful/janee-openclaw)- 容器化 Agent? 请参阅容器设置指南
- Cursor — 设置指南
- Claude Code — 设置指南
- Codex CLI — 设置指南
- 任何 MCP 客户端 — 只需指向
janee serve
OpenClaw 集成
如果你使用 OpenClaw,请安装该插件以获得原生工具支持:
npm install -g @true-and-useful/janee
janee init
# Edit ~/.janee/config.yaml with your services
# Install the OpenClaw plugin
openclaw plugins install @true-and-useful/janee-openclaw
在 Agent 配置中启用:
{
agents: {
list: [{
id: "main",
tools: { allow: ["janee"] }
}]
}
}
现在,你的 Agent 拥有以下工具:
janee_list_services— 发现可用的 APIjanee_execute— 通过 Janee 发起 API 请求
该插件会自动启动 janee serve。所有请求都会记录到 ~/.janee/logs/。
MCP 工具
Janee 提供三个 MCP 工具:
| 工具 | 描述 |
|---|---|
list_services | 发现可用的 API 及其策略 |
execute | 通过 Janee 发起 API 请求(HTTP 代理模式) |
exec | 使用注入的凭据运行命令行命令(exec 模式) |
manage_credential | 查看、授予或撤销对 Agent 专属凭据的访问权限 |
reload_config | 添加或移除服务后,从磁盘重新加载配置(使用 janee serve 启动时可用) |
Agent 会发现可用内容,然后通过 Janee 调用 API。审计跟踪不变,保护机制也不变。
配置
配置文件位于 ~/.janee/config.yaml:
server:
host: localhost
services:
stripe:
baseUrl: https://api.stripe.com
auth:
type: bearer
key: sk_live_xxx # encrypted at rest
github:
baseUrl: https://api.github.com
auth:
type: bearer
key: ghp_xxx
capabilities:
stripe:
service: stripe
ttl: 1h
autoApprove: true
stripe_sensitive:
service: stripe
ttl: 5m
requiresReason: true
Services = 使用真实密钥的真实 API
Capabilities = Agent 可请求的内容及其策略
支持的身份验证类型
| 类型 | 描述 | 示例 |
|---|---|---|
bearer | Authorization 标头中的 Bearer 令牌 | Stripe、OpenAI、GitHub |
basic | HTTP Basic Auth(用户名 + 密码) | 内部 API |
hmac-bybit | Bybit 的 HMAC-SHA256 签名 | Bybit 交易所 |
hmac-okx | OKX 的 HMAC-SHA256 + 密码短语 | OKX 交易所 |
hmac-mexc | MEXC 的 HMAC-SHA256 签名 | MEXC 交易所 |
headers | 自定义键值标头 | 非标准 API |
service-account | Google 服务账号 JSON 密钥 | Google Cloud |
github-app | 有效期较短的 GitHub 安装令牌 | GitHub API |
oauth1a-twitter | OAuth 1.0a 按请求签名 | Twitter/X API v2 |
aws-sigv4 | AWS Signature V4 按请求签名 | SES、S3 和其他 AWS 服务 |
Twitter/X OAuth 1.0a
Janee 在服务器端计算 OAuth 1.0a 签名(HMAC-SHA1),因此你的 4 个 Twitter 密钥在静态存储时始终处于加密状态,且不会进入 Agent 的上下文:
services:
twitter:
baseUrl: https://api.x.com
auth:
type: oauth1a-twitter
consumerKey: xxx # encrypted at rest
consumerSecret: xxx # encrypted at rest
accessToken: xxx # encrypted at rest
accessTokenSecret: xxx # encrypted at rest
capabilities:
twitter:
service: twitter
ttl: 1h
autoApprove: true
也可以使用内置模板:
janee add twitter
AWS SigV4
Janee 按请求计算 AWS Signature V4(HMAC-SHA256),让你的访问密钥在静态存储时始终处于加密状态。非机密字段(region、awsService)保留在明文配置中:
services:
aws-ses:
baseUrl: https://email.us-east-1.amazonaws.com
auth:
type: aws-sigv4
accessKeyId: AKIA... # encrypted at rest
secretAccessKey: xxx # encrypted at rest
region: us-east-1
awsService: ses
capabilities:
aws-ses:
service: aws-ses
ttl: 1h
autoApprove: true
常见 AWS 服务的内置模板:
janee add aws-ses # Amazon SES
janee add aws-s3 # Amazon S3
访问控制
控制哪些 Agent 可以使用哪些功能:
server:
host: localhost
defaultAccess: restricted # capabilities require explicit allowlist
capabilities:
stripe:
service: stripe
ttl: 1h
allowedAgents: ["agent-a", "agent-b"] # only these agents can use it
github:
service: github
ttl: 1h
# no allowedAgents + defaultAccess: restricted → no agent can use this
defaultAccess: restricted—— 未设置allowedAgents列表的功能对所有 Agent 隐藏defaultAccess: open(默认值)——未设置allowedAgents列表的功能对所有 Agent 开放allowedAgents——每项功能的 Agent 名称列表(与 MCP 初始化握手中clientInfo.name的值匹配)
Agent 在运行时创建的凭据默认采用 agent-only 访问权限——只有创建该凭据的 Agent 可以使用,除非它通过 manage_credential 工具明确授予访问权限。
Exec 模式功能
services:
twitter:
auth:
type: bearer
key: tvly-xxx
capabilities:
twitter:
service: twitter
mode: exec
allowCommands: ["bird", "tweet-cli"]
envMap:
TWITTER_API_KEY: "{{credential}}"
ttl: 1h
autoApprove: true
Exec 模式功能使用 janee_exec,而不是 execute。凭据会作为环境变量注入——Agent 只能看到 stdout/stderr。
Exec 模式下 Runner 的默认强化措施:
- 使用隔离的最小化环境(不继承完整的主机环境)
- 每条命令使用临时
HOME - 超时后终止整个进程组
Runner/Authority 模式(适用于容器)
当 Agent 在 Docker 容器中运行时,远程主机上的 janee_exec 无法访问容器文件系统。Runner/Authority 架构可解决此问题:
- Authority 在主机上运行:持有凭据、执行策略、代理 API 请求
- Runner 在每个容器内运行:向 Agent 提供 MCP 服务,将非 exec 调用转发给 Authority,并在本地运行
janee_exec
# Host: start Authority (MCP + exec authorization on one port)
janee serve -t http -p 3100 --host 0.0.0.0 --runner-key "$JANEE_RUNNER_KEY"
# Container: start Runner (agent talks to this)
janee serve -t http -p 3200 --host 127.0.0.1 \
--authority http://host.docker.internal:3100 --runner-key "$JANEE_RUNNER_KEY"
Agent 只需设置 JANEE_URL=http://localhost:3200。
你也可以将 Authority 作为独立进程运行:
janee authority --runner-key "$JANEE_RUNNER_KEY" --host 127.0.0.1 --port 9120
完整架构、exec 授权流程、Docker Compose 示例和故障排查,请参阅 Runner/Authority 指南。
请求策略
使用 rules 精确控制每项功能可以发出的请求:
capabilities:
stripe_readonly:
service: stripe
ttl: 1h
rules:
allow:
- GET *
deny:
- POST *
- PUT *
- DELETE *
stripe_billing:
service: stripe
ttl: 15m
requiresReason: true
rules:
allow:
- GET *
- POST /v1/refunds/*
- POST /v1/invoices/*
deny:
- POST /v1/charges/* # Can't charge cards
- DELETE *
规则的工作方式:
- 先检查
deny模式——明确拒绝始终优先 - 然后检查
allow模式——必须匹配才能继续 - 未定义规则 → 全部允许(向后兼容)
- 已定义规则但未匹配 → 默认拒绝
模式格式: METHOD PATH
GET *→ 任意 GET 请求POST /v1/charges/*→ 对 /v1/charges/ 及其子路径发出 POST 请求* /v1/customers→ 对 /v1/customers 发出任意方法的请求DELETE /v1/customers/*→ 删除任意客户
**这让安全措施真正有效:**即使 Agent 谎报“原因”,也只能访问策略允许的端点。策略在服务器端执行。
CLI 参考
janee init # Set up ~/.janee/ with example config
janee add # Add a service (interactive)
janee add stripe -u https://api.stripe.com -k sk_xxx # Add with args
janee remove <service> # Remove a service
janee remove <service> --yes # Remove without confirmation
janee list # List configured services
janee list --json # Output as JSON (for integrations)
janee search [query] # Search service directory
janee search stripe --json # Search with JSON output
janee cap list # List capabilities
janee cap list --json # List capabilities as JSON
janee cap add <name> --service <service> # Add capability
janee cap edit <name> # Edit capability
janee cap remove <name> # Remove capability
janee serve # Start MCP server (stdio, default)
janee serve --transport http --port 9100 # Start with HTTP transport (for containers)
janee serve --authority https://janee.example.com --runner-key $JANEE_RUNNER_KEY # Runner mode
janee authority --runner-key $JANEE_RUNNER_KEY # Start authority API
janee logs # View audit log
janee logs -f # Tail audit log
janee logs --json # Output as JSON
janee sessions # List active sessions
janee sessions --json # Output as JSON
janee revoke <id> # Kill a session
非交互式设置(适用于 AI Agent)
AI Agent 无法响应交互式提示。使用 --*-from-env 标志从环境变量读取凭据,避免密钥进入 Agent 的上下文窗口:
# Bearer auth (Stripe, OpenAI, etc.)
janee add stripe -u https://api.stripe.com --auth-type bearer --key-from-env STRIPE_KEY
# HMAC auth (Bybit)
janee add bybit --auth-type hmac-bybit --key-from-env BYBIT_KEY --secret-from-env BYBIT_SECRET
# HMAC auth with passphrase (OKX)
janee add okx --auth-type hmac-okx --key-from-env OKX_KEY --secret-from-env OKX_SECRET --passphrase-from-env OKX_PASS
# GitHub App auth (short-lived tokens)
janee add github --auth-type github-app --app-id-from-env GH_APP_ID --pem-from-env GH_PEM --installation-id-from-env GH_INSTALL_ID
# Twitter/X OAuth 1.0a (per-request signing)
janee add twitter --consumer-key $TWITTER_CONSUMER_KEY --consumer-secret $TWITTER_CONSUMER_SECRET \
--access-token $TWITTER_ACCESS_TOKEN --access-token-secret $TWITTER_ACCESS_TOKEN_SECRET
# AWS SigV4 (SES, S3, etc.)
janee add aws-ses --access-key-id $AWS_ACCESS_KEY_ID --secret-access-key $AWS_SECRET_ACCESS_KEY \
--region us-east-1 --aws-service ses
通过标志提供所有必需的凭据后,Janee 将:
- 不会打开 readline(不会因等待 stdin 而卡住)
- 使用合理的默认值自动创建能力(1h TTL,自动批准)
如果你愿意,也可以直接编辑 ~/.janee/config.yaml。
工作原理
┌─────────────┐ ┌──────────┐ ┌─────────┐
│ AI Agent │─────▶│ Janee │─────▶│ Stripe │
│ │ MCP │ MCP │ HTTP │ API │
└─────────────┘ └──────────┘ └─────────┘
│ │
No key Injects key
+ logs request
- Agent 使用能力、方法和路径调用
executeMCP 工具 - Janee 查找服务配置,解密真实密钥
- 使用密钥向真实 API 发起 HTTP 请求
- 记录:时间戳、服务、方法、路径、状态
- 将响应返回给 Agent
Agent 永远不会接触真实密钥。
📐 深入了解: 查看架构与安全模型,了解详细图示、威胁模型以及与替代方案的比较。
安全性
- 加密: 使用 AES-256-GCM 存储密钥
- Agent 身份: 从 MCP 初始化握手中的
clientInfo.name派生,无需自定义标头 - Agent 隔离: 每个 Agent 都有独立身份的专属会话(HTTP 传输会为每个会话创建一个 Server+Transport)
- 访问控制: 每项能力的
allowedAgents白名单 + 全服务器范围的defaultAccess策略 - 凭据范围: Agent 创建的凭据默认设为
agent-only - 审计日志: 每个请求都会记录到
~/.janee/logs/ - 会话: 有时间限制,可撤销
- 紧急停止开关: 使用
janee revoke或删除配置
Docker
将 Janee 作为容器运行,无需本地安装 Node.js:
# Build
docker build -t janee .
# Run in HTTP mode
docker run -d -p 3000:3000 \
-v ~/.janee:/root/.janee:ro \
janee --transport http --port 3000 --host 0.0.0.0
或者使用 Docker Compose:
mkdir -p config && cp ~/.janee/config.yaml config/
docker compose up -d
如需了解如何通过 Docker 使用 Claude Desktop,请参阅 Docker 文档。
参与贡献
欢迎贡献!提交 PR 前,请阅读 CONTRIBUTING.md,其中包含必需的 PR 检查清单(测试、变更日志、版本升级等)。
许可证
MIT — 由 True and Useful LLC 构建
别再把密钥交给 AI Agent。从现在开始控制访问权限。 🔐
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。