{"id":"a53c098e-b221-46ce-8658-ad31cf244f16","slug":"mcp-keyring-injector","kind":"mcp","name":"mcp-keyring-injector","summary":"Session-scoped MCP credential security - keys auto-injected at startup, auto-removed at exit, zero config file exposure","owner":"astrogilda","repoUrl":"https://github.com/astrogilda/mcp-keyring-injector","license":"MIT","licenseTier":"permissive","trust":"community","stars":5,"match":null,"fewStars":false,"format":"mcp","createdAt":"2025-12-06T21:57:31.000Z","addedAt":"2026-10-21T08:10:56.391Z","logoUrl":"https://avatars.githubusercontent.com/u/23521054?u=d44ac34d61b6760f0dcc76f24115f188e37a18e2&v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["developer-tools","files-documents"],"tags":["api-keys","authentication","claude-code","credentials","keyring","python","security"],"runtime":"binary","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-21T08:11:11.956Z","sample":false,"url":"https://conduits.dev/tools/mcp-keyring-injector","language":"Python","transports":["stdio"],"install":{},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"# MCP Keyring Injector\n\nSession-scoped credential management for Claude Code MCP servers. API keys are automatically injected from your OS keyring at startup and removed at exit - credentials exist in config files only while Claude Code runs.\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)\n\n## The Problem\n\nMCP servers in Claude Code require API keys in their environment configuration (`~/.claude.json`). Storing API keys in config files is a security risk:\n- Keys are in plaintext on disk\n- Easy to accidentally commit to git\n- Shared across all projects\n- Hard to rotate without editing configs\n\n## The Solution\n\nThis plugin solves the problem by:\n1. Storing API keys in your **system keyring** (encrypted)\n2. **Dynamically injecting** them into `~/.claude.json` when Claude Code starts (SessionStart hook)\n3. **Automatically removing** them when the session ends (SessionEnd hook)\n4. Working **cross-platform** (Linux, macOS, Windows)\n\nKeys exist in config files **only while Claude Code is running** - true session-scoped security!\n\n## Features\n\n- **Secure**: Keys stored encrypted in system keyring\n- **Cross-platform**: Works on Linux (GNOME Keyring), macOS (Keychain), Windows (Credential Manager)\n- **Automatic**: Runs on every Claude Code session start\n- **Flexible**: Configure multiple MCP services from one file\n- **Minimal overhead**: Negligible performance impact on session startup\n\n## Installation\n\n### 1. Install the plugin\n\n```bash\n# Via Claude Code plugin system\n/plugin marketplace add astrogilda/claude-plugins\n/plugin install mcp-keyring-injector\n\n# Or manually\ngit clone https://github.com/astrogilda/mcp-keyring-injector.git ~/Documents/mcp-keyring-injector\n```\n\n### 2. Install Python dependencies\n\n```bash\nuv pip install keyring\n```\n\n### 3. Store your first API key\n\nChoose your platform:\n\n**Linux (GNOME Keyring):**\n```bash\npython3 -c \"import keyring; keyring.set_password('github', 'api-key', 'YOUR_API_KEY')\"\n```\n\n**macOS (Keychain):**\n```bash\nsecurity add-generic-password -s github -a api-key -w YOUR_API_KEY\n```\n\n**Windows (PowerShell):**\n```powershell\ncmdkey /generic:github /user:api-key /pass:YOUR_API_KEY\n```\n\n### 4. Configure MCP credentials\n\nCreate `~/.claude/config/mcp-credentials.json`:\n\n```json\n{\n  \"github\": {\n    \"env_var\": \"GITHUB_TOKEN\",\n    \"service\": \"github\",\n    \"account\": \"api-key\",\n    \"label\": \"GitHub API Token\",\n    \"mcp_server\": \"github-mcp\"\n  }\n}\n```\n\nSee `examples/mcp-credentials.json` for more examples.\n\n### 5. Verify it works\n\nRestart Claude Code. You should see:\n```\nMCP credentials - Injected: GitHub API Token\n```\n\nCheck your GitHub MCP tools are now available!\n\n## Upgrading from v1.0.0\n\nIf you're upgrading from v1.0.0, here's what changed in v1.1.0:\n\n### What's New\n- **SessionEnd cleanup hook**: Credentials are now automatically removed when Claude Code exits\n- **Session-scoped security**: Keys only exist in `~/.claude.json` while Claude is running\n- **Enhanced status messages**: Better feedback on cleanup operations\n\n### Migration Steps\n\n1. **Update the plugin** (automatic if using plugin marketplace):\n   ```bash\n   /plugin update mcp-keyring-injector\n   ```\n\n2. **One-time cleanup** - Remove old credentials from config (they won't auto-cleanup):\n   ```bash\n   # Backup first\n   cp ~/.claude.json ~/.claude.json.backup\n\n   # Remove credentials manually from ~/.claude.json env sections\n   # Or let them be removed on next session start\n   ```\n\n3. **No config changes needed** - Your `mcp-credentials.json` format remains the same\n\n### Breaking Changes\n- **None!** This is a fully backwards-compatible security enhancement\n\n### What Happens After Upgrade\n- Next session: Credentials injected at start (as before)\n- **New behavior**: Credentials automatically removed at session end\n- Keys always remain safe in your system keyring\n\n## Configuration\n\n### Config File Format\n\n`~/.claude/config/mcp-credentials.json`:\n\n```json\n{\n  \"service-name\": {\n    \"env_var\": \"ENVIRONMENT_VARIABLE_NAME\",\n    \"service\": \"keyring-service-name\",\n    \"account\": \"keyring-account-name\",\n    \"label\": \"Human Readable Label\",\n    \"mcp_server\": \"mcp-server-name-in-claude.json\"\n  }\n}\n```\n\n**Fields:**\n- `env_var`: Environment variable the MCP server expects (e.g., `GITHUB_TOKEN`)\n- `service`: Keyring service name (how you stored the key)\n- `account`: Keyring account/username (how you stored the key)\n- `label`: Display name in status messages\n- `mcp_server`: MCP server name from `~/.claude.json` (defaults to service-name if omitted)\n\n### Adding Multiple Services\n\n```json\n{\n  \"github\": {\n    \"env_var\": \"GITHUB_TOKEN\",\n    \"service\": \"github\",\n    \"account\": \"api-key\",\n    \"label\": \"GitHub API Token\",\n    \"mcp_server\": \"github-mcp\"\n  },\n  \"openai\": {\n    \"env_var\": \"OPENAI_API_KEY\",\n    \"service\": \"openai\",\n    \"account\": \"api-key\",\n    \"label\": \"OpenAI API Key\",\n    \"mcp_server\": \"openai-mcp\"\n  }\n}\n```\n\n## How It Works\n\n```\nClaude Code Session Start\n         |\nSessionStart hook triggered\n         |\nRead ~/.claude/config/mcp-credentials.json\n         |\nFor each service:\n  |-- Retrieve API key from system keyring\n  |-- Inject into ~/.claude.json MCP server env\n  +-- Report success/failure\n         |\nClaude Code continues startup\n         |\nMCP servers start with injected credentials\n         |\n[... Claude Code session runs ...]\n         |\nClaude Code Session End\n         |\nSessionEnd hook triggered\n         |\nRead ~/.claude/config/mcp-credentials.json\n         |\nFor each service:\n  |-- Remove API key from ~/.claude.json MCP server env\n  +-- Report cleanup status\n         |\nKeys removed from config\n         |\nKeys remain only in system keyring\n```\n\n## Security Considerations\n\n### What This Protects Against\n- [YES] API keys in plaintext config files\n- [YES] Accidental git commits of secrets\n- [YES] Unauthorized file access (keyring requires user authentication)\n- [YES] **Session-scoped security (v1.1.0+)**: Keys automatically removed when Claude Code exits\n\n### What This Doesn't Protect Against\n- [NO] Malicious code with your user permissions (can access keyring)\n- [NO] Physical access to unlocked machine\n- [NO] Memory dumps while Claude Code is running\n\n### Best Practices\n1. Use unique API keys per machine\n2. Rotate keys regularly\n3. Use least-privilege API keys (read-only when possible)\n4. Don't share `~/.claude/config/mcp-credentials.json` (it's not secret, but lists your services)\n\n## Troubleshooting\n\n### \"MCP credentials - Failed: X (not in keyring)\"\n\nThe key isn't stored in your system keyring.\n\n**Solution:**\n```bash\npython3 -c \"import keyring; keyring.set_password('service', 'account', 'YOUR_KEY')\"\n```\n\n### \"MCP credentials - Failed: X (MCP server 'Y' not found)\"\n\nThe MCP server name doesn't match what's in `~/.claude.json`.\n\n**Solution:** Check your MCP server name:\n```bash\njq '.mcpServers | keys' ~/.claude.json\n```\n\nUpdate `mcp_server` field in config to match.\n\n### \"ERROR: keyring library not installed\"\n\nPython keyring library is missing.\n\n**Solution:**\n```bash\nuv pip install keyring\n```\n\n### Hook runs but tools still unavailable\n\nCheck MCP server logs:\n```bash\nls ~/.cache/claude-cli-nodejs/*/mcp-logs-*/\ncat ~/.cache/claude-cli-nodejs/*/mcp-logs-github-mcp/*.txt\n```\n\nLook for errors about missing API keys.\n\n## Development\n\n### Project Structure\n```\nmcp-keyring-injector/\n.claude-plugin/\n  +-- plugin.json             # Plugin metadata\nhooks/\n  +-- hooks.json              # Hook configuration\n  +-- inject-credentials.py  # SessionStart hook\n  +-- remove-credentials.py  # SessionEnd hook (v1.1.0+)\nexamples/\n  +-- mcp-credentials.json    # Example config\ndocs/\n  +-- SECURITY.md             # Security considerations\nCHANGELOG.md                # Version history\nREADME.md\nLICENSE\n```\n\n### Testing Locally\n\n```bash\n# Test the hook directly\necho '{}' | ~/Documents/claude-mcp-credentials/hooks/inject-credentials.py\n\n# Check if keys were injected\njq '.mcpServers.\"github-mcp\".env' ~/.claude.json\n```\n\n### Contributing\n\nContributions welcome! Please:\n1. Fork the repo\n2. Create a feature branch\n3. Add tests for new functionality\n4. Ensure code passes black + ruff\n5. Submit PR with clear description\n\n## License\n\nMIT License - see LICENSE file for details.\n\n## Credits\n\nCreated by [@astrogilda](https://github.com/astrogilda)\n\nUses the excellent [keyring](https://github.com/jaraco/keyring) library by Jason R. Coombs.\n\n## Links\n\n- [Claude Code Documentation](https://docs.anthropic.com/en/docs/claude-code)\n- [MCP Protocol](https://modelcontextprotocol.io/)\n- [Python Keyring Library](https://github.com/jaraco/keyring)\n"}