keymaster-mcp
Imports credentials from 1Password CSV exports into Keymaster's encrypted vault.
Imports credentials from Bitwarden CSV exports into Keymaster's encrypted vault.
Imports secrets from .env files into Keymaster's encrypted vault.
Acts as a Git credential helper, allowing Git to retrieve credentials from Keymaster during authenticated operations.
Stores GitHub credentials such as SSH keys and can supply them for authenticated GitHub/Git operations.
Finds Jenkins credentials by job URL or host and injects basic auth for user:token credentials when making HTTP requests to Jenkins.
Stores MySQL database credentials and injects MySQL environment variables such as MYSQL_PWD for commands run with credentials.
Stores Okta logins and TOTP seeds, allowing agents to retrieve current 2FA codes for Okta.
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., "@keymaster-mcp why did the deploy-api job fail on https://ci.example.com/job/deploy-api/412?"
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.
Keymaster is a local, encrypted credential vault with an MCP server built in. Tell your agent "check the last build on ci.example.com" and it finds the right login from the URL, a name or an alias, then uses it. You don't paste passwords, you don't say where they're kept, and in most cases the secret never enters the conversation.
you ─► "why did the deploy-api job fail on https://ci.example.com/job/deploy-api/412?"
agent ─► find_credentials("https://ci.example.com/job/deploy-api/412") → jenkins-ci (host match)
agent ─► http_request(ref="jenkins-ci", url=".../412/consoleText") → auth injected, output scrubbedInstall
Script: macOS and Linux, one line, nothing else needed:
curl -fsSL https://raw.githubusercontent.com/kiraa06/keymaster/main/install.sh | shIt installs uv if you don't have it and installs km and
keymaster-mcp from the latest release, checksum-verified and with their own Python (your
system Python is left alone). It registers the MCP server with Claude Code and offers to create
your vault. Re-run it any time to upgrade.
uv:
uv tool install git+https://github.com/kiraa06/keymaster
km init && km install-mcppipx:
pipx install git+https://github.com/kiraa06/keymasterFrom source:
git clone https://github.com/kiraa06/keymaster && cd keymaster
uv tool install --editable .Requirements
macOS 12+, or Linux with a Secret Service keyring (GNOME Keyring / KWallet)
Any MCP client: Claude Code, Claude Desktop, Cursor, …
Optional: Touch ID (macOS),
zenityfor approval dialogs on Linux,xclip/wl-clipboard
Related MCP server: keywarden
Use it
km init # master passphrase + one-time recovery code
km add jenkins-ci -t token -u ada --url https://ci.example.com -a jenkins -a ci
km add aws-prod -t aws -u AKIA… -f region=eu-central-1 -p sealed
km add orders-db -t database -u app -f host=db1.internal -f port=5432
km add github -t ssh_key --from-file ~/.ssh/id_ed25519 --url github.com
km add okta -u ada --url '*.okta.com' --totp # with its 2FA seed
km touchid setup # approve with your fingerprint 👆Then ask your agent to do things. It checks Keymaster whenever a task needs a login (see below).
Command | |
| look things up |
| manage |
| use |
| undo a change |
| check |
| lock up |
| keys |
| move / restore |
| misc |
What it does
Finds the right login from whatever the agent has
A credential can be looked up by its name, aliases, URLs (full URLs with path
prefixes, bare hosts, *.wildcards), a host field, tags or username, and typos are
tolerated. https://ci.example.com/job/deploy-api/412 finds jenkins-ci, and so do jenkins,
ci, and jenkns. When two credentials fit equally well, the agent is told to ask you instead
of guessing.
Makes sure the agent checks it first
MCP server instructions alone are easy to miss. With many servers configured, Claude Code defers
their tools, so the model sees only tool names, and it truncates long instructions. So
km install-mcp sets up three layers:
The MCP server. Its instructions and tool descriptions lead with "check Keymaster first".
A
UserPromptSubmithook (keymaster-hook, about 0.15s). When a prompt mentions creds, passwords, tokens, keys, logins or 2FA, or matches a stored credential's name, alias or host, it adds a reminder to the agent's context, naming the credentials that match. It only ever prints names, never secrets.A short rule in
~/.claude/CLAUDE.md, between<!-- keymaster:start/end -->markers.
You can opt out of either extra layer with --no-hook / --no-claude-md, and
km uninstall-mcp removes all three. Other hooks in settings.json are preserved, and the file
is backed up first.
Uses secrets without showing them
Tool | What the agent gets |
| the response. Auth is injected (basic for |
| command output with the secret scrubbed, including its base64, URL, hex and |
| the current 2FA code |
| nothing. You paste it yourself, and the clipboard clears after 30s |
| the raw value, only when it must type it into a browser, and only if the policy allows |
Asks you first
Every credential has a policy:
policy | agent can use it | agent can reveal it |
| ✅ | ✅ |
| ✅ | after you approve; "Allow for 8h" remembers the approval |
| ✅ | ❌ never |
| each time you approve | each time you approve |
Approval is a native dialog or Touch ID, shown to you and not the agent. The agent can't loosen a
policy or purge a credential without your approval. Running km through the agent's shell
doesn't get around this, because without a real terminal km treats the caller as the agent.
You type secrets, not the agent
add_credential defaults to secret_source="prompt": a secure dialog pops up, you type, and the
agent only hears "stored". It can also read the secret from the clipboard (then wipe it), from a
file (SSH keys, service-account JSON), or generate one it never sees.
generate_secret(store_in=…) rotates a password the same way.
Keeps receipts
Every find, reveal, use, approval and change goes into an HMAC hash-chained audit log.
km audit --verify pinpoints any edited or deleted line. km health grades the vault A–F: weak,
reused, expired, stale and unused secrets, plus breached passwords via HaveIBeenPwned (with
k-anonymity, so only 5 hash characters leave your machine).
Is hard to lose
It keeps version history per credential with rollback, a trash can, 20 rolling encrypted
snapshots, a recovery code, and a separately-encrypted km export. It can import from Chrome,
Bitwarden and 1Password CSVs or .env files, and it works as a git credential helper:
git config --global credential.helper '!km git-credential'.
Security
Encryption: AES-256-GCM under a random data key, wrapped by Argon2id (64 MiB) from your passphrase, with a second key slot for a 150-bit recovery code.
Integrity: tampering with the file, splicing an old copy under a new header, or rolling back to an older copy are all detected.
While unlocked: the key lives in the macOS Keychain / Secret Service, never in a file or on a command line.
km lock/km panicdrops it, and you can setauto_lock_hours.Brute force: wrong passphrases trigger a backoff. Everything is written atomically and file-locked, with
0600permissions.
Threat model: Keymaster protects secrets at rest and keeps them out of AI transcripts by
default. It does not stop malware already running as you while the vault is unlocked, and the
agent isn't sandboxed. A determined prompt injection could get run_with_credential to print a
secret in a form the scrubber misses. Use sealed / strict for crown jewels.
Details: docs/DESIGN.md. To report a vulnerability, see
SECURITY.md.
Other MCP clients
km install-mcp does it for Claude Code. For anything else (Claude Desktop, Cursor, Windsurf, …):
{ "mcpServers": { "keymaster": { "command": "~/.local/bin/keymaster-mcp" } } }Use the absolute path that which keymaster-mcp prints.
Troubleshooting
The agent looked for creds somewhere else (~/.aws, gh auth, env vars). Run
km install-mcp again: it adds the prompt hook and the CLAUDE.md rule if they're missing. Then
start a new Claude Code session, since hooks and CLAUDE.md load at startup.
The agent says the vault is locked. Run km unlock, or let it call unlock_vault, which
asks you for the passphrase in a dialog. If you set auto_lock_hours, this is expected.
No approval dialog appears. On macOS, check that the dialog isn't hiding behind other windows.
Approvals time out after 90s and count as denied. On Linux, install zenity. On a headless
box, run km config set approval deny and use open / sealed policies.
Keychain unavailable on Linux. Keymaster needs a Secret Service provider. Install and
start GNOME Keyring (gnome-keyring-daemon) or KWallet in your session.
command not found: km. ~/.local/bin isn't on your PATH:
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc && exec zshI forgot my passphrase. Run km unlock and paste the recovery code. Then km passwd sets a
new passphrase and km recovery mints a fresh code.
Everything else. Run km doctor.
Uninstall
km uninstall-mcp # MCP server + prompt hook + CLAUDE.md rule
uv tool uninstall keymaster
rm -rf ~/.keymaster # ⚠ deletes your vault — `km export` first if you want itContributing
Issues and pull requests are welcome; see CONTRIBUTING.md.
License
Available Tools
23 toolsadd_credentialA
Store a new credential. Keys the agent can later look it up by: name, aliases, urls
(full URLs, bare hosts, or wildcards like *.corp.com), and tags.
secret_source (how the main secret is obtained — prefer ones that keep it out of the chat):
prompt (default) user types it into a secure macOS dialog
clipboard read from clipboard, then clear it (user copies it first)
file read from `secret_file` (great for SSH keys / service-account JSON)
generate create a strong random password/passphrase
value use `secret` as given (only if the user already pasted it in chat)
none no main secret (e.g. only extra_secrets / notes)
`secret_field` overrides the field name (default depends on type: password/token/key/...).
`extra_secrets` e.g. {"totp_secret": "JBSW..."} or {"api_secret": "..."}.
`fields` = non-secret extras, e.g. {"host": "db.internal", "port": "5432", "region": "ap-south-1"}.
policy: open | confirm | sealed | strict (default from config).Inputs: name (required), tags, type, urls, +14 more.
audit_logARead-only
Recent vault activity (who revealed/used/changed what, when). Optionally for one credential.
Inputs: ref, limit.
copy_to_clipboardA
Copy a secret (default: main secret; or 'username', 'totp', any field) to the macOS clipboard for the human to paste. Auto-clears after N seconds. The agent never sees it.
Inputs: ref (required), field, purpose, seconds.
credential_historyARead-only
Previous versions of a credential's secrets (values hidden) for auditing / rollback.
Inputs: ref (required).
credential_typesBRead-only
The supported credential types and the main secret field of each.
Inputs: no named parameters.
delete_credentialADestructive
Move a credential to the trash (recoverable with restore_credential).
Inputs: ref (required).
find_credentialsARead-only
ALWAYS THE FIRST STEP when anything needs credentials — a login, an API call, a CLI or DB
that needs auth, a 2FA code, or the user asking for a password/token/key. Pass whatever you
have: a URL, hostname, name, alias or phrase ("https://ci.example.com/job/x", "jenkins",
"prod db", "aws sg"). Returns ranked matches, metadata only (secrets hidden), and flags
ambiguous when you should ask the user which one.
Inputs: query (required), tag, type, limit.
generate_secretCRead-only
Generate a strong password or diceware-style passphrase. With store_in (a credential ref)
it is written straight into that credential (old value kept in history) and NOT returned —
use this for rotation so the new secret never enters the chat.
Inputs: kind, words, length, reason, +3 more.
get_credentialARead-only
Get one credential by id, name, alias or URL. With reveal=true the raw secret values are
returned (subject to its policy — may pop an approval dialog for the user). Always give a
short purpose when revealing. Prefer http_request/run_with_credential over revealing.
Inputs: ref (required), fields, reveal, purpose.
get_totpBRead-only
Current 2FA/TOTP code for a credential that has a totp_secret (plus seconds remaining).
Inputs: ref (required), purpose.
health_reportARead-only
Audit the vault: weak, reused, expired/expiring, stale, unused and (optionally) breached passwords via HaveIBeenPwned k-anonymity (only 5 hash chars leave the machine). Graded A–F.
Inputs: check_pwned.
http_requestA
Make an HTTP request authenticated with a stored credential, without exposing the secret. auth: auto (basic for user+password/user+token e.g. Jenkins; bearer for bare tokens), basic, bearer, none, header:, query:. Placeholders {{km.password}}, {{km.username}}, {{km.token}}, {{km.}} are substituted in url/headers/body. Only hosts registered on the credential are allowed (anti-exfiltration guard). Response body is scrubbed of the secret.
Inputs: ref (required), url (required), auth, body, +7 more.
list_credentialsARead-only
List every stored credential (metadata only — names, types, usernames, URLs, aliases, tags, policies). Use this to answer "what creds / passwords / logins / keys do you have?". Optionally filter by type or tag.
Inputs: tag, type.
list_trashBRead-only
List soft-deleted credentials.
Inputs: no named parameters.
lock_vaultA
Lock the vault now (removes the key from the keychain). Unlocking needs the user.
Inputs: no named parameters.
purge_credentialADestructive
Permanently destroy a trashed credential. Always requires the user's approval.
Inputs: ref (required).
restore_credentialB
Restore a credential from the trash.
Inputs: ref (required).
revoke_approvalsA
Cancel every time-boxed 'Allow for …' approval, so the next reveal asks again.
Inputs: no named parameters.
rollback_credentialA
Restore a credential's username+secrets to an earlier version (current one is kept in history).
Inputs: ref (required), version (required).
run_with_credentialA
Run a bash command with the credential injected as environment variables; stdout/stderr
are scrubbed of the secret (and its base64/url/hex encodings).
Always set: KM_NAME, KM_USERNAME, KM_SECRET (main secret), KM_ for every secret and
field (KM_PASSWORD, KM_TOKEN, KM_KEY, KM_HOST...), KM_URL, KM_BASIC_AUTH.
Type extras — aws: AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY/AWS_SESSION_TOKEN/AWS_REGION;
database: PGHOST/PGPORT/PGUSER/PGPASSWORD/PGDATABASE/MYSQL_PWD;
ssh_key: KM_KEY_FILE (temp 0600 file, shredded after) + GIT_SSH_COMMAND.
env maps extra var names to fields, e.g. {"JENKINS_TOKEN": "token"} or templates
{"CREDS": "{{km.username}}:{{km.password}}"}. stdin also supports {{km.*}} placeholders.
Example: curl -su "$KM_USERNAME:$KM_TOKEN" https://ci.example.com/api/json
Inputs: ref (required), command (required), cwd, env, +3 more.
unlock_vaultA
Unlock the vault by asking the user for the master passphrase in a secure dialog (the passphrase never passes through the agent).
Inputs: no named parameters.
update_credentialA
Modify a credential. Only the arguments you pass change. To change the main secret use secret_source (prompt / clipboard / file / generate / value) — the previous value is kept in version history for rollback. Loosening the policy requires the user's approval. Use add_urls/add_aliases whenever you learn a new way the user refers to this credential.
Inputs: ref (required), name, notes, fields, +20 more.
vault_statusBRead-only
Is the vault initialised/unlocked, how many credentials, approval mode, etc.
Inputs: no named parameters.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 23 tools
Most tools have clearly distinct purposes: discovery (find_credentials), retrieval (get_credential), mutation (add/update/delete), and usage (http_request, run_with_credential) are well separated. A few pairs blur slightly — copy_to_clipboard vs get_credential(reveal=true), and generate_secret vs add_credential's secret_source=generate — but descriptions make the intended roles clear.
Nearly every tool follows a consistent snake_case verb_noun or noun pattern (lock_vault, list_credentials, add_credential, update_credential, delete_credential, rollback_credential, health_report). No style mixing or vague single-word verbs.
23 tools is on the heavy side for a credential vault, and a few (list_trash, restore_credential, purge_credential, credential_history) could plausibly fold into fewer operations. Still, most tools map to a genuinely distinct capability, so it's borderline rather than excessive.
The surface covers the full lifecycle: vault lock/unlock, credential CRUD, soft-delete/restore/purge, version history and rollback, secret generation, usage without exposure, TOTP, auditing, and health reporting. No obvious dead ends for the stated domain.
Maintenance
Related MCP Connectors
Password vault for AI agents with scoped, user-approved access
Credential broker for AI agents: scoped, revocable API access with policy enforcement and audit.
Give your AI hands. Identity, credential vault, and API gateway for autonomous agents.
Governed access to sensitive data, secrets and APIs for AI agents. A signed proof for each decision.
Related MCP Servers
- FlicenseBqualityDmaintenanceEnables secure retrieval of credentials from 1Password vaults for use by AI agents, supporting integration with browser automation for automated login.1-
- AlicenseAqualityCmaintenanceEnables AI agents to make authenticated API calls and run commands with secrets injected, while keeping credentials completely hidden from the model, with policy enforcement, grants, and audit logging.6MIT
- FlicenseNot gradedqualityCmaintenanceEnables agents to securely use credentials for GitHub, Cloudflare, OpenAI, Stripe, and xAI without ever reading the secret values, including credential health, rotation, and audit features.-
- AlicenseAqualityCmaintenanceEnables AI agents to securely manage local credentials, obtain short-lived tokens for authenticated API access, and audit every use by purpose.9MIT