{
  "markdown": "# hive-mcp-secrets\n\n[![srotzin/hive-mcp-secrets MCP server](https://glama.ai/mcp/servers/srotzin/hive-mcp-secrets/badges/score.svg)](https://glama.ai/mcp/servers/srotzin/hive-mcp-secrets)\n\n**Encrypted secret store for the A2A network — Hive Civilization.** AES-256-GCM at rest, agent-DID-scoped namespaces, audit log, x402 USDC settlement on Base L2. MCP `2024-11-05`. Inbound only.\n\nAgents put encrypted secrets keyed by `(namespace, key)` and retrieve them later. The namespace is the agent DID — a caller can only see and write to its own namespace. The master key lives in the operator's environment and is never committed, logged, or returned over the wire.\n\n```\nbrand : Hive Civilization gold #C08D23 (Pantone 1245 C)\nspec  : MCP 2024-11-05 / Streamable-HTTP / JSON-RPC 2.0\nwallet: W1 MONROE 0x15184bf50b3d3f52b60434f8942b7d52f2eb436e (Base)\ncrypto: AES-256-GCM, 12-byte IV per record, 16-byte auth tag, node:crypto\n```\n\n## Quick start\n\n```bash\ngit clone https://github.com/srotzin/hive-mcp-secrets\ncd hive-mcp-secrets\nnpm install\n\n# 32 random bytes as hex — never commit this value\nexport SECRETS_MASTER_KEY=$(node -e \"console.log(require('crypto').randomBytes(32).toString('hex'))\")\n\nnpm start\n# hive-mcp-secrets on :3000\n```\n\nHosted endpoint: `https://hive-mcp-secrets.onrender.com/mcp`\n\n## Tools and pricing\n\n| Tool | USD / call | Notes |\n|---|---|---|\n| `secrets_get`   | $0.002 | Read and decrypt a secret. Caller must own the namespace. |\n| `secrets_put`   | $0.005 | Encrypt and store a secret. Returns 503 if master key not configured. |\n| `secrets_list`  | free   | List keys in a namespace. Tier 0. |\n| `secrets_audit` | $0.002 | Read the audit log for a namespace. |\n\nAll payments are inbound. Submit a Base USDC `tx_hash` (caller → W1) in the request body or `x402-tx-hash` header. The shim reads the receipt from Base RPC, decodes the USDC `Transfer` log, and verifies recipient and amount before serving the call.\n\n## Operator note — master key required for writes\n\n`hive-mcp-secrets` reads `SECRETS_MASTER_KEY` from the process environment at startup.\n\n- If set, it is parsed as 64-char hex → 32 raw bytes; or as base64 → 32 raw bytes; or otherwise SHA-256 hashed to 32 bytes.\n- If not set, writes return `503 service_unavailable` with `reason: \"SECRETS_MASTER_KEY not set\"`. Reads of records that do not exist return `404` as usual; reads of stored records require the same key that wrote them, since AES-256-GCM rejects decryption with any other key.\n\nThe key is never committed to the repository, never logged, and never returned over the wire. Operators are expected to set it in the deployment environment (Render env var, Kubernetes secret, etc.) before enabling production traffic. Rotating the key invalidates all previously stored ciphertexts.\n\n## Namespace model\n\nThe `namespace` parameter on every endpoint is the agent DID that owns the data. Every endpoint enforces `caller_did === namespace` and returns `forbidden_namespace_mismatch` otherwise. There is no superuser, no cross-namespace read, and no multi-DID sharing in v1.\n\nThe audit log is per-namespace and records every action — `get`, `put`, `delete`, `list`, `audit`, plus the negative paths `payment_required`, `error:not_found`, `error:integrity_check_failed`, etc. Entries store `caller_did`, `action`, `ts_ms`, and (for paid ops) `tx_hash`, `payer`, and `amount_usd`.\n\n## REST endpoints\n\n| Method | Path | Purpose |\n|---|---|---|\n| `GET`    | `/v1/secrets/{namespace}/{key}` | Read and decrypt one secret. **Paid**. |\n| `PUT`    | `/v1/secrets/{namespace}/{key}` | Encrypt and store one secret. **Paid**. Returns `503` without master key. |\n| `DELETE` | `/v1/secrets/{namespace}/{key}` | Remove a secret. Free, caller-owned. |\n| `GET`    | `/v1/secrets/{namespace}`       | List keys in a namespace. Free, Tier 0. |\n| `GET`    | `/v1/secrets/audit`             | Audit log read. **Paid**. Query: `namespace`, `caller_did`, `since_ms?`, `until_ms?`, `limit?`. |\n| `GET`    | `/v1/secrets/today`             | Today's revenue snapshot. Free. |\n| `GET`    | `/health`                       | Service health, including `master_key_loaded`. |\n| `GET`    | `/.well-known/mcp.json`         | MCP discovery. |\n| `POST`   | `/mcp`                          | MCP JSON-RPC. |\n\n### `PUT /v1/secrets/{namespace}/{key}` body\n\n```json\n{\n  \"value\": \"the-secret-string\",\n  \"caller_did\": \"did:hive:0xabc...\",\n  \"tx_hash\": \"0x...64-char-tx-on-base...\"\n}\n```\n\nWithout `tx_hash`, the response is a 402 envelope:\n\n```json\n{\n  \"error\": \"payment_required\",\n  \"x402\": {\n    \"type\": \"x402\", \"version\": \"1\", \"kind\": \"secrets_put\",\n    \"asking_usd\": 0.005, \"accept_min_usd\": 0.005,\n    \"asset\": \"USDC\", \"asset_address\": \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\n    \"network\": \"base\", \"pay_to\": \"0x15184bf50b3d3f52b60434f8942b7d52f2eb436e\",\n    \"nonce\": \"...\", \"issued_ms\": 1714200000000\n  }\n}\n```\n\n## Encryption details\n\n- Algorithm: `aes-256-gcm` (FIPS-recognized AEAD)\n- Key length: 32 bytes\n- IV length: 12 bytes, fresh `crypto.randomBytes(12)` per record\n- Auth tag length: 16 bytes\n- Storage: SQLite `secrets` table — `(namespace, key, ciphertext, iv, auth_tag, created_ms, updated_ms, version)` with PRIMARY KEY `(namespace, key)`\n- Write path: `node:crypto.createCipheriv → update → final`, then `getAuthTag()`. All three values stored as base64 TEXT.\n- Read path: `createDecipheriv → setAuthTag → update → final`. Any single bit flipped in `ciphertext`, `iv`, or `auth_tag` causes `final()` to throw, which surfaces as `integrity_check_failed`.\n\nThe smoke test below verifies tampered ciphertext fails to decrypt — this is real AES-GCM, not an integrity check tacked on after the fact.\n\n## MCP usage\n\n```bash\ncurl -X POST https://hive-mcp-secrets.onrender.com/mcp \\\n  -H \"content-type: application/json\" \\\n  -d '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/list\"}'\n```\n\n```bash\ncurl -X POST https://hive-mcp-secrets.onrender.com/mcp \\\n  -H \"content-type: application/json\" \\\n  -d '{\n    \"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"tools/call\",\n    \"params\":{\n      \"name\":\"secrets_put\",\n      \"arguments\":{\n        \"namespace\":\"did:hive:0xabc\",\n        \"key\":\"openai_api_key\",\n        \"value\":\"sk-...\",\n        \"caller_did\":\"did:hive:0xabc\",\n        \"tx_hash\":\"0x...\"\n      }\n    }\n  }'\n```\n\n## Local smoke test\n\n```bash\nexport SECRETS_MASTER_KEY=$(node -e \"console.log(require('crypto').randomBytes(32).toString('hex'))\")\nnpm start &\nsleep 1\n\n# Tier 0 list (empty)\ncurl -s \"http://localhost:3000/v1/secrets/did:hive:0xa/\" | jq .\n\n# PUT without tx_hash → 402 envelope\ncurl -s -X PUT \"http://localhost:3000/v1/secrets/did:hive:0xa/k1\" \\\n  -H \"content-type: application/json\" \\\n  -d '{\"value\":\"hello\",\"caller_did\":\"did:hive:0xa\"}' | jq .\n\n# PUT with stub tx (set VERIFY_ONCHAIN=false locally)\nVERIFY_ONCHAIN=false curl -s -X PUT \"http://localhost:3000/v1/secrets/did:hive:0xa/k1\" \\\n  -H \"content-type: application/json\" \\\n  -d '{\"value\":\"hello\",\"caller_did\":\"did:hive:0xa\",\"tx_hash\":\"0xtest\"}' | jq .\n\n# GET round-trip\nVERIFY_ONCHAIN=false curl -s \"http://localhost:3000/v1/secrets/did:hive:0xa/k1?caller_did=did:hive:0xa&tx_hash=0xtest\" | jq .\n```\n\n## Hosting\n\nDeployed to Render: `srv hive-mcp-secrets`, `oregon`, `starter`, `autoDeploy=true`. The Render env var `SECRETS_MASTER_KEY` is **the operator's responsibility to set**. Without it, the deployed service still runs, `/health` reports `master_key_loaded: false`, and writes return `503`.\n\n## License\n\nMIT — see `LICENSE`.\n\n## Hive Civilization Directory\n\nPart of the Hive Civilization — agent-native financial infrastructure.\n\n- Endpoint Directory: https://thehiveryiq.com\n- Live Leaderboard: https://hive-a2amev.onrender.com/leaderboard\n- Revenue Dashboard: https://hivemine-dashboard.onrender.com\n- Other MCP Servers: https://github.com/srotzin?tab=repositories&q=hive-mcp\n\nBrand: #C08D23\n<!-- /hive-footer -->\n",
  "bytes": 7837,
  "sha": "c69c2b1d86f91a925df406f62dec557f5536a324906412dc26827398fb8e8aa7",
  "repo_slug": "srotzin/hive-mcp-secrets",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_srotzin_hive_mcp_secrets_3ea0dbc5/readme"
}