vault-mcp
Provides a credential preset for Cloudflare API tokens and keys, enabling agents to inject them into environments without revealing the secret values.
Provides a credential preset for Firebase service accounts and API keys, including placeholder-based injection into configuration files.
Provides a credential preset for GitHub tokens and API keys, allowing safe injection into .env files without exposing the values.
Provides a credential preset for Google Maps API keys, letting agents write the key into environment files while only seeing metadata.
Provides a credential preset for OpenAI API keys, enabling secure storage and injection into environment files without exposing the key.
Provides a credential preset for Resend API keys, allowing agents to inject them into .env files without revealing the secret.
Provides a credential preset for SendGrid API keys, enabling secure injection into environment files without exposing the value.
Provides a credential preset for Stripe secret keys, publishable keys, and webhook secrets, allowing agents to inject them into .env files while never seeing the values.
Provides a credential preset for Supabase API keys and credentials, enabling secure storage and injection into environment files.
Provides a credential preset for Twilio credentials, allowing agents to inject account keys and tokens into environments without exposing them.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@vault-mcpSet up .env with the Stripe keys from vault for the acme project"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
vault-mcp
A personal secrets vault your AI coding agent can use without ever seeing your keys.
Store your API keys once. When the agent needs a Stripe key, a Google Maps key or a database URL, it searches
the vault, finds the metadata, and writes the value straight into your .env. The value goes to disk; the
conversation only ever sees the variable name.
You: "Add a map to the dashboard showing user locations."
Agent: [vault_search "google maps"] -> finds google-maps/default/api_key
[vault_inject_env] -> writes NEXT_PUBLIC_GOOGLE_MAPS_API_KEY into .env
"I set NEXT_PUBLIC_GOOGLE_MAPS_API_KEY in .env and wired up the map component."No more pasting keys into chat.
Works with Claude Code, Claude Desktop, Cursor, Windsurf, Antigravity, VS Code, Zed — anything that speaks MCP over stdio.
What it does
Your agent stops asking you for keys. It searches the vault first and injects what it finds.
It never sees the values. All 29 tools return metadata and status only. Values go to a file, a process environment or a remote server, never back through the conversation.
Groups and accounts.
stripe/acmeandstripe/personalstay apart, each with its own secret key, publishable key and webhook secret.Projects. A project holds its own secrets and links to shared ones, so one call sets up a whole
.env.Four injection targets. A local
.env, any config file through{{vault:path}}placeholders, a command's environment with the output redacted, or a remote server's env file over SSH.Two ways to add a key. Tell the agent the value, or have it open the vault in your browser so you type the key in yourself behind your access code.
Encrypted at rest, no password to remember. AES-256-GCM, with the master key in Windows Credential Manager or the macOS Keychain.
An access code for what matters. Gates the web UI, and individually gates any secret marked
--protected.Backups. Local snapshots for undoing mistakes, portable passphrase-sealed backups for a drive or another machine.
Guard rails. It refuses to write a secret into a git-tracked file, warns when a server-only key is headed for a browser variable, and logs every read and injection.
15 service presets. Stripe, Google Maps, AWS, OpenAI, Anthropic, Cloudflare, Supabase, Firebase, Twilio, SendGrid, Resend, GitHub, a database URL, an SSH server, and a generic catch-all.
Related MCP server: Vault MCP
Install
git clone https://github.com/MHasnainJafri/vault-mcp.git
cd vault-mcp
npm install
npm run build
npm link # makes `vault` available everywhere (optional)
vault init # creates ~/.vault-mcp and the master keyThen register it with your editor or agent. vault install shows which clients it found on your machine:
vault install # list clients, and mark the ones detected
vault install --client cursor # write that client's config
vault install --all # every client it detected
vault install --print # just show the JSON to pasteThe config it writes is merged into whatever is already there, and the original is copied to
<config>.vault-backup first, so no other server or setting is disturbed.
Client | Config it writes |
Claude Code | prints |
Claude Desktop |
|
Cursor |
|
Windsurf |
|
Antigravity (IDE and CLI) |
|
VS Code (Copilot) |
|
Zed | use |
Any other MCP client takes the standard block:
{
"mcpServers": {
"vault": { "command": "node", "args": ["/abs/path/to/vault-mcp/dist/cli.js", "serve"] }
}
}VS Code names that block servers instead of mcpServers. A newly registered server appears the next time
the client starts.
Then set your access code, which you type yourself and never share with the agent:
vault set-pinAdd your keys
Three ways, none of which put the value in a chat window.
Guided, per service — walks the fields a service needs, hidden prompts:
vault add stripe/acme # secret_key, publishable_key, webhook_secret
vault add google-maps/default # api_key
vault setup # first-run wizard: init + first service + installOne key at a time:
vault add openai/personal/api_key --env OPENAI_API_KEY --tags ai
cat key.pem | vault add ssh/prod/private_key --stdinImport a file you already have — a .env, or a JSON object of named fields:
vault import ./my-app/.env --to projects/my-app
vault import ./server.json --to vps/my-serverJSON is the quickest way to add something with several fields at once:
{ "host": "198.51.100.20", "username": "deploy", "password": "…", "port": 22 }Each field becomes its own secret. Nested objects are flattened, so {"db":{"user":"root"}} becomes
db/user, and an array is kept whole as one value. The format is picked from the file extension, or sniffed
from the content if the name does not say.
Or use the local web UI:
vault uiOpens http://127.0.0.1:5177 on loopback only. If you have set an access code it asks for that first. Add,
edit, tag, import, back up, and reveal values (reveal works only in this local page, never through the agent).
Two ways to add a key mid-conversation
When the agent needs a key you do not have stored yet, you pick which way it goes in:
What happens | When to use it | |
You tell the agent the value | It calls | Test keys, throwaways. The value is in the transcript, so rotate anything live. |
"Open the vault for me" | It calls | Production credentials, anything that matters. The agent never sees it. |
For the second one, the agent is deliberately not given the URL token, so it cannot read that page. Your access code is what unlocks it.
vault set-pin # set the access code onceOrganize
Paths are group/account/field, so multiple accounts of the same service stay apart:
stripe/
acme/ secret_key, publishable_key, webhook_secret
personal/ secret_key
google-maps/
default/ api_key
projects/
my-shop/ database_url <- project-specificLink a shared key into a project instead of copying it:
vault link projects/my-shop stripe/acme/secret_key
vault link projects/my-shop stripe/acme/secret_key --env PAYMENTS_KEY # rename per projectThen one call injects everything that project needs:
vault inject --project projects/my-shop --file .envWhat the agent can do
The server registers as vault, so its tools appear as vault_*. All 29, with their parameters, are in
TOOLS.md. The ones that matter day to day:
Finding a key
Tool | What it does |
| Find a credential by service, purpose or env var name. Metadata only. |
| Browse the tree of groups, accounts and projects. |
| One secret in full; optional heavily masked preview ( |
| Everything one project needs, with the env var name for each. |
| The 15 service templates and their fields. |
| Counts, and whether the access code is set or unlocked. |
| Recent activity: which secret went where. |
Using a key
Tool | What it does |
| Write secrets into a |
| Fill |
| Run a command with secrets in its environment, output redacted. |
| Write secrets into a remote server's env file over SSH. |
| Compare a |
| Generate a committable |
| Confirm a secrets file is git-ignored, and fix it if not. |
Adding and organizing
Tool | What it does |
| Open the vault in your browser so you type the key in yourself. |
| Store a value you gave the agent. The value lands in the transcript. |
| Pull an existing |
| Change env var name, notes, tags, environment or expiry. |
| Make a group, account or project by hand. |
| Let a project use a shared key without copying it. |
| Remove a secret or a whole container. Needs |
| Unlock protected secrets for 15 minutes. |
Backups
Tool | What it does |
| Encrypted local snapshot, sealed with this machine's key. |
| What backups exist, read from their headers alone. |
| Inspect one backup without decrypting it. |
| Put a local backup back. Takes a safety snapshot first. |
| Remove a backup file. |
Plus one resource, vault://catalog: every secret as metadata in a single document.
Placeholders
For anything that is not a .env, write a placeholder and let the vault fill it:
# docker-compose.yml
environment:
STRIPE_KEY: "{{vault:stripe/acme/secret_key}}"
SA_JSON: "{{vault:firebase/prod/service_account|base64}}"vault_render_file { filePath: "docker-compose.yml" }Transforms: |base64, |json, |uri.
Running commands
vault_run {
command: "npx",
args: ["wrangler", "secret", "put", "STRIPE_KEY"],
secrets: [{ path: "stripe/acme/secret_key", varName: "STRIPE_KEY" }],
stdinSecret: "stripe/acme/secret_key"
}The child process gets the real value. Every occurrence of it — plain, base64, or URL-encoded — is stripped from the stdout and stderr you get back.
How the keys are protected
The vault is one AES-256-GCM encrypted file at
~/.vault-mcp/vault.enc.The master key lives in your OS keychain: Windows Credential Manager or macOS Keychain, via
@napi-rs/keyring. Nothing to type, nothing to remember, and another user account on the same machine cannot read it.Headless or CI: set
VAULT_MASTER_PASSWORDand the key is derived from it instead.Access code (optional).
vault set-pinsets a 4-12 digit code. It does two jobs: it unlocks the web UI, and it guards individual secrets marked--protected. Secrets added with--protectedare sealed withsha256(masterKey || scrypt(pin)), so they need both the keychain and the PIN. Give the PIN to the agent when it needs one; it unlocks for 15 minutes. Five wrong tries locks it for ten. The PIN is a second gate on top of the keychain, not the primary encryption — a 4-digit PIN alone would be trivial to brute-force, which is why the master key is doing the real work.
Rules the code enforces
No MCP tool result contains a secret value. A test drives all 29 tools and scans every response for known plaintexts, including base64 and URL-encoded forms.
vault_runredacts secret values from command output.Injecting into a git-tracked file, or an un-ignored file inside a repo, is refused unless you pass
force.addToGitignore: truefixes it properly instead.Nothing may be written inside
~/.vault-mcpitself.Every read and injection is appended to
~/.vault-mcp/audit.log— paths and destinations, never values.The web UI is loopback-only and needs a token generated at startup. When an access code is set, the page also asks for it before showing anything, and five wrong tries lock it for ten minutes.
vault_open_uistarts that server but is not given the token, so the agent cannot read the page it opened.A portable backup refuses a passphrase under 10 characters, and no tool accepts a passphrase as an argument.
Backups
Everything in the vault, in one encrypted file. Two kinds, and the difference matters.
Sealed with | Restores on | Use it for | |
Local | this machine's master key | this machine only | Undoing a bad delete. No passphrase to remember. |
Portable | a passphrase you type | any machine | A drive, cloud storage, moving Windows to Mac. |
vault backup # portable: asks for a passphrase (10+ characters)
vault backup --local # local snapshot, no passphrase
vault backups # list what you have
vault restore <file> # merge into the vault
vault restore <file> --replace # make the vault match the backup exactlyOr use the Backup panel in vault ui, which creates the file and hands it straight to your browser's
downloads so you can save it to a drive. The passphrase is typed in the page and never leaves it.
The agent can take local snapshots itself (vault_backup) and does so automatically before a restore or a
delete from the UI. It cannot make a portable backup, because that needs a passphrase and a passphrase must
never be typed into a conversation.
A few things worth knowing:
It is one encrypted file, not a zip of the vault folder. A zip would reveal how many keys you have and what they are called; this reveals only a date and a count.
Copying
vault.encon its own to another machine will not work — the master key lives in that machine's keychain. Portable backups exist precisely for this.The file carries a checksum, so a truncated or tampered copy is refused rather than half-restored.
A restore always takes a safety snapshot first, so even
--replaceis undoable.Lose the passphrase and the portable backup is gone. There is no recovery path, by design.
Commands
vault init Create the vault and master key
vault setup Guided first run
vault add <path> Add a secret or a whole service preset
vault ls [path] List what is stored
vault info <path> Show one secret's metadata (--preview for a mask)
vault get <path> Print a value to stdout (for piping)
vault rm <path> Delete (-r for a container)
vault import <file> --to Import a .env or JSON file
vault link <project> <path> Link a shared secret into a project
vault inject --project ... Write secrets into a local .env
vault set-pin Set the access code (web UI + protected secrets)
vault backup [--local] Portable backup with a passphrase, or a local snapshot
vault restore <file> Restore a backup (--replace to mirror it exactly)
vault backups List backups on this machine
vault export / import-bundle Older bundle format; backup/restore supersedes it
vault ui Local web UI
vault ui-url / ui-stop Link to, or stop, a UI an agent started
vault serve Run the MCP server (what your client launches)
vault install Register with Cursor, Windsurf, Antigravity, Claude…
vault status / audit / presetsWhere things live
MCP server name |
|
Registered by |
|
CLI command |
|
Vault directory |
|
Encrypted secrets |
|
Backups |
|
Activity log |
|
Master key | Windows Credential Manager / macOS Keychain, service |
Web UI |
|
Development
npm run build # tsup -> dist/
npm test # vitest, 83 tests
npm run typecheckLayout:
src/core/ crypto, keychain, store, envfile, importer, template, presets, git guards, audit, backup
src/mcp/ server + tools (read, inject, run, manage, ssh, backup, open-ui)
src/cli/ commander CLI
src/ui/ loopback web UI with the access-code lock screen
test/ core, vault, backup, git-guard, and the no-leak suiteHow much fits
There is no hard limit. Measured on this machine:
Secrets | Vault file | Search | Read one |
100 | 0.09 MB | 11 ms | 2 ms |
1,000 | 0.91 MB | 11 ms | 45 ms |
2,000 | 1.83 MB | 5 ms | 21 ms |
Thousands of keys are fine. A single value can be as large as you like within reason — a PEM private key or a Firebase service-account JSON is normal. The whole vault is held in memory while the server runs, so this is built for a person's keys, not for a company-wide store.
Known limits
vault getprints a value by design; do not run it on a shared screen.The web UI can reveal values. It is local-only, token-gated and code-gated, but it is a deliberate hole in the "never show a value" rule, for the human, not for the agent.
The audit log is append-only but not tamper-proof; anything that can read the vault file can also rewrite it.
The "the agent never sees a value" property covers the MCP tool surface. It keeps keys out of your transcript; it is not a sandbox against an agent that also has shell access to your machine.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
No tool schema history has been recorded yet.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Secrets for developers and agents—secure context and workflows without exposing secret values.
A secret store for AI agents: the agent never sees the plaintext.
Encrypted secret store and rotation for autonomous agent credentials
- TAPOAuthtech.human
Credential isolation for AI agents: placeholder secrets, policy checks, optional human approval.
Related MCP Servers
- AlicenseAqualityDmaintenanceShare encrypted, self-destructing secrets from your AI agent. Zero-knowledge E2E encryption. Agent-blind input sources (env:, file:, dotenv:) keep secrets out of LLM context.481MIT
- AlicenseNot gradedqualityCmaintenanceEnables LLM agents to securely use credentials like passwords and API keys without exposing them in the context window, through encrypted storage and proxy-based injection.62MIT
- AlicenseAqualityDmaintenanceEnables AI agents to securely use real secrets (API keys, database passwords) by requiring human approval for each release, ensuring secrets never enter the model's context.2Apache 2.0
- AlicenseNot gradedqualityAmaintenanceEnables AI agents to securely use API keys by storing them in an encrypted vault and injecting them on demand with user approval, without exposing the key values to the model.1MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/MHasnainJafri/vault-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server