# Agent authentication for MultiGroupPoster

How an AI client gets access to MultiGroupPoster, and which credentials exist. This file follows the section layout of the auth.md convention (https://github.com/workos/auth.md). It describes what MultiGroupPoster implements today (checked 28 October 2026) and what it does not.

MultiGroupPoster is a Chrome extension that posts to Facebook groups from the person's own browser. There are two machine surfaces:

- The public website and its read-only info API (`https://multiplegroupposter.com/api/v1/`, described in `/openapi.json`). No credential at all.
- The MCP server at `https://mcp.multiplegroupposter.com/mcp`, which acts for one person. It needs an OAuth access token, and the person has to approve the connection in their own extension.

## Discover

- `GET https://mcp.multiplegroupposter.com/mcp` without a token returns `401` with `WWW-Authenticate: Bearer resource_metadata="https://mcp.multiplegroupposter.com/.well-known/oauth-protected-resource"`.
- Protected resource metadata (RFC 9728): `https://mcp.multiplegroupposter.com/.well-known/oauth-protected-resource`. It names the authorization server `https://mcp.multiplegroupposter.com` and the scopes `mgp` and `offline_access`.
- Authorization server metadata (RFC 8414): `https://mcp.multiplegroupposter.com/.well-known/oauth-authorization-server` (the same document is served at `/.well-known/openid-configuration`). Endpoints: `/authorize`, `/token`, `/register`.
- Server card: `https://mcp.multiplegroupposter.com/mcp/server-card`. Catalog: `https://multiplegroupposter.com/.well-known/ard.json`.

## Pick a method

- No credential: everything on multiplegroupposter.com, including `/api/v1/pricing/`, `/api/v1/limits/`, `/api/v1/docs/?q=` and `/api/v1/mcp/`. Start here for questions about prices, limits and how the product works.
- OAuth 2.1 authorization code with PKCE (S256), public client (`token_endpoint_auth_method: none`): the only way to use the MCP server. The token is bound to one person's MultiGroupPoster extension.
- There are no API keys, no client credentials grant and no service accounts. An agent cannot act for a person without that person's approval in their own browser.

## Register

Two ways, both automatic:

- Client ID metadata document: use an `https` URL that serves your client metadata as the `client_id`. Supported (`client_id_metadata_document_supported: true`).
- Dynamic client registration (RFC 7591): `POST https://mcp.multiplegroupposter.com/register` with `redirect_uris` (https, or http on a loopback address for local apps) and an optional `client_name`. The response holds a `client_id`. Limit: 30 registrations per IP address per hour.

## Claim

This is the step that needs the person. After you send them to `/authorize` (with `response_type=code`, `code_challenge`, `code_challenge_method=S256`, `redirect_uri`, `client_id`, `state`):

1. The sign-in page asks for an 8-digit code. The person gets it in the extension: Help, then Connect an AI assistant, then Get my code. A code is valid for 20 minutes.
2. The sign-in page shows a 2-digit number. The extension shows three numbers and the person picks the matching one, or Deny. One try: a wrong pick denies the request.
3. The browser is redirected to your `redirect_uri` with `code`, `state` and `iss`.

For testing without an extension, the sign-in page has "Try a demo account": two sample group lists, jobs are simulated and nothing reaches Facebook. Demo accounts are deleted after 3 days.

## Exchange

`POST https://mcp.multiplegroupposter.com/token` (form encoded):

- `grant_type=authorization_code` with `code`, `redirect_uri`, `code_verifier` and `client_id`.
- `grant_type=refresh_token` with `refresh_token` and `client_id`. Refresh tokens last 180 days and renew with use; a rotated token stays valid for a 2-minute grace period so a retry does not lock you out.

The response is `{access_token, token_type: "Bearer", expires_in: 3600, refresh_token, scope}`. Access tokens last 1 hour.

## Use the access_token

Send it on every MCP request:

```
POST https://mcp.multiplegroupposter.com/mcp
Authorization: Bearer <access_token>
Content-Type: application/json
Accept: application/json, text/event-stream
```

The server is stateless Streamable HTTP. Call `get_started` first: it tells you whether the person's Chrome is open, whether they are signed in, their plan and lists, and the next step. Posts are drafts by default; `create_post` with `mode: "publish_now"` needs `confirmed: true`, which you may only send after the person said yes to a summary. See https://multiplegroupposter.com/docs/mcp/.

## Errors

- `401 {"error":"invalid_token"}` with `WWW-Authenticate`: missing, expired or revoked token. Refresh, or start the authorization again.
- `400 {"error":"invalid_grant"}`: wrong, used or expired code, wrong redirect URI or a failed PKCE check (`error_description: "PKCE"`).
- `400 {"error":"invalid_redirect_uri"}` or `{"error":"invalid_client_metadata"}` at registration.
- `400 {"error":"unsupported_grant_type"}` at the token endpoint.
- `429 {"error":"slow_down"}`: too many registrations from one address. Wrong codes on the sign-in page are limited to 10 per IP address per 15 minutes.
- Tool errors are MCP results with `isError: true` and `{"error": "...", "next_step": "..."}`. Follow `next_step`; never repeat `create_post` after an unclear error without calling `list_recent_posts` first.

## Revocation

There is no RFC 7009 revocation endpoint and no `agent_auth` events endpoint. The person revokes access in the extension: Help, Connect an AI assistant, Disconnect. That removes every token for their extension and deletes the jobs and media the server kept for it. After that, calls return `401`. Questions: support@multiplegroupposter.com.
