Introduction
Some MCP Servers require you to put API keys directly in mcp.json. However, hardcoding credentials in a config file comes with real risks.
- Accidental Git commits: A missing
.gitignoreentry or a carelessgit addcan push your API key to a repository - Exposure to AI agents: AI agents like Claude Code have access to the filesystem. If
mcp.jsonis read, your API key ends up in the AI's context - File leaks: If your machine is lost, stolen, or accessed without authorization, credentials stored in plain text are immediately compromised
In this article, I'll walk through two approaches to keep API keys out of mcp.json, using Backlog MCP Server as an example.
Option 1: Keychain (Mac only)
This approach stores the API key in macOS Keychain and retrieves it dynamically when the MCP server starts.
1. Generate a Backlog API key
Generate an API key from the Backlog settings page.

2. Save it to Keychain
Use the security add-generic-password command to register the API key in Keychain.
security add-generic-password -a "$USER" -s "BACKLOG_API_KEY" -wYou'll be prompted to enter the password interactively.
password data for new item:
retype password for new item:The value passed to -s (BACKLOG_API_KEY) is the service name in Keychain. Choose something descriptive — you'll reference it later with find-generic-password.
Note: By placing -w at the end, the password is never passed as a command-line argument, which prevents it from appearing in your shell history.
3. Configure mcp.json
The official setup example looks like this. (This article uses npx.)
{
"mcpServers": {
"backlog": {
"command": "npx",
"args": ["backlog-mcp-server"],
"env": {
"BACKLOG_DOMAIN": "your-domain.backlog.com",
"BACKLOG_API_KEY": "your-api-key"
}
}
}
}Here's the Keychain-based version.
{
"mcpServers": {
"backlog": {
"command": "bash",
"args": [
"-c",
"BACKLOG_API_KEY=$(security find-generic-password -a \"$USER\" -s \"BACKLOG_API_KEY\" -w) exec npx backlog-mcp-server"
],
"env": {
"BACKLOG_DOMAIN": "your-backlog-domain"
}
}
}
}The command is changed to bash, and inside args, the API key is fetched from Keychain before launching npx backlog-mcp-server. security find-generic-password -w prints the stored value to stdout, which is then assigned to the BACKLOG_API_KEY environment variable.
The args becomes a bit harder to read, but the API key never appears in mcp.json.
Note: BACKLOG_API_KEY is only set within this bash -c subprocess. When exec npx backlog-mcp-server replaces the bash process, the environment variables are inherited — so the MCP server receives the key correctly. The variable does not propagate to your shell session, so running echo $BACKLOG_API_KEY in your terminal will return nothing.
With this setup, the API key is never stored in plain text in any file, significantly reducing the risk of exposure to AI agents or file leaks.
Option 2: 1Password CLI (cross-platform)
If you use 1Password, the 1Password CLI is another option — and unlike Keychain, it works on Windows too.
Here's what the configuration looks like with 1Password CLI.
{
"mcpServers": {
"backlog": {
"command": "op",
"args": [
"run",
"--env-file=/dev/null",
"--",
"npx",
"backlog-mcp-server"
],
"env": {
"BACKLOG_DOMAIN": "your-domain.backlog.com",
"BACKLOG_API_KEY": "op://your-vault/your-item/your-field"
}
}
}
}Here's what each setting does.
"command": "op"— Launches the 1Password CLI as the main process"run"— Theop runcommand. It replaces anyop://references inenvwith the actual secret values before launching the child process"--env-file=/dev/null"— By default,op runlooks for a.envfile. This disables that behavior so only theenvblock inmcp.jsonis used"--"— A separator indicating that everything after this is the child command, not anopoption"npx", "backlog-mcp-server"— The actual MCP server command to runBACKLOG_API_KEY: "op://your-vault/your-item/your-field"— A secret reference pointing to a specific field in your 1Password vault.op rundetects this and substitutes the real value before passing it tonpx
The API key is never stored in plain text — it's fetched securely from 1Password at runtime.
Conclusion
Hardcoding API keys in mcp.json creates risks you might not notice until it's too late — accidental Git commits, AI agents reading your credentials, or a leaked config file.
Here's a summary of the two approaches covered in this article.
- Option 1: Keychain — Mac only. No extra tools required, easy to set up
- Option 2: 1Password CLI — Cross-platform. The smoothest option if you're already using 1Password
When setting up an MCP Server, take a moment to think about how you're managing credentials — not just whether the server works.
Thank you for reading this far!