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
| Path | Function |
|---|---|
/.well-known/oauth-protected-resource | Metadata of the protected resource (/mcp) |
/.well-known/oauth-authorization-server | Metadata of the authorization server |
/oauth/authorize | Start of the flow; validates client_id, redirect_uri, and PKCE |
/oauth/authorize/request/:id | Query of the pending request, for the consent screen |
/oauth/authorize/decision | Registration of the decision (approve or deny) |
/oauth/token | Exchange of the code for the token pair and renewal by refresh token |
/oauth/revoke | Token revocation |
/mcp | The MCP endpoint itself |
/mcp/connections | Lists (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:
- validates that the
client_idis a canonical https URL, with a path; - fetches the client document with SSRF protection, a 64 KB limit, and a 5 s timeout;
- extracts the client name and the list of allowed redirect URIs;
- 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
| Token | Format | Validity |
|---|---|---|
| Access | a2m_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: Bearerheader. A token in the query string is not accepted — this prevents it from appearing in logs.
Limits and protections
| Protection | Rule |
|---|---|
| Calls per connection | 120 per minute |
| Authentication failures per IP | 600 per minute (only invalid tokens count) |
| Body size | 4 MB — enough for media up to 2 MB in base64 |
| Origin | Requests with Origin are only accepted if the origin is from the app itself (assistants call from the server, without Origin) |
| Rejection responses | 401 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:
- Every tool runs with the role of the user who authorized access.
- Deactivating the user invalidates the assistant's access.
- 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
- Treat consent as you treat a login: read the client name before approving.
- Revoke connections you don't recognize.
- Prefer a dedicated user (with a restricted role) when the automation is for a service, not a person.
- Sharing tokens between assistants is not allowed: each one does its own flow.