# auth.md — how agents register and authenticate with Collectly

Collectly is a free collection tracker for physical collectibles: collections, the
items inside them, and the collectors who own them. This document tells an AI
agent, assistant or MCP client how to connect, what it may do, and how to get
credentials if it needs them.

Machine-readable discovery documents for this service:

| Document | URL |
| --- | --- |
| OAuth Protected Resource Metadata (this service) | https://collectly.xyz/.well-known/oauth-protected-resource |
| Authorization server metadata | https://app.base44.com/.well-known/oauth-authorization-server |
| API catalog (RFC 9727) | https://collectly.xyz/.well-known/api-catalog |
| OpenAPI description | https://collectly.xyz/functions/openapi |
| MCP server | https://collectly.xyz/api/mcp |

## Audience

This service is for agents that help people browse, organise or research
collectibles. Typical uses: reading a collector's public catalogue, answering
questions about a specific item, and summarising new blog posts.

## Access modes

Collectly has two access modes. Start with the first one; only move to the second
when the task genuinely needs a signed-in collector's private data or an action
on their behalf.

### 1. Anonymous — no registration, no credentials

Public collections, public items, opt-in collector profiles and the blog are
readable without any account. This is the right mode for discovery, browsing and
answering questions about content that is already public.

- MCP server: `https://collectly.xyz/api/mcp`
- Public catalogue API: `https://collectly.xyz/functions/publicCatalog`
- Any public page as markdown: `https://collectly.xyz/functions/markdownPage?path=/browse`
- Blog feed: `https://collectly.xyz/functions/blogFeed`

Nothing is registered and nothing is stored. There is no sign-up step, so there
is no credential to manage and nothing to revoke. Content that a collector has
marked private is never returned in this mode, whatever the agent asks for.

### 2. Acting for a signed-in collector — OAuth 2.1

To act as a Collectly user (reading their private collections, or taking an
action their account is permitted to take), the agent authorises against
Collectly's authorization server and calls the MCP server with the resulting
token. The collector signs in on Collectly and approves the request on the
consent page; the agent never sees their password.

Authorization server: `https://app.base44.com`
Issuer (must match the value in the authorization server metadata): `https://app.base44.com`

## Registration

Agents register themselves as OAuth clients with **dynamic client registration**
(RFC 7591). No human provisioning, invitation or API key is involved, and no
account is created on Collectly by registering.

- Registration endpoint: `https://app.base44.com/oauth/register`
- Method: `POST`, JSON body
- Client authentication: `none` (public client — use PKCE)
- Requested scope: `app:mcp`

Example:

```http
POST https://app.base44.com/oauth/register
Content-Type: application/json

{
  "client_name": "Example agent",
  "redirect_uris": ["http://127.0.0.1/callback"],
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"],
  "token_endpoint_auth_method": "none"
}
```

The response carries a `client_id` to use in the authorization request below.

## Supported methods

| Method | Endpoint | Notes |
| --- | --- | --- |
| Anonymous access | `https://collectly.xyz/api/mcp` | Public, read-only data. No credentials. |
| Dynamic client registration | `https://app.base44.com/oauth/register` | RFC 7591. Returns a `client_id`. |
| Authorization code + PKCE | `https://app.base44.com/oauth/authorize` | `code_challenge_method` must be `S256`. |
| Refresh token | `https://app.base44.com/oauth/token` | Keeps a long-running agent connected. |
| Device authorization | `https://app.base44.com/oauth/device/code` | For agents with no browser. |
| Userinfo | `https://app.base44.com/oauth/userinfo` | Identifies the signed-in collector. |

## Using credentials

Tokens are bearer tokens. Send them in the `Authorization` header on every
request to the MCP server:

```http
GET https://collectly.xyz/api/mcp
Authorization: Bearer <access_token>
Accept: text/event-stream
```

- Use the token only against Collectly and the endpoints above.
- Never log it, embed it in a page, or forward it to another service.
- Refresh it with the refresh token when it expires; if a refresh fails, run the
  authorization flow again.
- The collector can withdraw access at any time from their Collectly account. A
  withdrawn or expired token returns `401`; re-authorise rather than retrying.
- Anonymous mode needs no header at all — send none rather than an empty one.

## Limits

Access follows the permissions of the collector who authorised it, and private
content stays private in anonymous mode. All read endpoints are rate limited, so
agents should cache what they fetch and back off on `429`.
