Skip to main content
Most people never need this page. If you are connecting Claude, Claude Code, Cursor or VS Code, the client does all of this for you — go to Connect a client and click through the browser prompt. This page is for the other case: you are writing an MCP client, reviewing Attensira before listing or approving it, or debugging a flow that stops somewhere in the middle and you need to know which document said what.

Two roles, and only one of them is ours

The authorization server is Clerk, running under our own hostname. That is the same system that signs you in to the dashboard, so approving a client is the sign-in you already know. The split is not cosmetic. The resource server never holds a signing key and never issues anything — it verifies what arrives and forwards it. Everything about issuing a token, and every rule that governs one, belongs to the authorization server.
This page describes the resource server’s behaviour precisely, because that is ours. For the authorization server it describes the shape of the flow and points you at the discovery document for the specifics. Endpoint paths, registration limits, refresh-token format and lifetimes are the authorization server’s to state, and a copy of them here would be a copy that goes stale.

Discovery

Start with an unauthenticated request to the MCP endpoint. It answers 401 with a challenge that points at the metadata:
Shell
Response header
Two paths serve the protected-resource document (RFC 9728), with identical bodies — clients differ on which one they probe:
Protected-resource metadata
Body
authorization_servers names the issuer. Read the endpoints from its own document rather than from this page — that is what discovery is for, and it is the only copy that cannot be out of date:
Authorization-server metadata
It gives you authorization_endpoint, token_endpoint, jwks_uri, registration_endpoint, the supported grant types and the PKCE methods.
Until the authorization server answers, the 401 above omits resource_metadata. That is deliberate: a client that sees the pointer starts a flow, and pointing one at a server that is not there fails worse than a plain refusal. If you get a 401 with no pointer, OAuth is not available yet on that deployment — use an API key.

Scopes

There are deliberately no Attensira scopes. The scopes a token carries are the authorization server’s own built-ins — openid, profile, email, offline_access and user:org:read — and none of them names an Attensira permission. A token names a person; what that person may do is a question the Attensira backend already answers from the verified subject, and a second permission system here would only be a second thing to disagree with it. Two consequences follow. Every OAuth connection is read and write. Approving a client grants it your organisation, and there is no read-only consent — restrict a connected assistant by what you ask it to do, or by the tool allow-list your client offers, and use a read-only API key where you need a credential that cannot write. And offline_access is the one scope that is not optional in practice: access tokens are short-lived and refreshing is the only way a client stays connected, so a client that does not request it will ask you to sign in again within the hour. user:org:read lets the authorization server stamp an organisation on the token when you have one. It is read when present and never required: a solo workspace has no organisation to stamp, and a connection is resolved from who you are either way.

Authorization code with PKCE

The authorization code grant with PKCE (S256) is what to implement. Confirm the supported methods in the discovery document before you build against it.
Authorize request
The user signs in and approves. The redirect back carries the code and your state echoed byte for byte; exchange the code at the token_endpoint with your code_verifier. The resource parameter (RFC 8707) must be exactly https://mcp.attensira.com/mcp. It is what binds the token to this server, and the resource server checks it on every request — see Tokens.
Authorization codes are single use. Do not retry an exchange on a network error without first checking whether the original attempt succeeded: a replayed code is indistinguishable from a stolen one, and is treated as such.

Registering a client

Clients register through dynamic client registration (RFC 7591). Client ID Metadata Documents are not offered: the authorization server’s discovery document does not advertise client_id_metadata_document_supported, so register dynamically. The discovery document names the registration_endpoint; the limits and expiry that apply to a registration are the authorization server’s and are stated there. No client secrets are issued. Every MCP client is a public client, and a secret shipped inside one is not a secret.
Anyone can register a client and choose its display name. Read the name on the consent screen before approving, and treat an unfamiliar client as a thing to be sure about: every approved connection can add prompts, run automations and spend credits, because there is no read-only consent.

Tokens

Access tokens are RS256-signed JWTs with aud set to https://mcp.attensira.com/mcp. The resource server verifies each one locally against the authorization server’s published keys: signature, issuer, audience and expiry. Nothing is re-signed and nothing is rewritten before it reaches the API. They are short-lived, and the client refreshes them in the background. Refresh eventually runs out, at which point the client asks you to sign in again — occasional, and the point of the design rather than a fault. Lifetimes are the authorization server’s to set. The access token names you by reference — the user, and the organisation when the authorization server has one for you — and carries no email, no name and no other personal data.
Because verification is local, the resource server never asks whether a token is still wanted. Revoking a connection stops the next refresh, but an access token already in a client’s hands stays valid until it expires. If you need access cut off immediately, use an API key and revoke it — a key is checked on every request.

Which workspace a token reaches

A token names your organisation, not one workspace. Every tool that works on a workspace takes an optional project, so one connection reaches every workspace the organisation owns — an agency running three domains connects once, not three times. Omit it and your only workspace is used; if there are several, name one. get_account lists the ids in workspaces. A workspace id outside your organisation comes back as a workspace that does not exist, which is the same answer as one that never existed.

Errors from the MCP endpoint

These are the resource server’s, and they are exact. The 401 is deliberately the same string for every cause. Telling a caller which one is true tells an attacker how close they are. It is the only refusal the MCP endpoint makes: there is no 403 and no scope gate, because a token that verifies may call any tool, and whether that customer is allowed the answer is decided by the backend — the one place that knows what an Attensira workspace is. The single exception is get_ai_traffic_install, which the backend refuses to a token because its response carries a signing secret; it says so, and the fix is an API key. Errors raised during the flow itself — invalid_request, invalid_client, invalid_grant, invalid_scope, invalid_target, access_denied — come from the authorization server in the RFC 6749 envelope, and its documentation governs them.

Static keys still work here

None of this replaces atn_live_ keys. The MCP endpoint accepts an OAuth token or a static key, permanently, and headless callers such as n8n and CI should keep using keys — they cannot complete a browser sign-in. See API keys. The REST API takes a static key only. OAuth tokens are for the MCP server.