{
  "markdown": "# openrouter-admin-mcp\n\n[![npm version](https://img.shields.io/npm/v/openrouter-admin-mcp?color=cb3837&logo=npm&label=npm)](https://www.npmjs.com/package/openrouter-admin-mcp)\n[![npm downloads](https://img.shields.io/npm/dw/openrouter-admin-mcp?color=cb3837&logo=npm&label=downloads)](https://www.npmjs.com/package/openrouter-admin-mcp)\n[![CI](https://img.shields.io/github/actions/workflow/status/oviron/openrouter-admin-mcp/test.yml?branch=main&logo=github&label=ci)](https://github.com/oviron/openrouter-admin-mcp/actions/workflows/test.yml)\n[![MCP Registry](https://img.shields.io/badge/MCP_Registry-listed-7C3AED?logo=anthropic)](https://registry.modelcontextprotocol.io/v0/servers/io.github.oviron%2Fopenrouter-admin/versions)\n[![Node](https://img.shields.io/node/v/openrouter-admin-mcp?logo=node.js)](https://nodejs.org)\n[![License: MIT](https://img.shields.io/badge/license-MIT-blue)](LICENSE)\n\nMCP server for the **OpenRouter management API** — programmatic control of credits, inference keys, guardrails, organization members, and usage analytics from inside Claude Code, Claude Desktop, Cursor, or any MCP-compatible client.\n\n![demo](assets/hero.png)\n\n> Read-only by default. Destructive write operations are gated behind an opt-in env flag.\n\nThis is **not** an inference proxy. It uses an OpenRouter [Provisioning API key](https://openrouter.ai/settings/provisioning), which can manage your account but cannot make completion calls.\n\n## Why\n\nOpenRouter's UI is solid for one-off tweaks, but checking spend across keys, drilling into per-model/per-day usage, configuring account-wide guardrails, or rotating limits requires a lot of clicking. This server exposes those operations as MCP tools — Claude can answer \"what burned my credits this week?\", \"create a temporary key with a $0.30 daily cap\", or \"bind the new prod key to our daily-$50 guardrail\" in a single turn.\n\n## Features\n\n26 tools wrapping the OpenRouter management API:\n\n- **`or_overview`** — one-shot dashboard: credits + active keys (with reset/expiration) + today's UTC burn by model.\n- **Inference key CRUD** including `limit_reset` (daily/weekly/monthly) and `expires_at`.\n- **Guardrails CRUD** — account-wide spending limits with provider/model allowlists, ZDR enforcement. Bulk-assign to keys or org members.\n- **Activity drill-down** — aggregate `by_model`, `by_day`, `by_provider`, or `by_key`. Token-level breakdown (prompt / completion / reasoning) per row.\n- **Generation lookup** — fetch any single inference call by `gen-…` id (cost, tokens, latency, finish reason).\n- **Model & endpoint discovery** — current pricing per 1M tokens, per-provider uptime, ZDR-compliant endpoints.\n\nPlumbing: HTTP retry on 429/5xx with `Retry-After` support, in-session GET cache, write invalidation. Returns raw fields — interpretation is left to the agent.\n\n## Install\n\n### One-click\n\n[![Install in VS Code](https://img.shields.io/badge/Install-VS_Code-007ACC?logo=visualstudiocode)](https://insiders.vscode.dev/redirect/mcp/install?name=openrouter-admin&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22openrouter-admin-mcp%22%5D%2C%22env%22%3A%7B%22OPENROUTER_PROVISIONING_KEY%22%3A%22sk-or-v1-...%22%7D%7D)\n[![Install in Cursor](https://img.shields.io/badge/Install-Cursor-000000?logo=data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMTIuOTk5MyAyTDIxIDdWMTdMMTIuOTk5MyAyMkwxMyAxNi41TDE3IDE0LjI1VjkuNzVMMTMgN1YyWiIgZmlsbD0id2hpdGUiLz48L3N2Zz4=)](https://cursor.com/install-mcp?name=openrouter-admin&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIm9wZW5yb3V0ZXItYWRtaW4tbWNwIl0sImVudiI6eyJPUEVOUk9VVEVSX1BST1ZJU0lPTklOR19LRVkiOiJzay1vci12MS0uLi4ifX0=)\n\n> Replace the placeholder `sk-or-v1-...` with your real key after install.\n\n### Manual\n\nRun via `npx` (no install needed) or install globally:\n\n```bash\nnpx -y openrouter-admin-mcp\n# or\nnpm install -g openrouter-admin-mcp\n```\n\n## Configuration\n\nCreate a Provisioning key at <https://openrouter.ai/settings/provisioning>, then add the server to your MCP client config.\n\n**Claude Code** (`~/.claude.json`) or **Claude Desktop** (`claude_desktop_config.json`):\n\n```json\n{\n  \"mcpServers\": {\n    \"openrouter-admin\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"openrouter-admin-mcp\"],\n      \"env\": {\n        \"OPENROUTER_PROVISIONING_KEY\": \"sk-or-v1-...\"\n      }\n    }\n  }\n}\n```\n\nRestart your client to load the server. By default this gives **read-only** access — to enable key creation, mutation, and deletion, see [Enabling write tools](#enabling-write-tools) below.\n\n### Enabling write tools\n\nDestructive operations (`or_key_create`, `or_key_update`, `or_key_delete`) are **disabled by default** to prevent accidental key mutation through prompt-injected tool calls. Add `OPENROUTER_ADMIN_ALLOW_WRITE` to your env block to enable them:\n\n```json\n\"env\": {\n  \"OPENROUTER_PROVISIONING_KEY\": \"sk-or-v1-...\",\n  \"OPENROUTER_ADMIN_ALLOW_WRITE\": \"1\"\n}\n```\n\nThe server logs which mode it started in:\n\n```\nopenrouter-admin-mcp running on stdio (write tools: ENABLED)\n```\n\nRead tools (`or_overview`, `or_credits`, `or_current_key`, `or_keys_list`, `or_key_get`, `or_activity`) are always available regardless of this flag.\n\n## Tools\n\n### Read (always available)\n\n| Tool | Purpose |\n|---|---|\n| `or_overview` | One-shot dashboard: credits + active keys + today's burn by model. |\n| `or_credits` | Account balance: total purchased, total used, remaining. |\n| `or_current_key` | Metadata of the Provisioning key the server is using. |\n| `or_keys_list` | All inference keys with usage, limits, reset cadence, expiration. |\n| `or_key_get` | Detailed view of one key by hash. |\n| `or_activity` | Usage for the last 30 UTC days. Filters: `date`, `api_key_hash`, `user_id`. Aggregations: `none`, `by_model`, `by_day`, `by_provider`, `by_key`. |\n| `or_generation` | Fetch a single inference call by its `gen-…` id (cost, tokens, latency, finish reason). |\n| `or_models` | Model catalog with per-1M pricing, context length, modalities. Filterable. |\n| `or_model_get` | Full details for one model id. |\n| `or_model_endpoints` | Per-provider endpoints for a model: pricing, uptime, status. |\n| `or_models_user` | Models filtered by your account's privacy/guardrail settings. |\n| `or_zdr_endpoints` | ZDR-compliant endpoints for privacy-constrained workflows. |\n| `or_guardrails_list` | All guardrails: limit_usd, reset, allow/block lists, ZDR. |\n| `or_guardrail_get` | Full details for one guardrail. |\n| `or_guardrails_assignments` | Composite — which keys/members are bound to which guardrail. |\n| `or_org_members` | Members of the OpenRouter organization (Management-key + org account). |\n\n### Write (opt-in via `OPENROUTER_ADMIN_ALLOW_WRITE=1`)\n\n| Tool | Purpose |\n|---|---|\n| `or_key_create` | Create a new inference key. Returns the one-time secret. |\n| `or_key_update` | Update name / disabled / limit / `limit_reset` / `expires_at`. |\n| `or_key_delete` | Permanently delete a key. |\n| `or_guardrail_create` | Create a guardrail. |\n| `or_guardrail_update` | Update a guardrail. |\n| `or_guardrail_delete` | Delete a guardrail. |\n| `or_guardrail_assign_keys` / `_unassign_keys` | Bulk-(un)assign a guardrail to inference keys. |\n| `or_guardrail_assign_members` / `_unassign_members` | Bulk-(un)assign a guardrail to org members. |\n\n### Example — create a daily-capped temporary key\n\n```\n> Create a key called \"scratch\" with a $0.50 daily limit that expires in 30 days.\n\n[Claude calls or_key_create with:\n  name=\"scratch\",\n  limit=0.50,\n  limit_reset=\"daily\",\n  expires_at=\"2026-05-25T00:00:00Z\"]\n\nCreated key **scratch**\nHash: f7a3...\nLimit: $0.5 (resets daily)\nExpires: 2026-05-25T00:00:00Z\n\nSecret: `sk-or-v1-...`\n⚠️ This secret cannot be retrieved later — store it now.\n```\n\n### Example — diagnose a cost spike\n\n```\n> Why did my OpenRouter spend jump yesterday?\n\n[Claude calls or_activity with date=\"2026-04-24\", aggregate=\"by_model\"]\n\nActivity: 47 rows | total $0.8570 | 305 req\nBy model (top 5):\n- xiaomi/mimo-v2-flash      $0.5240 | 178 req | 24 rows\n- anthropic/claude-haiku-4.5 $0.2105 | 39 req  | 5 rows\n- ...\n```\n\n### Example — bind a key to an account-wide guardrail\n\n```\n> Cap our prod-bot key at the daily-$50 guardrail.\n\n[Claude calls or_guardrails_list, finds gr_prod_daily_50,\n then or_guardrail_assign_keys with id=\"gr_prod_daily_50\", hashes=[\"…\"]]\n\nAssigned guardrail `gr_prod_daily_50` to 1 key(s).\n```\n\n## Design\n\nThe server returns raw API fields. It does **not** flag what's \"near limit\", what's an \"anomaly\", or what the agent should do — that's the agent's job. Composite tools (`or_overview`, `or_guardrails_assignments`) merge multiple endpoints into one workflow response, but they don't interpret. Rationale: production MCP servers (Stripe, GitHub, Linear) follow the same pattern.\n\n## Data handling\n\n- The Provisioning key is read from the `OPENROUTER_PROVISIONING_KEY` environment variable and forwarded only to `https://openrouter.ai/api/v1/*` over HTTPS.\n- The server is stateless across restarts. An in-session GET cache (60s TTL on `/credits`, `/key`, `/keys`, `/keys/{hash}`) is held in memory only and dropped on shutdown.\n- The key never appears in error messages or tool output (verified by tests).\n\n## Development\n\n```bash\ngit clone https://github.com/oviron/openrouter-admin-mcp.git\ncd openrouter-admin-mcp\nnpm install\nnpm run build      # compile TypeScript + chmod +x build/index.js\nnpm test           # vitest, 84 unit tests, mocked fetch\n```\n\nProject layout:\n\n```\nsrc/\n  client.ts            # OpenRouterClient — fetch wrapper, retry, in-session cache\n  index.ts             # MCP server entry — registers tool groups\n  tools/\n    credits.ts         # or_credits, or_current_key\n    keys.ts            # or_keys_list, _get, _create, _update, _delete\n    activity.ts        # or_activity (5 modes incl. by_key)\n    overview.ts        # or_overview composite\n    generation.ts      # or_generation\n    models.ts          # or_models, _model_get, _model_endpoints, _models_user, _zdr_endpoints\n    guardrails.ts      # or_guardrails_list/_get/CRUD/bulk-assign + composite assignments\n    organization.ts    # or_org_members\ntest/\n  client.test.ts, credits.test.ts, keys.test.ts,\n  activity.test.ts, overview.test.ts, generation.test.ts,\n  models.test.ts, guardrails.test.ts, organization.test.ts,\n  registration.test.ts, helpers.ts, smoke.test.ts\n```\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n",
  "bytes": 10479,
  "sha": "da7398b7688ad3f3709ae042157382b700cc5ffef87279ece2e452ae4480acf6",
  "repo_slug": "oviron/openrouter-admin-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_oviron_openrouter_admin_97edcc39/readme"
}