MCP server configs often need secrets (API tokens, passwords). Since .mcp.json is version-controlled, secrets go in environment variables referenced via ${ENV_VAR} syntax. The config file is safe to commit; each developer sets their own token locally.
The pattern
{
"mcpServers": {
"github": {
"command": "github-mcp-server",
"env": {
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
}
}
}
}
At runtime, ${GITHUB_TOKEN} resolves to the developer’s local environment variable. The actual token never appears in the repository.
What NOT to do
Hardcode the secret: "GITHUB_TOKEN": "ghp_abc123..." in .mcp.json exposes the token to everyone with repo access and to git history forever.
Add .mcp.json to .gitignore: this prevents sharing the MCP configuration with the team — the whole point of project-level config. You’d need manual setup for every developer.
Base64 encode: "GITHUB_TOKEN": "Z2hwX2FiYzEyMy4uLg==" provides zero security. Anyone can decode base64 instantly. It’s obfuscation, not encryption.
Separate secrets file with import: there is no import directive in .mcp.json. The ${ENV_VAR} syntax is the built-in mechanism for separating secrets from configuration.
Per-developer tokens
Each developer sets GITHUB_TOKEN in their local environment (shell profile, .env file, IDE settings). The same .mcp.json works for everyone — the config is shared, the secrets are personal.
One-liner: Use ${ENV_VAR} syntax in .mcp.json to reference environment variables — the config file stays in version control, secrets stay in each developer’s local environment.