Skip to main content

OAuth and security

agents2.me implements OAuth 2.1 with PKCE for MCP. There is no application password, static key, or shared long-lived token — the assistant receives tokens that belong to one person.

Endpoints​

PathFunction
/.well-known/oauth-protected-resourceMetadata of the protected resource (/mcp)
/.well-known/oauth-authorization-serverMetadata of the authorization server
/oauth/authorizeStart of the flow; validates client_id, redirect_uri, and PKCE
/oauth/authorize/request/:idQuery of the pending request, for the consent screen
/oauth/authorize/decisionRegistration of the decision (approve or deny)
/oauth/tokenExchange of the code for the token pair and renewal by refresh token
/oauth/revokeToken revocation
/mcpThe MCP endpoint itself
/mcp/connectionsLists (GET) and revokes (DELETE) the user's connections

Client identification​

There is no dynamic registration of clients. The client_id is a canonical https URL that points to the client's own metadata document (the CIMD standard). agents2.me:

  1. validates that the client_id is a canonical https URL, with a path;
  2. fetches the client document with SSRF protection, a 64 KB limit, and a 5 s timeout;
  3. extracts the client name and the list of allowed redirect URIs;
  4. caches it for 1 hour.

That is why the assistant needs to publish its own metadata document — this is how the consent screen shows a trustworthy name instead of a random URL.

Tokens​

TokenFormatValidity
Accessa2m_at_…1 hour
Renewal (refresh)a2m_rt_…30 days, with rotation
  • The tokens are stored only as a hash — not even agents2.me can print the value after it is issued.
  • The renewal is rotating: each use of the refresh token generates a new one and invalidates the previous one (with a tolerance window for concurrent requests).
  • The authorization code lives for 60 seconds; the consent request, 10 minutes.
  • The token always goes in the Authorization: Bearer header. A token in the query string is not accepted — this prevents it from appearing in logs.

Limits and protections​

ProtectionRule
Calls per connection120 per minute
Authentication failures per IP600 per minute (only invalid tokens count)
Body size4 MB — enough for media up to 2 MB in base64
OriginRequests with Origin are only accepted if the origin is from the app itself (assistants call from the server, without Origin)
Rejection responses401 with WWW-Authenticate pointing to the metadata; 429 when exceeding the limit; 403 for a disallowed origin

Permissions​

The assistant inherits the user, not the company. Consequences:

  1. Every tool runs with the role of the user who authorized access.
  2. Deactivating the user invalidates the assistant's access.
  3. Changing the user's role changes — immediately — what the assistant can do.

Audit​

MCP calls are logged as authenticated calls, with identification of the connection, the user, and the time (without the token contents, which are never readable). The list of active connections, the last use, and revocation are in Settings → Connected apps.

Best practices​

  1. Treat consent as you treat a login: read the client name before approving.
  2. Revoke connections you don't recognize.
  3. Prefer a dedicated user (with a restricted role) when the automation is for a service, not a person.
  4. Sharing tokens between assistants is not allowed: each one does its own flow.