OAuth 2.0 with PKCE
Most MCP clients (Claude Desktop, Cursor, etc.) handle the OAuth flow automatically. This section is for developers building custom MCP clients.1. Dynamic Client Registration
Register your client to get aclient_id and client_secret.
2. Authorization Request
Redirect the user to the authorization endpoint.| Parameter | Required | Description |
|---|---|---|
response_type | Yes | Must be code |
client_id | Yes | From client registration |
redirect_uri | Yes | Must match a registered redirect URI |
code_challenge | Recommended | PKCE code challenge (S256) |
code_challenge_method | With challenge | Must be S256 |
state | Recommended | Opaque value for CSRF protection |
scope | Optional | Space-separated scopes (defaults to read) |
redirect_uri with a code parameter.
3. Token Exchange
Exchange the authorization code for tokens.4. Token Refresh
When the access token expires, use the refresh token to get a new one.Scopes
| Scope | Description |
|---|---|
read | Read access to notes, knowledge, workspace, and members |
write | Write access (reserved for future use) |
offline_access | Request a refresh token |
openid | OpenID Connect identity |
profile | User profile info |
email | User email address |
Token Lifetime
| Token | Lifetime |
|---|---|
| Access token (JWT) | 1 hour |
| Refresh token | 30 days |
| Authorization code | 10 minutes |
API Key Authentication
As an alternative to OAuth, you can use an existing Caret API key.Permission Mapping
| Permission | MCP Tools |
|---|---|
notes / read | caret_list_notes, caret_get_note, caret_search_notes, caret_search_knowledge |
users / read | caret_list_members |
| (none required) | caret_get_workspace |
Errors
| Error | Status | Description |
|---|---|---|
invalid_client | 400/401 | Unknown client or authentication failed |
invalid_grant | 400 | Authorization code expired, already used, or PKCE verification failed |
invalid_scope | 400 | Requested scope not supported or not allowed |
invalid_request | 400 | Missing or malformed parameters |
server_error | 500 | Internal server error |