{
  "markdown": "# Gvnr\n\n[![Tests](https://github.com/mightbesaad/gvnr/actions/workflows/test.yml/badge.svg)](https://github.com/mightbesaad/gvnr/actions/workflows/test.yml)\n[![Release](https://img.shields.io/github/v/tag/mightbesaad/gvnr?label=release&color=blue)](https://github.com/mightbesaad/gvnr/releases)\n[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)\n[![MCP Registry](https://img.shields.io/badge/MCP%20Registry-dev.gvnr%2Fgvnr-purple)](https://registry.modelcontextprotocol.io/v0.1/servers?search=dev.gvnr/gvnr)\n[![gvnr MCP server](https://glama.ai/mcp/servers/mightbesaad/gvnr/badges/score.svg)](https://glama.ai/mcp/servers/mightbesaad/gvnr)\n[![smithery badge](https://smithery.ai/badge/mightbesaad/gvnr)](https://smithery.ai/servers/mightbesaad/gvnr)\n\nSpend caps, rate coordination, idempotency, and a human-in-the-loop gate for AI agents — **enforced before the call, not after the invoice.** One MCP endpoint, settled via x402 (USDC on Base). No proxy, no self-hosting, no infrastructure to deploy.\n\nListed on the Official MCP Registry as [`dev.gvnr/gvnr`](https://registry.modelcontextprotocol.io/v0.1/servers?search=dev.gvnr/gvnr).\n\n---\n\n## The problem\n\nAgents cost 10–12× more than estimated in production. System prompts, retry loops, and tool calls multiply fast — a runaway agent can generate a $47,000 bill in 11 days. The usual fix, self-hosting a gateway like LiteLLM, means running infrastructure most developers won't set up.\n\nGvnr is the hosted alternative: an external authority your agent checks **before** it spends. Your agent asks \"am I clear to make this call?\" and acts on the answer.\n\n---\n\n## How it works\n\nGvnr is **not** an LLM proxy — your tokens never pass through it, and you pay your model provider directly. Gvnr governs the *decision to spend*, in two independent meters:\n\n**1. The governance-operation quota** — what you buy from Gvnr.\nYour account holds a balance of **governance operations** (`operations_remaining`). One `budget_clear` burns one op. You top this up with USDC; it's decoupled from your LLM spend. `get_balance` reports it.\n\n**2. The spend envelope** — a USD cap *you* set, per agent.\n`set_envelope(agent_id, limit_usd, window)` gives an agent a daily or per-session USD ceiling. Gvnr tracks estimated spend against it and denies once it's exceeded — this is the runaway guardrail. No dollars move; it's an accounting limit you control.\n\nA `budget_clear` is approved only when **both** hold: the account has ops left in the quota, and the agent is under its envelope. The loop:\n\n1. Your agent calls `budget_clear(agent_id, model, estimated_tokens)` before each LLM request.\n2. Gvnr checks the op quota and the agent's envelope, and returns `{ approved: true, ... }` or `{ approved: false, reason }`.\n3. If denied, your agent skips (or escalates via `request_approval`).\n4. After the LLM responds, call `reconcile(...)` with the real token counts so the envelope tracks actual cost, not the estimate.\n\n---\n\n## Quick start\n\n### 1. Provision an account\n\n```bash\ncurl -X POST https://gvnr.dev/v1/account\n# { \"api_key\": \"bg_...\", \"account_id\": \"...\", \"operations_remaining\": 25 }\n```\n\nNew accounts include **25 free trial ops** — enough to run the full loop (set an envelope, `budget_clear`, `reconcile`) before you fund anything. Your `api_key` is the credential for every call; `account_id` is just an internal reference for support. Account creation is credential-only by design (agent-native) — **email is optional**, set separately via `POST /v1/account/notification-email`, and used only for human approval notices.\n\n### 2. Top up your governance-op quota\n\nPay-as-you-go: **1,000 ops per $1**, any amount (try the whole rail for **$1**), USDC on Base. Open the pay page, name your amount, and pass your API key:\n\n```\nhttps://gvnr.dev/pay?usd=1&api_key=bg_YOUR_KEY\n```\n\nSend USDC to the address shown and paste your tx hash — ops are credited proportional to the amount received, after on-chain verification. Programmatic clients can submit the hash directly:\n\n```bash\ncurl -X POST \\\n  -H \"Authorization: Bearer bg_YOUR_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"tx_hash\":\"0x...\"}' \\\n  https://gvnr.dev/v1/account/topup-verify\n# { \"operations_remaining\": 1000, \"credited_ops\": 1000, \"credited_usd\": 1 }\n```\n\nOr settle in one round-trip with an x402 client (Base MCP, AgentKit, x402-fetch) — name your own amount:\n\n```\nPOST https://gvnr.dev/v1/account/topup?usd=5      # → 402 challenge → pay → 5,000 ops credited\n```\n\n### 3. Set a spend envelope for your agent\n\n```bash\ncurl -X PUT \\\n  -H \"Authorization: Bearer bg_YOUR_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"agent_id\":\"my-agent\",\"limit_usd\":5,\"window\":\"daily\"}' \\\n  https://gvnr.dev/v1/budget/envelope\n# { \"success\": true, \"agent_id\": \"my-agent\", \"limit_usd\": 5, \"window\": \"daily\" }\n```\n\n### 4. (optional) Set a rate envelope per (agent, provider, model)\n\n```bash\ncurl -X PUT \\\n  -H \"Authorization: Bearer bg_YOUR_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"agent_id\":\"my-agent\",\"provider\":\"anthropic\",\"model\":\"claude-sonnet-4-6\",\"requests_per_minute\":30}' \\\n  https://gvnr.dev/v1/rate/envelope\n```\n\n### 5. Before each LLM request: `budget_clear`, then `rate_check`\n\n```bash\ncurl -X POST \\\n  -H \"Authorization: Bearer bg_YOUR_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"agent_id\":\"my-agent\",\"model\":\"claude-sonnet-4-6\",\"estimated_tokens\":2000}' \\\n  https://gvnr.dev/v1/budget/clear\n# { \"approved\": true, \"remaining_usd\": 4.994, \"operations_remaining\": 18999 }\n\ncurl -X POST \\\n  -H \"Authorization: Bearer bg_YOUR_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"agent_id\":\"my-agent\",\"provider\":\"anthropic\",\"model\":\"claude-sonnet-4-6\"}' \\\n  https://gvnr.dev/v1/rate/check\n# { \"allowed\": true, \"requests_remaining_this_minute\": 29 }\n```\n\n### 6. (optional) Dedupe retries with `idempotency_check`\n\n```bash\ncurl -X POST \\\n  -H \"Authorization: Bearer bg_YOUR_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"key\":\"job-abc-123\",\"ttl_seconds\":3600}' \\\n  https://gvnr.dev/v1/idempotency/check\n# First call:  { \"is_first_call\": true,  \"ttl_remaining_seconds\": 3600 }\n# Replay:      { \"is_first_call\": false, \"ttl_remaining_seconds\": 3598 }\n```\n\n### 7. After the LLM responds, reconcile against actual usage\n\n```bash\ncurl -X POST \\\n  -H \"Authorization: Bearer bg_YOUR_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"agent_id\":\"my-agent\",\"actual_input_tokens\":1800,\"actual_output_tokens\":2400}' \\\n  https://gvnr.dev/v1/budget/reconcile\n# { \"ok\": true, \"drift_usd\": 0.003, \"remaining_usd\": 4.991, \"operations_remaining\": 18999 }\n```\n\n`reconcile` adjusts the **spend envelope** by the drift between your estimate and actual cost (the op quota is untouched). You don't pass the model again — reconcile reuses the one from your prior `budget_clear`. Anthropic, OpenAI, and Gemini all return `usage` fields with real token counts — pass those in to keep the envelope honest.\n\n---\n\n## Human-in-the-loop approvals\n\nWhen an agent hits a denial or a sensitive action, pause for a human instead of failing:\n\n```bash\n# 1. Open a request — returns an approval_id and a mobile-friendly approval_url\ncurl -X POST -H \"Authorization: Bearer bg_YOUR_KEY\" -H \"Content-Type: application/json\" \\\n  -d '{\"agent_id\":\"my-agent\",\"action_summary\":\"Spend $40 on a research run\",\"ttl_seconds\":3600}' \\\n  https://gvnr.dev/v1/approval/request\n# { \"approval_id\": \"...\", \"approval_url\": \"https://gvnr.dev/approve/...\", \"expires_at\": ... }\n\n# 2. The human opens approval_url and taps approve / deny (emailed if notification-email is set).\n\n# 3. Your agent polls until the decision lands:\ncurl -H \"Authorization: Bearer bg_YOUR_KEY\" \\\n  https://gvnr.dev/v1/approval/check/APPROVAL_ID\n# { \"decision\": \"pending\" }  →  \"approved\" | \"denied\" | \"timeout\"\n```\n\nThe agent proceeds on `approved`, skips on `denied`, and handles `timeout` (no decision before `expires_at`) however it likes.\n\n---\n\n## MCP setup\n\nAdd to Claude Desktop or any MCP-compatible client:\n\n```\nhttps://gvnr.dev/mcp?api_key=bg_YOUR_KEY\n```\n\n### Claude Code\n\n```bash\nclaude mcp add gvnr --transport http \\\n  \"https://gvnr.dev/mcp?api_key=bg_YOUR_KEY\"\n```\n\n### MCP tools\n\n| Tool | Description |\n|---|---|\n| `budget_clear(agent_id, model, estimated_tokens)` | Check clearance against the op quota + spend envelope; burns one op |\n| `set_envelope(agent_id, limit_usd, window?)` | Create or update an agent's USD spend cap |\n| `get_balance()` | Remaining governance-operation quota (`operations_remaining`) |\n| `reconcile(agent_id, actual_input_tokens, actual_output_tokens)` | Apply estimate-vs-actual drift to the spend envelope after the LLM responds |\n| `set_rate_envelope(agent_id, provider, model, requests_per_minute)` | Allocate a per-(agent, provider, model) rate share |\n| `rate_check(agent_id, provider, model)` | Approve or deny against the rate envelope; returns `retry_after_ms` on denial |\n| `idempotency_check(key, ttl_seconds?)` | Dedupe retries on a caller-supplied key; returns `is_first_call` |\n| `request_approval(agent_id, action_summary, ttl_seconds?)` | Open a human-in-the-loop approval request; returns an `approval_id` |\n| `check_approval(approval_id)` | Poll an approval: `pending` / `approved` / `denied` / `timeout` |\n\n---\n\n## REST API\n\nAll endpoints except `POST /v1/account` require `Authorization: Bearer bg_YOUR_KEY`.\n\n**TypeScript users:** generate full types from the live OpenAPI spec — `npx openapi-typescript@latest https://gvnr.dev/openapi.json -o types/gvnr.d.ts`. See [TYPESCRIPT.md](TYPESCRIPT.md) for the integration pattern (typed `fetch`, x402 topups, discriminated response unions).\n\n### Account & top-up\n\n| Method | Path | Description |\n|---|---|---|\n| `POST` | `/v1/account` | Provision account — returns `api_key` |\n| `GET` | `/v1/account/balance` | Remaining governance-op quota (`operations_remaining`) |\n| `GET` | `/v1/packs/:pack/info` | Public — preset details, USDC address, raw amount |\n| `POST` | `/v1/account/topup-verify/:pack` | Submit tx hash → verify on-chain → credit (proportional to amount received) |\n| `POST` | `/v1/account/topup?usd=<amount>` | x402-gated pay-as-you-go top-up — name your amount (min $1, max $100) |\n| `POST` | `/v1/account/topup/:pack` | x402-gated preset top-up (machine clients) |\n\n### Budget\n\n| Method | Path | Description |\n|---|---|---|\n| `POST` | `/v1/budget/clear` | Clearance call — approve or deny |\n| `POST` | `/v1/budget/reconcile` | Apply estimate-vs-actual drift to the envelope |\n| `PUT` | `/v1/budget/envelope` | Create or update agent spend cap |\n| `GET` | `/v1/budget/envelope/:agent_id` | Read envelope state |\n| `DELETE` | `/v1/budget/envelope/:agent_id` | Delete an agent's envelope |\n\n### Rate · Idempotency · Approval\n\n| Method | Path | Description |\n|---|---|---|\n| `PUT` | `/v1/rate/envelope` | Set a per-(agent, provider, model) RPM share |\n| `POST` | `/v1/rate/check` | Runtime rate check — `allowed` flag, `retry_after_ms` on denial |\n| `POST` | `/v1/idempotency/check` | Dedupe on a caller-supplied key — `is_first_call` |\n| `POST` | `/v1/approval/request` | Open a human approval request — returns `approval_id` |\n| `GET` | `/v1/approval/check/:approval_id` | Poll decision: `pending` / `approved` / `denied` / `timeout` |\n\n### Clearance response\n\n```json\n{ \"approved\": true, \"remaining_usd\": 4.994, \"operations_remaining\": 18999 }\n```\n\n```json\n{ \"approved\": false, \"remaining_usd\": 0, \"reason\": \"envelope_exceeded\" }\n```\n\nDenial reasons: `no_credits` (op quota exhausted) · `no_envelope` (agent has no envelope) · `envelope_exceeded`\n\n### Status codes\n\nA **denial is not an HTTP error** — it's a `200` with a flag, so check the body, not the status:\n\n| Situation | HTTP | Body |\n|---|---|---|\n| `budget_clear` / `rate_check` allow **or** deny | `200` | `{ approved/allowed: true \\| false, ... }` |\n| Top-up requires payment | `402` | x402 challenge (in the `payment-required` header; see Billing) |\n| Missing / invalid API key | `401` | `{ error }` |\n| Per-IP account-creation throttle | `429` | `{ error: \"rate_limited\", retry_after_ms }` |\n| Bad request body | `400` | `{ error, hint }` |\n\n---\n\n## Billing — governance ops, not your tokens\n\nGvnr charges for **governance operations**, not LLM usage. Your model tokens are billed by your provider; Gvnr never sees them.\n\nTop-ups are **pay-as-you-go at 1,000 ops/$1** in USDC on Base mainnet — name any amount on [`/pay`](https://gvnr.dev/pay) and ops are credited proportionally after on-chain verification. No minimum, no subscription; the amounts below are just one-tap presets:\n\n| Amount | Governance ops | Link |\n|---|---|---|\n| $1 (trial) | 1,000 | `/pay?usd=1` |\n| $19 | 19,000 | `/pay?usd=19` |\n| $39 | 39,000 | `/pay?usd=39` |\n| $79 | 79,000 | `/pay?usd=79` |\n\nWorks with Base MCP, AgentKit, and any x402 client. The `402` challenge follows x402 v2 — payment requirements (network, USDC asset, amount, `payTo`) are returned in the **`payment-required` response header** (the body is empty), so an x402 client settles it automatically; you only hand-parse it if you're rolling your own.\n\n---\n\n## Envelope windows\n\n- `daily` — resets at UTC midnight each day\n- `session` — never resets (use for one-shot tasks; caller-managed)\n\n---\n\n## Supported models\n\nModel pricing is a static lookup on the hot path — no external calls. The estimate deducted from the envelope is `rate(model) × estimated_tokens ÷ 1,000,000` (output rate for chat models, input rate for embeddings), reconciled to actual afterward. These are the per-million-token rates (USD):\n\n| Model | Input | Output |\n|---|---|---|\n| `claude-opus-4-8` / `4-7` / `4-6` | $5 | $25 |\n| `claude-sonnet-4-6` | $3 | $15 |\n| `claude-haiku-4-5` | $1 | $5 |\n| `gpt-4o` | $2.50 | $10 |\n| `gpt-4o-mini` | $0.15 | $0.60 |\n| `gpt-4-turbo` | $10 | $30 |\n| `text-embedding-3-small` / `-large` | $0.02 / $0.13 | input-only |\n| `gemini-embedding-001` / `-2` | $0.15 / $0.20 | input-only |\n\nEmbedding / input-only models are billed on input tokens — pass input tokens as `estimated_tokens` to `budget_clear`. Unknown models fall back to a conservative `$15 / $75` default.\n\n---\n\n## Network\n\nRuns on **Base mainnet** (`X402_NETWORK=eip155:8453`), settling real USDC. There's no minimum to try it: top up as little as **$1** (1,000 governance ops) to exercise the full live rail end-to-end — no testnet needed.\n\n---\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n\nThe canonical hosted service is `https://gvnr.dev`. Self-hosted instances are unaffiliated.\n\n---\n\n## Acknowledgments\n\ngvnr was designed and built by [mightbesaad](https://github.com/mightbesaad) in close partnership with **Claude Code** (Anthropic) — chiefly **Claude Opus 4.8**. From the substrate architecture and the billing model to the code in this repository, it was a genuine collaboration. Thank you.\n",
  "bytes": 14790,
  "sha": "e1b7b7e534311c2e767c7ffe9836266ce8cd376a037ef2ac949c170ee38e165d",
  "repo_slug": "mightbesaad/gvnr",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_dev_gvnr_gvnr_3569b277/readme"
}