Skip to main content
EchoZero supports OAuth 2.1 authorization code with PKCE for clients that cannot safely store long-lived API keys - Claude connectors, ChatGPT apps, local CLIs, and directory integrations.

Endpoints

User consent is handled in the Dev Portal at devportal.echozero.app/mcp/oauth/authorize. Users approve from their saved portal session - do not ask them to copy JWTs from browser devtools.

PKCE parameters

Generate a code_verifier (43-128 random characters) and keep it secret until token exchange.
1

Redirect to authorize

Send the user to GET https://mcp.echozero.app/oauth/authorize with PKCE code_challenge, state, scope, and redirect_uri.
2

User approves in Dev Portal

EchoZero redirects to the Dev Portal consent page. If the user is not signed in, they authenticate first, then approve the requested scopes.
3

Receive authorization code

EchoZero redirects back to your redirect_uri with ?code=...&state=.... Verify state matches what you sent.
4

Exchange code for token

Response:
5

Call protected APIs

Send Authorization: Bearer <access_token> on REST and MCP requests.

Verify the token

After login, confirm the token is active:
For server-side validation without calling user-scoped routes:
Returns { "active": true, "sub": "...", "client_id": "...", "scope": "...", "exp": ... } when valid.

OAuth scopes

Scopes map to API key permissions. Request only what your integration needs: Legacy scope aliases (agents:read, bots:write, etc.) are also accepted. admin:* is not available via OAuth.

Token lifetime and refresh

When the access token expires, re-run the PKCE consent flow or use a long-lived API key for headless servers. There is no offline_access or refresh grant at this time.

code_verifier requirements

43-128 characters from [A-Z], [a-z], [0-9], ., -, _, ~ (unreserved URI characters).

OAuth error responses

MCP with OAuth

OAuth tokens work on MCP the same way as API keys:
  1. POST https://mcp.echozero.app/mcp with Authorization: Bearer <access_token> on every request, including initialize.
  2. Save the mcp-session-id response header from initialize.
  3. Send mcp-session-id: <session> on subsequent MCP calls (tools/list, tools/call, SSE stream, etc.).
MCP sessions are bound to the credential used at initialize. Switching API keys or OAuth tokens while reusing the same mcp-session-id returns 403 with JSON-RPC error code -32002.
See the MCP Server guide for a full initialize example.

Assistant setup (coming soon)

Coming soon: The public skills pack (EchoZeroApp/skills) and ez login CLI are not yet published. Use the PKCE flow above or API keys until the skills repo is public.

Directory integrations

For ChatGPT, Claude, Gemini, and other assistant directories, use connector metadata from:
Per-platform manifests live under /public/directory/* with authorize URL, token URL, and recommended scope lists.