keep
Click on "Deploy 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., "@keeprun gh api user with GH_TOKEN"
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.
đ keep
Use a secret without holding it. An encrypted vault whose values are injected into the commands an agent runs, and redacted from everything that comes back. The agent works with âčkeep:GH_TOKENâș. The token itself never enters its context, its transcript, or anything that reads the transcript later.
Part of tools-for-agents. Zero dependencies: the Node standard library plus your OS keychain. CLI + MCP.
Why this exists
An agent that needs an API key today has one way to get it: read it. It runs cat .env or echo $TOKEN, or it asks you to paste the key into the chat. From that moment the value sits in the model's context. It also sits in the session transcript on disk (~/.claude/projects/*.jsonl), and every process that reads transcripts can see it: summarisers, search indexes, memory systems that dream sessions into long-term memory.
Measured on the machine this was built on, on the day it was built: the first keep scan --transcripts went through 7,335 transcript files (1.28 GB) in ten seconds and found a Firebase service-account private key. An agent had read the key out of a project's .env weeks earlier, and it had been in a transcript ever since.
keep closes that path. The agent names the secret, and keep hands the value to the program, never to the agent:
keep run --with GH_TOKEN -- gh api user
keep run -- curl -H 'Authorization: Bearer {{OPENAI_API_KEY}}' https://api.openai.com/v1/modelsAnything the program prints goes through a redactor built from every kept value, and the agent reads âčkeep:OPENAI_API_KEYâș wherever the value would have appeared.
Related MCP server: Keiko
Install
git clone https://github.com/tools-for-agents/keep.git && cd keep
node src/cli.js init # creates ~/.keep; the master key goes into the OS keychain
ln -s "$PWD/src/cli.js" ~/.local/bin/keep
claude mcp add keep --scope user -- node "$PWD/mcp/mcp-server.js"Node 22+. Nothing to npm install.
For the person
keep set GH_TOKEN # typed hidden, never echoed, never in shell history
pbpaste | keep set OPENAI_API_KEY # or piped
keep set DEPLOY_KEY --allow gh,fly # only these programs may receive it
keep import .env # keep every KEY=value in a dotenv file (then delete the file)
keep list # names, policy, usage â and what agents have asked for
keep audit # every use: when, which names, which command, exit code
keep scan --transcripts # has anything already leaked?
keep redact --patterns < in > out # a filter: kept values and known key shapes â their nameskeep redact is for the other tools that store what an agent wrote: a memory that dreams transcripts, a log shipper, a search index. ghost pipes every session through it before dreaming, so a key an agent once printed does not end up in long-term memory. With --patterns it also masks anything shaped like a well-known key, and it masks a private key as a whole block, body included, not just its BEGIN line.
For the agent (MCP)
Tool | What it does |
| names, allowed commands and usage for each kept secret, never values; also the secrets you asked for that have not arrived yet |
| runs argv with the named secrets injected as env vars; |
| reports where a kept value, or anything shaped like a well-known key, shows up in files or transcripts: file, line and name, never the value |
| asks your person for a secret you lack; it shows up in their |
| the usage log |
No tool returns a value. That is the design, not a gap in it, and a test fails if a tool whose name looks like get, read, reveal or export ever appears.
What the redactor catches
A secret leaks in more shapes than its own. curl -v prints the Authorization header, and a Basic header is base64("user:" + secret): the secret's bytes, shifted by the username and written in another alphabet. So every value becomes a set of needles:
the raw value, its JSON-escaped form and its URL-encoded form;
base64 and base64url at all three byte alignments. base64 works in 3-byte groups, so how the secret encodes depends on how many bytes came before it. keep encodes it after 0, 1 and 2 bytes of padding and keeps only the characters that depend on the secret alone, which finds it inside any base64 string.
Output is streamed, and a value can be split across two chunks. The redactor holds back (longest needle â 1) characters at each boundary. A test splits a secret at every possible position and checks all of them.
Policy
keep set NAME --allow gh,curl restricts a secret to named programs. A restricted secret:
cannot be handed to
sh -c,node -eorpython -c, which is the move an agent would make if it had been talked into exfiltrating the value;must be run by name (
gh) and not by path (./gh), because a file namedghin the working directory is not theghyou meant.
Honest limits
keep is built against accidental exposure (a value in a context window, a transcript or a log) and it narrows misuse. It is not a boundary against a hostile process running as you, and it says so here rather than let you find out:
Anything running as your user can ask the keychain for the master key, or read
~/.keep/master.keyon the file backend, just as it could read your.env.A program you allow can do whatever it likes with the value.
--allow curllets curl send the key to any host.Redaction catches the shapes listed above. It does not catch a value that was reversed, hashed, split or re-encoded some other way before it was printed.
keep statussays which backend holds the master key. On Linux withoutsecret-toolit is a 0600 file next to the vault, which is weaker, and keep prints that when the vault is created.
Files
| the values: AES-256-GCM, one authenticated blob. If it has been altered it fails to open; it never decrypts to garbage |
| names, allow-lists, usage counts, requests. Never a value |
| one line per use, with the command already redacted |
OS keychain · | the 32-byte master key (macOS |
Every file is 0600 in a 0700 directory, and each write goes to a temp file first and is renamed into place, so a crash never leaves half a vault.
Env | |
| vault directory (default |
|
|
| where |
Test
node --test # 23 tests; the file backend, no keychain touched
node scripts/mutants.mjs # breaks each safety property on purpose and demands the suite goes redLicense
MIT
This server cannot be deployed
Maintenance
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
- AlicenseNot gradedqualityCmaintenanceEnables secure credential storage for AI agents by encrypting secrets and providing agent-invisible references, ensuring sensitive data never leaks to the model.MIT
- FlicenseNot gradedqualityCmaintenanceEnables AI agents to securely use secrets by running commands with environment-injected credentials and sanitizing output to prevent leakage.1-
- AlicenseNot gradedqualityCmaintenanceEnables deterministic, no-LLM scrubbing of secrets from text or logs before they enter agent context, supporting redaction, masking, and hashing without ever leaking the original value.MIT
- AlicenseCqualityCmaintenanceEnables AI agents to securely store and manage encrypted secrets locally while using them indirectly through environment-variable injection or file writes, so plaintext values never enter the agent's context.8MIT