Coding agents · MCP
API keys in MCP config files: the risk and the fix
Short answer
An API key typed into an MCP config file, such as Claude Code’s .mcp.json or Cursor’s mcp.json, sits in plain text on disk, often in a project folder that is committed to git, synced or read by the agent itself.
Claude Code and Cursor can both read keys from environment variables instead, so the config file holds only a variable name. Where an MCP server supports OAuth sign-in, you may not need a key at all.
The risk
Why API keys in MCP config files leak
MCP (Model Context Protocol) servers connect a coding agent such as Claude Code or Cursor to outside tools. When a server needs an API key, its config file is the tempting place to put it, and a risky one:
- Project-level config is meant to be shared. Cursor’s documentation suggests committing a project’s .cursor/mcp.json so teammates get the same tools, and Claude Code’s .mcp.json is designed for teams too.
- The agent works inside the same folder, so it can read the config file unless you block it.
- Config files end up in backups, synced folders, screenshots and screen shares.
- The MCP server receives the key whatever you do, so a key with broad permissions gives the server broad power.
Compared
Where to keep an MCP server’s API key, compared
| Option | Committed to git? | Readable by the agent? | Verdict |
|---|---|---|---|
| Key typed into project config | Often | Yes | Avoid |
| Key typed into your global user config | No | Possibly | Better, but still plain text on disk |
| Environment variable reference | No | Only through commands that read the environment | Recommended |
| OAuth sign-in, where the server supports it | No | There is no long-lived key to read | Best when available |
Claude Code
The fix in Claude Code: ${VAR} in .mcp.json
Claude Code expands ${VAR} and ${VAR:-default} in a project’s .mcp.json, in the command, args, env, url and headers fields. If a variable is not set and has no default, Claude Code warns you and leaves the text unexpanded.
{
"mcpServers": {
"payments": {
"type": "http",
"url": "https://mcp.example.com/mcp",
"headers": { "Authorization": "Bearer ${PAYMENTS_MCP_TOKEN}" }
}
}
} Cursor
The fix in Cursor: ${env:NAME} in mcp.json
Cursor resolves ${env:NAME} in the command, args, env, url and headers fields of mcp.json. Local (stdio) servers can also load an envFile; remote servers cannot.
Cursor reads environment variables from its own process. If you start it from a desktop icon, variables set only in your shell profile may be missing; restart Cursor after changing them.
{
"mcpServers": {
"payments": {
"command": "node",
"args": ["path/to/payments-mcp-server.js"],
"env": { "PAYMENTS_API_KEY": "${env:PAYMENTS_API_KEY}" }
}
}
} Clean-up
What to do if a key is already in a config file
-
Revoke it
Assume the old key is exposed. Create a new key at the provider and delete the old one.
-
Narrow the new key
Give the new key only the scopes the MCP server needs.
-
Swap in a variable
Replace the value in the config with ${VAR} (Claude Code) or ${env:NAME} (Cursor).
-
Look for copies
Check git history, other branches, backups, shared snippets and screenshots for the old value.
Argoned
Where Argoned fits
Argoned does not inject keys into MCP servers today. It helps one step earlier: when a client or colleague creates the key, they send it to you as a sealed link, an encrypted link that opens once, instead of pasting it into a chat or an email. You open it, set the environment variable, and the key never lands in a file you share.
FAQ
Questions
Is it safe to commit .mcp.json or .cursor/mcp.json?
Yes, if it contains only variable references and no keys or tokens.
Why does my ${env:NAME} variable come through empty in Cursor?
Cursor only sees variables that exist in its own process. If you launched it from a desktop icon, start it from a terminal or set the variable system-wide, then restart Cursor.
Does an environment variable hide the key from the MCP server?
No. The server needs the key to work. Environment variables keep the key out of files and chats; a narrowly scoped key limits what the server can do with it.
Can Argoned put keys into my MCP config?
Not today. A sealed link is opened in a web browser by a person. Open it, then set the environment variable yourself.
Next
Keep reading
- Give a coding agent an API key safely Keys for Claude Code, Cursor and Codex.
- Hand over API keys for n8n, Zapier or Make Collect client keys without email or chat.
- Password managers for AI agents compared Argoned, 1Password, Proton and Bitwarden.
- Is it safe to give an AI agent your password? What pasting a password really exposes.
- AI agents Five ways to hand over a login, compared.
- Pricing Free: 8 items and sealed sharing with AI agents and people, no card. Pro: £2.99 a month for 512 items and import.
- Security How Argoned encrypts each item and each shared credential in your browser, what our servers store, and what is not protected yet.
Sources
- Connect Claude Code to tools via MCP · Claude Code Docs, read 16 October 2026
- Model Context Protocol (MCP) · Cursor Docs, read 16 October 2026
- Specification: Authorization · Model Context Protocol, read 16 October 2026
Your agent needs a login. Send it sealed.
Seal a login or API key in your browser and send a link instead of the password.
£0 · Free plan, no card needed · Encrypted in your browser