# iQub MCP — agent registration (auth.md)

iQub is a messaging platform. This document is the auth.md skill for its MCP
resource: how an agent acting on behalf of a person registers a delegation and
obtains a short-lived, revocable grant, without an API key and without a
pre-registered OAuth client.

- Service: iQub
- Protected resource: `https://mcp.dev.iqub.io/mcp`
- Protected resource metadata (RFC 9728): `https://mcp.dev.iqub.io/.well-known/oauth-protected-resource/mcp`
- Authorization server: `https://app.dev.iqub.io`
- Authorization server metadata (RFC 8414): `https://app.dev.iqub.io/.well-known/oauth-authorization-server`
- Identity endpoint: `https://app.dev.iqub.io/oauth/agent/identity`
- Token endpoint: `https://app.dev.iqub.io/oauth/token`
- Revocation endpoint (RFC 7009): `https://app.dev.iqub.io/oauth/revoke`
- Scopes: `tools`

## Registration methods

| Method | Offered | Error when not offered |
| --- | --- | --- |
| `service_auth` | yes — email plus a claim ceremony the person completes on the Portal | `service_auth_not_enabled` in environments where registration is off |
| `identity_assertion` | not yet | `identity_assertion_not_enabled` |
| `anonymous` | not yet | `anonymous_not_enabled` |

The authorization server metadata carries an `agent_auth` block only where
`service_auth` registration is enabled. Read it before registering; the block's
`identity_endpoint` is authoritative.
## service_auth in five steps

1. Register. `POST https://app.dev.iqub.io/oauth/agent/identity` with JSON
   `{"type": "service_auth", "login_hint": "<the person's email>", "client_name": "<your name>"}`.
   The response carries `registration_id`, `client_id`, `claim_token`,
   `claim_token_expires`, and a `claim` object with `user_code`, `verification_uri`,
   `verification_uri_complete`, `expires_in` and `interval`.
2. Show the person `user_code` and `verification_uri` (or open
   `verification_uri_complete`). They sign in to iQub, type the code, and choose the
   workspace, consumption plan and permissions the delegation carries. The workspace
   starts as the one their iQub session is in and can be switched on the claim page,
   and is named again on the confirmation step. The claim token is yours alone: never
   place it in a URL or show it to the person.
3. Poll. `POST https://app.dev.iqub.io/oauth/token` with form fields
   `grant_type=urn:workos:agent-auth:grant-type:claim&claim_token=<claim_token>`, no more
   often than `interval` seconds. `authorization_pending` means keep polling;
   `slow_down` means the interval grew, back off; `expired_token` means the window
   closed, register again.
4. Use the grant. Success is a standard token response with `access_token`,
   `refresh_token`, `expires_in`, `scope` and `client_id`. Present the access token as
   `Authorization: Bearer` on `https://mcp.dev.iqub.io/mcp`. It is bound to that resource and to the
   workspace, mode and permissions the person chose.
5. Refresh and revoke. Refresh with `grant_type=refresh_token`, `refresh_token` and the
   `client_id` from step 4. Revoke with `POST https://app.dev.iqub.io/oauth/revoke` and `token=<refresh_token>`.
   The person can also disconnect you from the Portal at any time.

A claim token is single-use. Presenting it again after a grant was minted revokes that
grant, exactly as replaying an authorization code would.

## Also available

The browser flow is unchanged: `authorization_code` with PKCE at
`https://app.dev.iqub.io/oauth/authorize`, with RFC 7591 dynamic client registration and
client ID metadata documents. Use it when your client already has a browser in the
loop; use auth.md when it only has the person's email.

## Limits

The identity endpoint and the claim grant are anonymous and rate limited per issuer.
A refusal is an OAuth error document with `error: temporarily_unavailable` and a
`Retry-After` header.
