The default setup for kagimcp requires placing your KAGI_API_KEY as plain text in configuration files, CLI arguments, or environment variables. This is convenient but carries risks: keys can be accidentally committed to version control, leaked in shell history, or exposed in process listings.
This guide covers three more secure alternatives for managing your Kagi API key.
- Approach 1: macOS Keychain
- Approach 2: Secret Manager / Pass (cross-platform)
- Approach 3: Encrypted .env File with SOPS
- Comparison
Platform: macOS
Apple Keychain is the native credential store on macOS. It encrypts secrets at rest using your login password and provides access control per-application.
security add-generic-password \
-a "$USER" \
-s "kagi-api-key" \
-w "YOUR_API_KEY_HERE"security find-generic-password -a "$USER" -s "kagi-api-key" -wYou cannot embed shell commands directly in the JSON config. Instead, use a wrapper script.
Create ~/.local/bin/kagimcp-wrapper.sh:
#!/usr/bin/env bash
export KAGI_API_KEY="$(security find-generic-password -a "$USER" -s "kagi-api-key" -w)"
exec uvx kagimcp "$@"chmod +x ~/.local/bin/kagimcp-wrapper.shThen configure Claude Desktop:
{
"mcpServers": {
"kagi": {
"command": "/Users/YOUR_USERNAME/.local/bin/kagimcp-wrapper.sh",
"args": []
}
}
}claude mcp add kagi \
-e KAGI_API_KEY="$(security find-generic-password -a "$USER" -s "kagi-api-key" -w)" \
-- uvx kagimcpThe key is resolved at the time you run the command and stored in Claude Code's config. To rotate keys, update the Keychain entry and re-run the command above.
security delete-generic-password -a "$USER" -s "kagi-api-key"Platform: Linux, macOS, WSL
pass is the standard Unix password manager. It stores each secret as a GPG-encrypted file inside ~/.password-store/. It works on Linux, macOS (via Homebrew), and WSL.
# macOS
brew install pass gnupg
# Debian/Ubuntu
sudo apt install pass gnupg
# Fedora
sudo dnf install pass gnupg2If you do not already have a GPG key:
gpg --full-generate-keyInitialize the password store with your GPG key ID:
pass init "YOUR_GPG_KEY_ID"pass insert kagi/api-key
# You will be prompted to enter and confirm the key.pass show kagi/api-key#!/usr/bin/env bash
export KAGI_API_KEY="$(pass show kagi/api-key)"
exec uvx kagimcp "$@"chmod +x ~/.local/bin/kagimcp-wrapper.shThen reference the wrapper in your Claude Desktop config:
{
"mcpServers": {
"kagi": {
"command": "/home/YOUR_USERNAME/.local/bin/kagimcp-wrapper.sh",
"args": []
}
}
}claude mcp add kagi \
-e KAGI_API_KEY="$(pass show kagi/api-key)" \
-- uvx kagimcp- Secrets are encrypted with your GPG key -- no plaintext files on disk.
- The password store is a regular Git repo, so you can sync encrypted secrets across machines.
- Integrates with
gpg-agentfor cached passphrase entry. - Ecosystem of extensions and GUIs (e.g.,
qtpass,browserpass).
Platform: Linux, macOS, Windows
SOPS (Secrets OPerationS) by Mozilla encrypts and decrypts files while keeping the structure readable. It supports age, gpg, AWS KMS, GCP KMS, and Azure Key Vault as encryption backends.
This approach is useful when you want to keep configuration in a file (e.g., for team sharing or CI/CD) without exposing secrets in plaintext.
# macOS
brew install sops age
# Linux (using Go)
go install github.com/getsops/sops/v3/cmd/sops@latest
# Install age: https://github.com/FiloSottile/age#installationGenerate an age key (simpler alternative to GPG):
age-keygen -o ~/.config/sops/age/keys.txtNote the public key printed to stdout (starts with age1...).
Create a .sops.yaml in your project or home directory:
creation_rules:
- path_regex: \.env\.enc$
age: "age1your_public_key_here"Create a plaintext .env file (temporarily):
echo 'KAGI_API_KEY=YOUR_API_KEY_HERE' > .env.tmpEncrypt it:
sops encrypt --input-type dotenv --output-type dotenv .env.tmp > .env.enc
rm .env.tmpThe resulting .env.enc file contains encrypted values but readable keys. It is safe to commit to version control.
#!/usr/bin/env bash
# Decrypt and export variables from the encrypted env file
eval "$(sops decrypt --input-type dotenv --output-type dotenv /path/to/.env.enc)"
export KAGI_API_KEY
exec uvx kagimcp "$@"chmod +x ~/.local/bin/kagimcp-wrapper.shThen reference the wrapper in your Claude Desktop config as shown in the previous approaches.
claude mcp add kagi \
-e KAGI_API_KEY="$(sops decrypt --input-type dotenv --output-type dotenv /path/to/.env.enc | grep KAGI_API_KEY | cut -d= -f2)" \
-- uvx kagimcp- Encrypted files are safe to commit -- only people/systems with the decryption key can read the values.
- Supports cloud KMS backends (AWS, GCP, Azure) for team and CI/CD use.
- File structure (key names) remains visible for review, only values are encrypted.
- Can encrypt/decrypt individual values in YAML and JSON files too.
| Feature | macOS Keychain | pass (GPG) | SOPS (age/GPG/KMS) |
|---|---|---|---|
| Platform | macOS only | Linux, macOS, WSL | Linux, macOS, Windows |
| Encryption | AES-256 (system) | GPG | age, GPG, or cloud KMS |
| Setup complexity | Low | Medium | Medium |
| Team/CI-friendly | No | Partial (Git sync) | Yes (cloud KMS support) |
| GUI available | Yes (Keychain Access) | Yes (QtPass) | No |
| Requires extra tools | No (built-in) | gpg, pass |
sops, age or gpg |
- macOS single-user: Use Keychain -- zero additional tools, native integration.
- Linux single-user: Use
pass-- standard, well-supported, GPG-encrypted. - Teams or CI/CD pipelines: Use SOPS with a cloud KMS backend -- shareable, auditable, no shared secret keys.
- Never commit plaintext API keys to version control. Add patterns like
.env,*.key, andcredentials.jsonto your.gitignore. - Rotate keys periodically via the Kagi API settings page.
- Use the minimum required scope when Kagi introduces scoped API keys.
- Audit shell history -- commands containing API keys may be saved in
~/.bash_historyor~/.zsh_history. Use a leading space (ifHISTCONTROL=ignorespaceis set) to prevent recording sensitive commands. - Restrict file permissions on any file that contains or has access to secrets:
chmod 600 ~/.local/bin/kagimcp-wrapper.sh