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.
guard: an agent does not read a secret file
keep lets an agent use a secret without holding it, but nothing stopped an agent from holding one
anyway. The leak keep's first scan found was exactly that: an agent looking for a database URL ran
grep -n "…\|PG\|…" backend/.env, the base64 body of a Firebase private key happened to contain
"PG", and the key went into the transcript. There was no intent and no attack, just a grep.
keep guard --install # a Claude Code PreToolUse hook (Bash|Read); keeps every other hook; backs settings up
keep guard --uninstallA command that prints a secret file (cat, grep, head, sed, awk, git diff, base64 <,
curl -d @.env, and so on) or a Read of one (.env*, *.pem, *.key, id_rsa,
*service-account*.json, credentials.json, .netrc, .npmrc, …) is refused. The refusal
carries the way forward, which an agent can take on its own with no human awake:
keep import <file> stores every value without printing one, and keep run --with NAME -- … uses
it. Nothing that doesn't print a secret is touched: templates (.env.example), cp .env.example .env,
source .env && npm start, writing to a secret file, ls, mv, and keep's own commands.
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 # 29 tests; the file backend, no keychain touched
node scripts/mutants.mjs # breaks each safety property on purpose and demands the suite goes redThe agent toolkit
keep is the hold secrets leg of tools-for-agents — an operating system for agents.
Nine zero-dependency, MCP-native tools that form one loop, with a self at its centre:
🛰️ | coordinate — The company's work, made visible. | |
🔎 | read code — Read code without reading files. | |
⚒ | run safely — Run it before you claim it works. | |
🔐 | keep | hold secrets — Use a secret without holding it. |
🧠 | remember — A second brain that outlives the context window. | |
🧭 | read the web — The web, ~90% lighter. | |
🔻 | read data — Read data without reading the blob. | |
◎ | recall it all — One query. Every store you have. | |
👁 | see — Look at what you built. | |
👻 | the self at the centre — A self that persists across sessions. Not a tool: it is what the agent is while it calls these. |
Reading this as an agent? /llms.txt is the map, and
/tools.json hands you all 79 MCP tools — every name, every
description, every install command — in one fetch, without cloning anything.
License
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.19 PyPIMIT
- 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