# Proxy — Agent Auth Guide

You are an agent that wants to call the Proxy MCP server on a user's behalf. This file describes how to connect and how to handle the credential safely.

Two hosts are relevant:

- **Resource server** — `https://mcp.useproxy.dev/mcp` — the MCP server you will call.
- **Landing/docs** — `https://useproxy.dev` — where the user learns about Proxy and where the machine-readable docs (this file included) live.

## Current state

Proxy has no API keys, ever. Every client registers itself dynamically and authenticates with OAuth 2.0 PKCE — there is no out-of-band secret for the user to generate or hand you. If you can complete a standard MCP OAuth handshake, you can connect yourself; no human needs to visit a dashboard and mint anything.

## Use the existing tooling first

Before you touch anything auth-shaped, check whether you're already connected.

1. **You're already an MCP client** (Claude, ChatGPT, Cursor, etc.) — check your current tool list for `get_meta_ads`, `search_competitors`, etc. If they're there, Proxy is already connected; call the tools directly, nothing to fetch.
2. **Native connect** — if you support adding MCP servers yourself, point at `https://mcp.useproxy.dev/mcp` (streamable-http) and let your host run its own OAuth discovery and dynamic client registration. Manifest for discovery: `https://useproxy.dev/.well-known/mcp.json`.
3. **CLI install** — if you're running shell commands and can't do an in-host OAuth flow, use `curl -sL useproxy.dev/install | sh`. It runs the PKCE flow itself: opens a local callback listener, launches the user's browser for consent, then writes an OAuth-connected config into whichever client it detects (Claude Code, Claude Desktop, Cursor, Codex, etc.). This still needs a human at the machine to approve the consent screen — it's a lighter-weight OAuth client, not a way to skip the browser step. Re-running it is safe — it revokes and replaces any existing install token. Per-client steps: https://useproxy.dev/welcome.md
4. **Agent skill** — load `https://useproxy.dev/SKILL.md` for the ad-research playbook (tool selection, credit budgeting, gotchas) before doing real work.
5. **Sandbox** — `https://mcp.useproxy.dev/sandbox` needs no auth at all and returns fixture ad data. This is the only option that needs no human present. Use it whenever you're fully unattended (no user available to complete a browser consent step, now or later) — there's currently no non-interactive way to get a live-data credential.

If any of these already gets you connected, stop there.

## Supported login option: OAuth 2.0 PKCE with dynamic client registration (no API keys)

There is no user-issued secret to relay. You obtain your own OAuth client via dynamic client registration (DCR is open — no pre-approval needed) and the user authorizes it in their browser once.

### How to connect

Standard MCP authorization: discover the resource/authorization server metadata at `https://mcp.useproxy.dev`, register a client (DCR), redirect the user through PKCE authorize + consent, exchange the code for an access token. A spec-compliant MCP client library does all of this for you when you connect to `https://mcp.useproxy.dev/mcp` — you don't hand-roll it. Every path — native connect and the CLI installer alike — ends in a browser consent screen a human has to approve at least once; there's no non-interactive variant. If you're in a shell and can't rely on your host's own OAuth client, use the CLI installer (§3 above) instead of implementing the flow yourself — but a user still has to be there to approve it. If nobody is available at all, use the sandbox (§5 above) instead.

### How to use the token

```http
POST /mcp HTTP/1.1
Host: mcp.useproxy.dev
Authorization: Bearer <access_token>
```

Your MCP client library holds the token — you shouldn't need to see or handle it directly. If you do end up with it in view (e.g. reading a client config file), never echo it back to the user, log it, or include it in commit messages, PR descriptions, error reports, or screenshots.

### Errors

| Situation | Meaning | What to do |
| --- | --- | --- |
| `401` on connect or first tool call | No valid access token yet, or the OAuth handshake hasn't completed. | Let your MCP client run the standard flow (discovery → DCR → PKCE authorize → token), or fall back to the CLI installer — both need a human to approve consent once. No human available at all? Use the sandbox instead. |
| `401` on a previously-working connection | Token expired or was revoked. | Let your OAuth client refresh/re-authorize automatically. If it can't, re-run `curl -sL useproxy.dev/install | sh` — it's idempotent. |
| A tool call succeeds but the response contains an upgrade/credit-wall message | Not an auth failure — the user's daily credit allowance is used up. | Surface the wall message and upgrade link to the user (also available via `get_credit_balance`). Don't retry or try to reconnect. |
| Anything else at the transport level | Rare. | Check `https://mcp.useproxy.dev/health`; retry once, then tell the user something's wrong server-side. |

## Revocation

There's no key to revoke, but the two connection paths revoke differently — removing a connector in client settings does not, by itself, invalidate a CLI-installed token:

- **Native OAuth connectors** (Claude web/ChatGPT/Cursor/etc., connected via the full handshake) — the user removes the connector from their client's settings. That ends the client's OAuth grant.
- **CLI-install token** (the `proxy_...` string the installer writes into a local client config) — it doesn't expire on its own, and deleting it from a config file doesn't invalidate the string itself; a copy saved elsewhere would keep working. The only way to kill it is for the user to re-run `curl -sL useproxy.dev/install | sh`, which deletes the old token server-side before issuing a new one. If a copy needs to be killed immediately and reinstalling isn't an option, the user should contact support@useproxy.dev.

You'll discover revocation as a `401` on a previously-working connection — drop the cached session and prompt the user to reconnect or reinstall.
