Skip to content

Your first key

A client key is what an agent or a developer uses to reach /mcp. It belongs to one project, grants a chosen subset of that project's services, expires, and every call made with it is attributed to its label.

Mint one

Client keys → Create a key in the console.

Field Notes
Label Who the calls are from — anders, claude-code, ci. This is what appears in the audit log.
Project One project. A key cannot reach another, and the store refuses to mint one that tries.
Services Which of that project's services this key may reach. Grant the minimum.
Lifetime 1 hour, 8 hours, 24 hours, 30 days, or never. Default 30 days.

Minting a client key in the console

The key is shown once. Prodpeek stores only a SHA-256 of it and cannot recover it. Lost it? Revoke and mint another; that is cheaper than a recoverable secret.

Pick a short lifetime

This is the second problem Prodpeek exists to solve, so it is worth being deliberate rather than accepting the default.

Lifetime For
1h / 8h A debugging session. A developer working an incident. The right default for a human.
24h A CI job, or a day of work.
30d A long-lived agent integration you will actually notice expiring.
never Something that would page someone at 03:00 if it stopped. Rare, and a deliberate act.

An expired key is refused at the door with token_expired, audited under its label, so "why did my key stop working" is answerable from the log rather than from guesswork.

Use it

curl -s -X POST http://127.0.0.1:8787/mcp \
  -H "Authorization: Bearer $PRODPEEK_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | python3 -m json.tool

For Claude Code, Cursor, or anything else that speaks MCP, see With Claude Code.

Ask the key what it can do

Every client key can call one built-in tool, prodpeek__explain. It answers from local state, makes no outbound call, and describes the key's own grants:

curl -s -X POST http://127.0.0.1:8787/mcp \
  -H "Authorization: Bearer $PRODPEEK_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
       "params":{"name":"prodpeek__explain","arguments":{}}}'

It returns which services the key holds, which tools each allows, which it refuses and why. This is the first thing an agent should do, and it is faster and quieter than probing — probing fills your audit log with refusals to learn what one local call would have said.

Revoking

Client keys → Revoke. Immediate: the next call with it is refused. Revoking does not touch the service or its credential, only this key's ability to reach it.

Revoke when someone leaves, when a laptop is lost, when an agent integration is retired, or when you see something in the audit log you did not expect. It costs nothing and re-minting takes ten seconds.

Admin keys are a different thing

A client key reads production through /mcp. An admin key configures the instance through /api/v1 and /mcp-admin.

Neither is a superset of the other. An admin key cannot read a customer's database; a client key cannot mint another key. Present either at the wrong door and you get wrong_door, audited.

Mint an admin key when you want CI, the CLI, or an agent to set things up:

prodpeek admin-key create ci --ttl 24h

Next

→ Point Claude Code at it