Authenticating
How an agent authenticates to the MCP server with an sk- key, and which calls need more.
Every Putty surface takes one bearer: either a Privy access token from a
signed-in dashboard session, or an sk- API key. This page is about the
key, because that is the one an agent holds.
The key
POST /account/api-keys mints one and returns the plaintext exactly once. The
store keeps only the SHA-256 hash, a twelve-character display prefix, and the
last four characters — there is no way to recover the plaintext afterwards, so
copy it when you see it.
curl -X POST http://localhost:3001/account/api-keys \
-H "Authorization: Bearer $PRIVY_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "label": "ci-deploy" }'The key looks like sk-AbCdEfGh1jkLmnOpQrStUvWxYz0123456789aBcDeFg — the sk-
prefix, then 43 base62 characters of CSPRNG entropy, 46 in all. The prefix is
there so that GitHub secret scanning and tools like TruffleHog recognise an
accidentally committed key rather than it sitting in a public repo unnoticed.
Treat it like any other secret: a CI secret manager, never source.
Sending it
Over HTTP
curl https://api.putty.wtf/agents \
-H "Authorization: Bearer $PUTTY_API_KEY"Over MCP
The Streamable HTTP transport requires the Accept header to list both
content types. Send a POST with a JSON-RPC body:
curl -N https://mcp.putty.wtf/mcp \
-H "Authorization: Bearer $PUTTY_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'In an MCP client config, the same three values:
{
"mcpServers": {
"putty": {
"type": "http",
"url": "https://mcp.putty.wtf/mcp",
"headers": {
"Authorization": "Bearer sk-…",
"Accept": "application/json, text/event-stream"
}
}
}
}The server is stateless
There is no session to establish. A client that only needs to discover or call
tools can skip the initialize round-trip entirely, and a fresh server and
transport are built per request — so two concurrent callers cannot cross
responses, even if both start at JSON-RPC id 1.
What a key is not enough for
The tool set does not change between the two caller flavours, but some tools need
more than a key. Anything scoped to a wallet resolves a Privy DID first,
because a wallet belongs to a person and an sk- key names only an account. A
caller holding just a key gets a clear refusal rather than a call against nobody's
wallet.
That is the whole of Privy — its users, wallets, actions, and transactions — and the wallet half of the Blockchain category's LP tools.
Tools that do not need a wallet: the whole Catalog category, Brand where it is not applied to a wallet-scoped resource, Media, Project, Dexscreener, and the read-only RPC half of Blockchain.
What needs no authentication at all
These need no bearer, and a client can read them with no account:
GET /mcp/tools— the full tool list, 75 tools with every input and output schema, plus thecategoriesandsubcategoriesarrays.GET /health— liveness. It performs no dependency checks, so a 200 means the process answered, not that Postgres is reachable.POST /verifyandGET /verify/methods— the free Verify. Paste a contract, get the permission diff and the plain-English readback. It never touches the credit ledger.
Beyond the MCP surface, thirteen HTTP operations across the API are free and
public, including the token Scan, the Receipts page, the showcase listing and
its badge, the leaderboard, the hook catalogue, and the brand preview. That list
is on the free layer page, and it is the OpenAPI document's
own — each of those operations is marked security: [].
Revoking
DELETE /account/api-keys/{id} revokes a key instantly; any new request
presenting it gets a 401. GET /account/api-keys lists every key you have
minted, including revoked ones, with its label, prefix, and last four
characters — never the plaintext.
What an agent cannot do with a key
A key authenticates; it does not grant. Registering an agent with
POST /agents grants nothing either — it names a workload so its spend is
separately reportable. The agent can only make metered calls with a bearer the
caller already holds, and it draws on the caller's credit balance.
The tools that move value or publish are request-shaped for the same reason.
Onchain simulates and reports rather than sending;
Social drafts and returns a link for a person to click;
media_generate_video prices the job and submits nothing until a second call
confirms it.