{
  "markdown": "# NIM Key Manager\n<img width=\"1200\" height=\"630\" alt=\"NIM-KE~1\" src=\"https://github.com/user-attachments/assets/1dc02b55-1a6d-41ff-a76b-14abb53a853d\" />\n\n**Self-hosted, production-ready manager for the API keys of _your own_ NVIDIA Build/NIM account** — encrypted storage, assisted rotation, expiry detection, usage stats, projects, RBAC, audit, a web dashboard, and a **Claude MCP connector**. Deploy your own instance in a few minutes; everything is configured through environment variables.\n\n[![CI](https://github.com/BySergiMM/nim-key-manager/actions/workflows/ci.yml/badge.svg)](https://github.com/BySergiMM/nim-key-manager/actions/workflows/ci.yml)\n[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n[![Python 3.12](https://img.shields.io/badge/python-3.12-blue.svg)](https://www.python.org/)\n[![Coverage](https://img.shields.io/badge/coverage-94%25-brightgreen.svg)](#development--tests)\n\n> **NVIDIA Terms of Service.** NVIDIA Build offers **no public API** to create or rotate keys programmatically (you generate them at [build.nvidia.com](https://build.nvidia.com/settings/api-keys)), and API keys **must not be shared or redistributed** to third parties. This project is therefore designed for **you to manage your _own_ keys on your _own_ instance**: the only outbound call is the official read-only **validation** endpoint `GET https://integrate.api.nvidia.com/v1/models`. It does not automate or scrape the NVIDIA portal, and it is **not** a service for handing your keys to other people.\n\n## Deploy your own (no local setup)\n\n[![Deploy to Render](https://render.com/images/deploy-to-render-button.svg)](https://render.com/deploy?repo=https://github.com/BySergiMM/nim-key-manager)\n\n1. Click the button (or **Use this template → Create repository**, then in [Render](https://render.com) pick **New → Blueprint** and select your fork). Render reads [`render.yaml`](render.yaml) and provisions **everything automatically**:\n   - a managed PostgreSQL database,\n   - the Dockerized web service with a health check,\n   - the secrets `JWT_SECRET`, `ENCRYPTION_MASTER_KEY` and `MCP_OAUTH_JWT_SIGNING_KEY` (generated and stored by Render's secret manager),\n   - `DATABASE_URL` injected from the database.\n2. When prompted, set `FIRST_ADMIN_EMAIL` and `FIRST_ADMIN_PASSWORD` (your initial admin, created on first boot).\n3. Open the service URL: log in at `/`, explore the API at `/docs`.\n4. Every push to `main` runs CI (lint + types + tests + build) and redeploys automatically. Migrations (`alembic upgrade head`) run on container start.\n\nPrefer another host? Any platform that runs a Docker container + PostgreSQL works — see [`docs/deployment.md`](docs/deployment.md).\n\n## Use it from Claude (MCP connector)\n\nThe same deployment exposes a **Model Context Protocol server** at `‹BASE›/mcp` so you can add it to **Claude as a custom connector**. Claude authenticates with **OAuth 2.1** (GitHub by default, Google optional) and can list/inspect keys, **dispense** a ready-to-use key, register/rotate/revoke and manage projects — with the same RBAC and audit trail as the REST API. Only identities in `MCP_ALLOWED_IDENTITIES` may connect (fail-closed).\n\n1. Create a GitHub **OAuth App** with callback `‹BASE›/auth/callback`; copy the Client ID/Secret.\n2. In Render set `MCP_GITHUB_CLIENT_ID`, `MCP_GITHUB_CLIENT_SECRET` and `MCP_ALLOWED_IDENTITIES` (your GitHub login/e-mail). The rest is already in `render.yaml`.\n3. In Claude: **Settings → Connectors → Add custom connector** → URL `‹BASE›/mcp` → **Connect**.\n\nFull guide (Google, tool reference, security, troubleshooting): [`docs/connector.md`](docs/connector.md).\n\n## Features\n\n- **Secure key registration** — encrypted at rest with AES-256-GCM (key derived via HKDF-SHA256 from the platform secret manager). Never stored or logged in plaintext.\n- **Assisted, audited rotation** — you create the new key in your NVIDIA account, paste it, and the system performs an atomic swap (new key active, old one revoked with a `rotated_from_id` lineage link).\n- **Expiry detection** — hourly background job + maintenance endpoint; configurable `expiring_soon` flag.\n- **Periodic validation** — automatic sweep against NVIDIA every 6 h (configurable) that flags invalid/revoked keys.\n- **Key dispensing** — `GET /api/v1/keys/dispense` returns the least-recently-used active key (LRU), globally or per project, recording usage.\n- **Projects** — group keys by consumer/workload.\n- **Statistics** — inventory by status, dispenses, usage time series.\n- **Security** — JWT (access + refresh), roles `admin`/`manager`/`viewer`, rate limiting, immutable audit of every sensitive operation.\n- **Claude connector (MCP)** — OAuth-secured MCP server at `/mcp` (see above).\n- **Operations** — structured JSON logging, Prometheus metrics at `/metrics`, health check at `/health`, OpenAPI at `/docs`.\n\n## Architecture\n\n```\napp/\n├── domain/           # Enums and domain exceptions (no dependencies)\n├── application/      # Use cases (services) and ports (interfaces)\n│   └── services/     # auth, users, keys, projects, stats, audit\n├── infrastructure/   # Adapters: SQLAlchemy (repositories) and NVIDIA gateway\n├── api/              # FastAPI: routers, schemas, deps, rate limiting\n├── mcp/              # Claude connector: MCP server, OAuth and identity mapping\n├── dashboard/        # Lightweight SPA served at /\n├── tasks/            # Scheduled jobs (APScheduler)\n└── core/             # Config, crypto, security, logging\n```\n\nPragmatic Clean Architecture: dependencies point inward; the application layer knows nothing about FastAPI and reaches NVIDIA through the `KeyValidator` port. Details and decisions in [`docs/architecture.md`](docs/architecture.md).\n\n**Stack**: Python 3.12 · FastAPI · FastMCP (Claude connector) · SQLAlchemy 2 (async) · managed PostgreSQL · Alembic · Docker · GitHub Actions · Render (Blueprint) · structlog · Prometheus · slowapi · APScheduler.\n\n## API quickstart\n\n```bash\nBASE=https://your-service.onrender.com\n\n# Log in (the admin was created on first boot)\nTOKEN=$(curl -s $BASE/api/v1/auth/login -H 'Content-Type: application/json' \\\n  -d '{\"email\":\"you@example.com\",\"password\":\"your-password\"}' | jq -r .access_token)\n\n# Register a key created at build.nvidia.com (validating it against NVIDIA)\ncurl -s $BASE/api/v1/keys -H \"Authorization: Bearer $TOKEN\" -H 'Content-Type: application/json' \\\n  -d '{\"name\":\"prod-1\",\"api_key\":\"nvapi-...\",\"validate_remote\":true}'\n\n# Get an available key (LRU) to use in your application\ncurl -s \"$BASE/api/v1/keys/dispense\" -H \"Authorization: Bearer $TOKEN\"\n```\n\nMore examples (rotation, projects, stats, audit) in [`docs/api-examples.md`](docs/api-examples.md). Interactive OpenAPI at `/docs`.\n\n## Roles\n\n| Operation | viewer | manager | admin |\n|---|---|---|---|\n| View keys, projects and stats | ✅ | ✅ | ✅ |\n| Register / validate / rotate / revoke / dispense keys | ❌ | ✅ | ✅ |\n| Manage projects | ❌ | ✅ | ✅ |\n| Delete keys, manage users, read the audit log | ❌ | ❌ | ✅ |\n\n## Development & tests\n\nNot required to deploy, but fully supported:\n\n```bash\npip install -e \".[dev]\"\npytest --cov=app          # required coverage gate: 85% (currently ~94%)\nruff check . && mypy app\ndocker compose up         # local stack with PostgreSQL\n```\n\n## Security\n\nThreat model, cryptographic details and design decisions in [`docs/security.md`](docs/security.md). Key points: AES-256-GCM encryption with a key derived (HKDF) from the secret manager, SHA-256 fingerprints to deduplicate without exposing the secret, short-lived signed JWTs, argon2 password hashing, per-IP rate limiting, audit of every sensitive operation, and no plaintext keys in logs or responses except the explicit dispense endpoint. To report a vulnerability, see [`SECURITY.md`](SECURITY.md).\n\n## Contributing\n\nContributions are welcome — see [`CONTRIBUTING.md`](CONTRIBUTING.md) and the [Code of Conduct](CODE_OF_CONDUCT.md). A short Spanish overview is available in [`README.es.md`](README.es.md).\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n",
  "bytes": 8032,
  "sha": "3d1065d23e7f8ce0f3cfe8fe811293ca7525253b91c1e75e4d8a3827f351ffcc",
  "repo_slug": "bysergimm/nim-key-manager",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_bysergimm_nim_key_manager_edaaa566/readme"
}