{"id":50928196,"url":"https://github.com/astrogilda/mcp-keyring-injector","last_synced_at":"2026-06-17T01:05:13.865Z","repository":{"id":332327768,"uuid":"1111408940","full_name":"astrogilda/mcp-keyring-injector","owner":"astrogilda","description":"Session-scoped MCP credential security - keys auto-injected at startup, auto-removed at exit, zero config file exposure","archived":false,"fork":false,"pushed_at":"2025-12-07T16:18:20.000Z","size":15,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-01-13T13:51:24.492Z","etag":null,"topics":["api-keys","authentication","claude-code","credentials","keyring","mcp","python","security"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/astrogilda.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"docs/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-06T21:57:31.000Z","updated_at":"2025-12-30T12:27:04.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/astrogilda/mcp-keyring-injector","commit_stats":null,"previous_names":["astrogilda/mcp-keyring-injector"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/astrogilda/mcp-keyring-injector","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/astrogilda%2Fmcp-keyring-injector","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/astrogilda%2Fmcp-keyring-injector/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/astrogilda%2Fmcp-keyring-injector/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/astrogilda%2Fmcp-keyring-injector/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/astrogilda","download_url":"https://codeload.github.com/astrogilda/mcp-keyring-injector/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/astrogilda%2Fmcp-keyring-injector/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34429522,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-16T02:00:06.860Z","response_time":126,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-keys","authentication","claude-code","credentials","keyring","mcp","python","security"],"created_at":"2026-06-17T01:05:13.114Z","updated_at":"2026-06-17T01:05:13.856Z","avatar_url":"https://github.com/astrogilda.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"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","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fastrogilda%2Fmcp-keyring-injector","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fastrogilda%2Fmcp-keyring-injector","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fastrogilda%2Fmcp-keyring-injector/lists"}