agent-vault

agent-vault

Agent Vault is a local credential vault for AI agents. It enables agents to use secrets by name without ever seeing their values, with host allowlists, output scrubbing, and audit logging.

Category
访问服务器

README

Agent Vault

Give your AI agent the ability to use secrets without ever letting it see them.

CI License: MIT Python 3.11+

<p align="center"> <img src="docs/demo.gif" alt="agent-vault demo: init the vault, add a secret at a hidden prompt, list without values, the whole vault encrypted on disk, a tool's output scrubbed of the secret, and an audit log" width="900"> </p>

Agent Vault is a local credential vault for AI agents. Your agent references a secret by name (e.g. stripe_key) and never sees its value: the vault injects the real credential outside the model's context, enforces per-secret rules about which hosts each secret may travel to, scrubs secret values out of everything the agent reads back, and writes an append-only audit log of every use.

Think of it as a hotel front desk — the agent is a guest who can ask for doors to be opened but never holds the master key.

        AI agent  ──"use vault:stripe_key on api.stripe.com"──▶  Agent Vault
        (sees only names)                                        │
                                                                 ├─ inject real value
                                                                 ├─ check host allowlist
                                                                 ├─ scrub the response
                                                                 └─ append to audit log

Table of contents

Why

To do real work, agents need credentials — a Stripe key, a GitHub token, a database password. The naive approach is to paste those secrets into the agent's context. That is dangerous:

  • The secret ends up in the model's conversation, which is sent to a provider and often stored in logs and transcripts.
  • A prompt-injection payload in a web page or document the agent reads can trick it into exfiltrating the key.
  • Once a secret is in the chat history, you cannot un-expose it.

Agent Vault keeps the real values in a locked box on your machine. The agent operates on secrets by name, and a normal process — outside the model — plugs in the real value, does the thing, scrubs the value from anything the agent sees, and records it.

Features

  • Reference by name. Agents use stripe_key; they never receive the value.
  • Two doors, one core. An MCP server for agent-native API calls and a run command wrapper for any CLI tool.
  • Per-secret host allowlist. A secret can only be sent to the hosts you approve — a hijacked agent can't POST your key to evil.com.
  • Output scrubbing. Secret values (and their base64 / percent-encoded forms) are replaced with {{vault:NAME}} before the agent sees them.
  • Whole-vault authenticated encryption. Values and metadata (including each secret's allowlist) are encrypted and MAC'd with Fernet, so on-disk tampering is detected and rejected.
  • Append-only audit log. Every injection, request, and denial is recorded — names and hosts, never values.
  • Local-only. No cloud, no sync, no telemetry. The master key lives in your OS keychain.

Install

uv tool install agent-vault
# or
pipx install agent-vault

For development against a clone of this repo:

uv sync

Quick start

# Create the vault and store the master key in your OS keychain.
agent-vault init

# Add a secret. You're prompted for the value with hidden input;
# --host limits where the secret may be sent over MCP HTTP.
agent-vault add stripe_key --host api.stripe.com

# List secret names and metadata — never values.
agent-vault list

# Run a tool with a secret injected as an environment variable.
agent-vault run --env GITHUB_TOKEN -- gh pr list

# Or interpolate a secret into command arguments with a {{vault:NAME}}
# placeholder. The value is substituted before exec and scrubbed from output.
agent-vault run -- curl -H "Authorization: Bearer {{vault:stripe_key}}" https://api.stripe.com/v1/charges

{{vault:NAME}} placeholders in the command are replaced with the real value just before the child process is exec'd, and every stored secret value is scrubbed back to {{vault:NAME}} in the child's stdout and stderr before you (or your agent) see it. agent-vault run exits with the child's own exit code.

How it works

Agent Vault is one core exposed through two thin frontends, so it covers both things agents actually do — call APIs and run shell tools.

                 ┌───────────────── Agent Vault ─────────────────┐
   MCP tools ───▶│  server.py   ┐                                │
                 │              ├─▶  core: store · policy ·       │
   shell     ───▶│  runner.py   ┘        scrub · audit · keys     │
   (agent-vault run)             │                                │
                 └──────────────────────┬────────────────────────┘
                                        ▼
                          ~/.agent-vault/vault.json   (one Fernet-authenticated blob)
                          ~/.agent-vault/audit.jsonl  (append-only, 0600)
                          OS keychain                 (master key)
  • store — load/save the encrypted vault, add/get/remove secrets.
  • keys — master key from the OS keychain (or AGENT_VAULT_KEY for CI).
  • policy — host-allowlist checks (exact + single-level wildcard).
  • scrub — replace secret values (and encoded forms) with placeholders.
  • audit — append-only JSONL log of every use and denial.

Agent setup (MCP)

Agent Vault ships an MCP server so agents can use secrets without ever handling their values. Add it to your agent's MCP configuration (for Claude Code, in .mcp.json or your MCP settings):

{"mcpServers": {"agent-vault": {"command": "agent-vault", "args": ["mcp"]}}}

The server exposes two tools: vault_list_secrets, which returns secret names and metadata (never values), and vault_http_request, which performs an authenticated HTTP call by injecting a named secret server-side, enforcing the secret's host allowlist, and scrubbing the response before returning it.

Security model

Agent Vault provides five guarantees:

  1. Secret values never appear in agent-visible output. MCP responses and agent-vault run output are scrubbed: every stored value is replaced with its {{vault:NAME}} placeholder before the agent sees it. MCP response scrubbing also covers the base64 and percent-encoded forms of a value, so a reflected basic-auth or query credential is caught. Wrapped run children do not inherit the AGENT_VAULT_KEY master key in their environment.
  2. Per-secret host allowlist on MCP HTTP. Each secret carries an allowed_hosts list. A prompt-injected agent cannot exfiltrate stripe_key to evil.com via vault_http_request — off-allowlist hosts are denied before any request is made, agent-supplied routing headers (Host, :authority, forwarded, and the X-Forwarded-Host/For/Proto/Port/Server, X-Real-IP, X-Original-Host, X-Host family) are rejected so they can't reroute an allowlisted request, and any request in which a raw secret value itself appears in method/url/headers/body is denied.
  3. Every use and every denied attempt is audit-logged. Injections, HTTP requests, and policy denials are all recorded (names and hosts, never values). The audit log is symlink-safe, fsync-durable, and tolerant of a corrupt line.
  4. Local-only, with the whole vault authenticated at rest. There is no cloud service, sync, or telemetry. The entire vault file — secret values and metadata, including each secret's allowed_hosts — is encrypted and authenticated with Fernet (AES-128-CBC + HMAC), so any on-disk tampering (e.g. an agent editing allowed_hosts to widen a secret's policy) fails the MAC and is rejected on load. The master key lives in your OS keychain (with an AGENT_VAULT_KEY environment-variable fallback for headless use). Vault writes are atomic (temp-file + fsync + rename), locked against concurrent writers, and symlink-safe (O_EXCL/O_NOFOLLOW).
  5. Honest limitations, documented rather than hidden:
    • agent-vault run has no host policy, and by design hands the real secret to the child process (that is how the child authenticates). Once a process legitimately holds a secret it can do anything with it — transform it, forward it, or store it — and no amount of output scrubbing can prevent that. run will inject a secret into any command you ask it to. Host allowlists apply only to MCP HTTP requests.
    • Scrubbing is best-effort and matches secret values literally (plus their base64/percent-encoded forms on MCP responses). If a tool transforms a secret some other way (hashing, reversing, splitting), the transformed form is not recognized or scrubbed. run output scrubbing is additionally line-based: a secret straddling a line boundary, or one containing a newline, is not scrubbed.
    • Substituted {{vault:NAME}} values appear in the child command's argv, visible in ps and other process listings on the same machine for the child's lifetime. Prefer --env NAME injection where the tool accepts credentials from the environment.
    • Authentication detects tampering but not rollback. An attacker who can overwrite vault.json cannot forge new policy, but can restore a previous valid copy of the whole file (reverting a tightened allowlist or a rotated secret). Protect the vault directory with filesystem permissions; anti- rollback is out of scope for this local-file design.
    • Confidentiality assumes the agent is confined to the vault's tools. Agent Vault protects secret values from an agent that can only reach them through vault_http_request and run. It does not defend against a process running as your own user that can execute arbitrary code — such a process can read the master key from your OS keychain (subject to the OS's own prompts) or from AGENT_VAULT_KEY in the environment, and decrypt the whole vault directly, with no scrubbing, allowlist, or audit entry. If you pair Agent Vault with a shell-capable agent, the vault raises the bar and gives you an audit trail for tool-mediated use, but it is not a sandbox and cannot contain an agent that already has same-user code execution.

Exit codes follow Click's convention: 0 on success, 1 on a user or validation error, 2 on a usage error. Policy denials are surfaced as structured MCP errors, not exit codes; agent-vault run passes through the child command's exit code unchanged.

Found a vulnerability? Please read SECURITY.md — do not open a public issue for security reports.

Audit log

The audit log lives at ~/.agent-vault/audit.jsonl (or $AGENT_VAULT_HOME/audit.jsonl). It is append-only, written with mode 0600, and stored as one JSON object per line. Each entry records a timestamp, an event type (add, remove, run_inject, http_request, or denied), the secret name, a target (a command or host), whether the action was allowed, and a short detail string. It never contains secret values.

agent-vault audit --tail 20

Environment variables

  • AGENT_VAULT_HOME — override the vault directory (default ~/.agent-vault). Useful for isolating vaults per project or in tests.
  • AGENT_VAULT_KEY — a base64 Fernet key used instead of the OS keychain. Set this for headless or CI environments where no keychain is available.

Project layout

agent_vault/
  cli.py            # Typer CLI: init / add / list / remove / audit / run / mcp
  runner.py         # `agent-vault run` — placeholder + env injection, output scrubbing
  server.py         # MCP server: vault_list_secrets, vault_http_request
  core/
    store.py        # encrypted vault storage (whole-file authenticated)
    keys.py         # master-key management (keychain + AGENT_VAULT_KEY fallback)
    policy.py       # host allowlist checks
    scrub.py        # replace secret values with {{vault:NAME}}
    audit.py        # append-only audit log
tests/              # pytest suite (unit + CLI + runner + MCP)
docs/               # design spec and implementation plan

Contributing

Contributions are welcome. Start with CONTRIBUTING.md for development setup, the test workflow, and the (higher-than-usual) bar for changes that touch the security-sensitive core. By participating you agree to the Code of Conduct.

Security policy

Please report vulnerabilities privately as described in SECURITY.md, not via public issues.

License

MIT. See LICENSE.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选