The players
Your client is registered in sandbox (test cards) or production (live cards) mode — a production client requires an active subscription. See Production.
The flow

- The user clicks Connect with Agentcard in your app.
- Your app generates a PKCE
code_verifier, derives itscode_challenge, and redirects the user to/authorize. - Agentcard verifies the user by email and shows the consent screen with your app’s name.
- The user approves; Agentcard redirects back to your
redirect_uriwith an authorizationcode. - Your app exchanges the code (plus the
code_verifierand yourclient_secret) at/tokenfor anaccess_tokenandrefresh_token. - Your app calls the MCP server with
Authorization: Bearer <access_token>. - When the token expires, a call returns
401— refresh once at/tokenand retry. Each refresh rotates the refresh token.
The requests
Authorize — redirect the user to:{ access_token, refresh_token, expires_in, token_type }. Store both tokens encrypted, keyed to the user.
Refresh when a call returns 401:
client_secret on both requests; confidential clients must send it on both.
Tokens
Keep it safe
- PKCE is always enforced — for confidential clients too. The
code_verifierproves the token request comes from whoever started the flow. - Always send
resource=https://mcp.agentcard.sh/mcpon both/authorizeand/token— tokens are bound to that audience and validated on every call. - Bind
stateto the initiating user and verify it on the callback to prevent CSRF. - Keep secrets server-side. Never expose
client_secretor tokens to the browser, and never log them.
Discovery
Everything above is discoverable at runtime — endpoints can be confirmed programmatically:agent-cards connections lists the apps they’ve connected, and connections revoke <clientId> disconnects one instantly.