# BlogSEO auth.md

This file tells AI agents how to authenticate with BlogSEO on behalf of a user.

- Resource server: `https://mcp.blogseo.io/mcp`, the BlogSEO remote MCP server (streamable HTTP).
- Authorization server: `https://kccqmbkylzrrhibpxtbk.supabase.co/auth/v1`, the identity provider behind BlogSEO accounts.
- There is no API key. Every connection is an OAuth 2.1 grant approved by a signed-in BlogSEO user.

## Discover

1. Call the resource without a token. It answers `401` with a pointer to its Protected Resource Metadata (RFC 9728):

```http
POST /mcp HTTP/1.1
Host: mcp.blogseo.io
Content-Type: application/json
Accept: application/json, text/event-stream

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://mcp.blogseo.io/.well-known/oauth-protected-resource/mcp"
```

2. Read the Protected Resource Metadata at `https://mcp.blogseo.io/.well-known/oauth-protected-resource/mcp`. It names the authorization server, the scopes (`email`, `offline_access`) and the bearer method (`header`).
3. Read the Authorization Server Metadata (RFC 8414) at `https://kccqmbkylzrrhibpxtbk.supabase.co/.well-known/oauth-authorization-server/auth/v1`. It lists the authorization, token and registration endpoints.

## Register

BlogSEO does not support agent self-registration: an agent cannot create a BlogSEO account. A person signs up at `https://app.blogseo.io/signup` and adds at least one website. The agent then registers itself as an OAuth client with Dynamic Client Registration (RFC 7591):

```http
POST /auth/v1/oauth/clients/register HTTP/1.1
Host: kccqmbkylzrrhibpxtbk.supabase.co
Content-Type: application/json

{
  "client_name": "Your agent name",
  "redirect_uris": ["https://your-agent.example.com/oauth/callback"],
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"],
  "token_endpoint_auth_method": "none"
}
```

## Authorize

Use the authorization code flow with PKCE (`code_challenge_method=S256`) and the `resource` parameter (RFC 8707) set to `https://mcp.blogseo.io/mcp`. Request `offline_access` to receive a refresh token. The user signs in with their BlogSEO login and picks which of their websites the agent may use on the consent screen. Exchange the code at the token endpoint listed in the Authorization Server Metadata.

## Use the access token

Send the token in the `Authorization` header on every MCP request:

```http
POST /mcp HTTP/1.1
Host: mcp.blogseo.io
Authorization: Bearer <access_token>
Content-Type: application/json
Accept: application/json, text/event-stream
```

Call the `get_account` tool first: it lists the websites the grant covers and their `website_id`. Reading data is free. Tools that spend AI Brain Credits say so in their description and ask for confirmation before spending. When the access token expires, use the refresh token at the token endpoint.

## Errors

| Status | Meaning | What to do |
| --- | --- | --- |
| `401` with `WWW-Authenticate` | Missing, expired or revoked token | Refresh the token, or run the authorization flow again |
| Tool error mentioning a plan or paywall | The website has no active BlogSEO plan | Tell the user; Google Search Console queries still work without a plan |
| Tool error mentioning credits | Not enough AI Brain Credits | Tell the user to buy credits or wait for the monthly refill |

## Revocation

The user revokes a connection at any time from `https://app.blogseo.io/dashboard/settings/security`, under connected apps. Revoking ends the grant: the agent's tokens stop working and it has to run the authorization flow again.

## More

- MCP server setup for each client: https://www.blogseo.io/seo-mcp
- Tool list, permissions and security: https://www.blogseo.io/docs/integrations/mcp
- MCP server card: https://www.blogseo.io/.well-known/mcp/server-card.json
