Authentication
Custom MCP clients authenticate with OAuth 2.1 + PKCE (S256) as public clients — no client secret, ever.
Tokens last 30 days, with no refresh grant
This is the most important constraint to design for. When a token expires, the user must re-approve — build your client to expect that.
Endpoints
- POST /api/oauth/registerDynamic Client Registration — returns your client_id
- GET /api/oauth/authorizeConsent screen — user reviews scopes and approves
- POST /api/oauth/tokenExchanges the authorization code for a 30-day access token
Flow
- Register your client with Dynamic Client Registration —
authorization_codegrant only,token_endpoint_auth_method: none. - Send the user to the consent screen with a PKCE challenge.
- Exchange the returned code (plus verifier) for an access token.
- Call
POST /mcpwith the token as a Bearer header.
View example
Dynamic client registration
curl -X POST https://klaarin.com/api/oauth/register \
-H "Content-Type: application/json" \
-d '{
"client_name": "My Klaarin Agent",
"redirect_uris": ["https://myagent.dev/callback"],
"grant_types": ["authorization_code"],
"token_endpoint_auth_method": "none"
}'Token exchange
curl -X POST https://klaarin.com/api/oauth/token \
-d grant_type=authorization_code \
-d code=<authorization code> \
-d code_verifier=<PKCE verifier> \
-d client_id=<client id> \
-d redirect_uri=https://myagent.dev/callback