The three hosts
They are separate names on purpose. The resource server never sees a signing key, and the issuer string is one origin with no ambiguity about what it means.
Discovery
Start with an unauthenticated request to the MCP endpoint. It answers401 with a challenge that points at the metadata:
Shell
Response header
Protected-resource metadata
Body
404. Attensira is not an OpenID Provider and never issues an id_token:
Authorization-server metadata
Endpoints
Every one of these is on
auth.attensira.com only. The same paths on webapp.attensira.com return 404 — one issuer, one origin.
Scopes
There are exactly two, and there will not be a third in this version.attensira:write implies attensira:read; you do not need to request both, though clients commonly do.
An authorize request that names no scope at all gets attensira:read only. A client that needs to change your workspace has to ask for it, so the consent screen can tell you that is what it is asking for. See the tool reference for which scope each tool needs.
Authorization code with PKCE
Only the authorization code grant is supported, and only with PKCE usingS256. There is no implicit grant, no password grant, and code_challenge_method=plain is rejected.
Authorize request
state echoed byte for byte, and the issuer:
Redirect
Shell
redirect_uri is matched exactly against what the client registered. The single exception is RFC 8252 loopback — localhost, 127.0.0.1 and ::1 compare scheme, host and path and ignore the port, so a CLI that listens on an ephemeral port works. No other host gets that carve-out and there are no wildcards.
The resource parameter (RFC 8707) must be exactly https://mcp.attensira.com/mcp. Anything else is invalid_target.
Client identification
Three ways to be a client, in the order Attensira prefers them:- Verified clients. Claude, Claude Code,
mcp-remote, Cursor and VS Code are known to the authorization server, so the consent screen shows a real product name rather than a string the client supplied about itself. - Client ID Metadata Documents. Host a metadata document at an HTTPS URL and use that URL as your
client_id. Nothing to register, nothing to expire. - Dynamic client registration.
POST https://auth.attensira.com/oauth/registerper RFC 7591, for clients that cannot do CIMD. Registration is rate limited by IP,redirect_urisis required and must behttps://or loopback, and a registration expires after 90 days of the client not being used.
none; a request that presents a secret is rejected with invalid_client. Every MCP client is a public client, and a secret shipped inside one is not a secret.
Tokens
Refresh tokens rotate: every use returns a new one and consumes the old. Replaying a consumed refresh token revokes the whole chain it belongs to, so a client that keeps a stale copy around and retries with it will log itself out. A well-behaved client stores only the newest.
The access token names you by reference — the user, the workspace and the granted scopes — and carries no email, no name and no other personal data.
Sixty minutes is also the worst case after you revoke a connection. Revocation stops the next refresh immediately, but an access token already in a client’s hands stays valid until it expires. Plan on up to an hour, not instantly, and rotate anything else that was exposed alongside it.
Revoking
Two places, for two different situations. Revoke a whole connection from Settings → Connections in the app — this is what you want when a laptop is lost, a teammate leaves, or you no longer recognise something in the list. See Connected applications. A client can also revoke its own tokens at the endpoint, which is what a well-behaved client does when you sign out of it:Shell
200, including for a token that was already revoked or never existed. A revocation endpoint that distinguished them would be a way to test whether a stolen token is live.
Errors
Errors use the RFC 6749 envelope, never a200 with an error inside it:
Error body
The
401 from the MCP endpoint is deliberately the same string for every cause — missing, malformed, expired, wrong audience, bad signature. Telling a caller which one is true tells an attacker how close they are.
Insufficient scope is a 403 and not a 401 on purpose: the token is fine, so a client that discards it and restarts discovery is doing the wrong thing. Reconnect with the wider scope instead.
Static keys still work here
None of this replacesatn_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 — see API keys. The REST API does not use OAuth at all.