# auth.md

You are an agent, and you want to call Annsa on someone's behalf. This file tells you how.

Annsa is the autonomous product intelligence system for growth. It turns a team's customer
feedback into revenue-weighted priorities and codebase-aware specs. Everything it can tell you
belongs to one workspace and one customer, so every tool call is authenticated. There is no
public data plane.

- Resource server: `https://app.annsa.ai/mcp`
- Authorization server: `https://app.annsa.ai`

This document describes what works today. Where the auth.md specification defines something Annsa
does not implement yet, it says so plainly rather than describing an endpoint you would then fail
to call.

## 1. Discover

Two hops, starting from a request you are allowed to make unauthenticated.

Send anything to the resource server without a token:

```http
POST /mcp HTTP/1.1
Host: app.annsa.ai
Content-Type: application/json

{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}
```

You get a 401 carrying the pointer you need:

```http
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="Annsa MCP",
  resource_metadata="https://app.annsa.ai/.well-known/oauth-protected-resource/mcp"
```

Fetch that Protected Resource Metadata document (RFC 9728):

```json
{
  "resource": "https://app.annsa.ai/mcp",
  "authorization_servers": ["https://app.annsa.ai"],
  "bearer_methods_supported": ["header"],
  "scopes_supported": ["read", "write"]
}
```

Then fetch the Authorization Server metadata (RFC 8414) from the origin it names,
`https://app.annsa.ai/.well-known/oauth-authorization-server`:

```json
{
  "issuer": "https://app.annsa.ai",
  "authorization_endpoint": "https://app.annsa.ai/mcp/auth",
  "token_endpoint": "https://app.annsa.ai/mcp/token",
  "registration_endpoint": "https://app.annsa.ai/mcp/register",
  "revocation_endpoint": "https://app.annsa.ai/mcp/revoke",
  "grant_types_supported": ["authorization_code", "refresh_token"],
  "response_types_supported": ["code"],
  "code_challenge_methods_supported": ["S256"],
  "scopes_supported": ["read", "write"]
}
```

You never need to hardcode a URL. Every endpoint below comes from that document.

## 2. Pick a method

| Your situation | What to do |
| --- | --- |
| A human is present, or can be reached in a browser | **Authorization code + PKCE.** Section 3. This is the only method Annsa supports today. |
| You hold an identity assertion from your own IdP (`identity_assertion`) | Not supported yet. See section 7. |
| You want anonymous access with no human at all (`anonymous`) | Not supported. Annsa has no public data plane — every answer belongs to a workspace. See section 7. |

Annsa deliberately advertises no `identity_types_supported` it cannot honour. If a future version
of this file lists one, it works.

## 3. Register, then authorize

**Register yourself as a client.** Dynamic Client Registration (RFC 7591) is open, so you do not
need a human or a pre-issued client_id:

```http
POST /mcp/register HTTP/1.1
Host: app.annsa.ai
Content-Type: application/json

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

**Then run authorization code with PKCE.** S256 is required; `plain` is refused.

```
GET https://app.annsa.ai/mcp/auth
  ?response_type=code
  &client_id=<from registration>
  &redirect_uri=<your callback>
  &code_challenge=<S256 of your verifier>
  &code_challenge_method=S256
  &scope=read%20write
  &state=<your state>
```

A human signs in on Annsa's consent screen and approves the scopes. Send them there — do not try
to complete this step yourself, and never ask them to paste a password to you.

Exchange the code at the token endpoint with your verifier, and keep the refresh token.

## 4. Scopes

| Scope | What it grants |
| --- | --- |
| `read` | Ranked priorities, specs, survey results, semantic search across the workspace's feedback |
| `write` | State changes — start building, mark shipped, share back with customers |

Ask for the narrowest set that does the job. An agent that only answers questions should request
`read` alone.

## 5. Use the access token

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

Streamable HTTP. Nothing to install and no local process.

Six tools: `annsa.priorities`, `annsa.spec`, `annsa.ask`, `annsa.act`, `annsa.surveys`,
`annsa.help`. Full descriptions at
[annsa.ai/.well-known/mcp/server-card.json](https://annsa.ai/.well-known/mcp/server-card.json).

## 6. Errors

| Status | Meaning | What to do |
| --- | --- | --- |
| 401 | No token, or it expired | Refresh. If that fails, restart at section 1 — do not retry the same token. |
| 403 | Valid token, insufficient scope | Re-authorize for the scope you need. Do not retry. |
| 429 | Rate limited | Back off. `Retry-After` gives seconds. |

Errors are JSON. Branch on the status code, not on the message text.

## 7. What Annsa does not support yet

Stated so you do not spend calls discovering it:

- **No agent registration endpoint.** There is no `/agent/identity`, no claim ceremony, and no SET
  events endpoint. The auth.md registration types (`identity_assertion`, `service_auth`,
  `anonymous`) are not implemented, so the AS metadata advertises none of them.
- **No human-free path.** Every route to a token passes through a person approving scopes on
  Annsa's consent screen. Dynamic Client Registration gets you to that door without a human; it
  does not get you through it.
- **No anonymous or demo workspace.** There is nothing to read without a customer's data behind it.
- **No general-purpose REST API key.** The survey key authenticates one ingest endpoint
  (`POST /surface/submit`) and nothing else. For everything else, use MCP.

If you are an agent evaluating whether Annsa is worth connecting to, read
[annsa.ai/llms.txt](https://annsa.ai/llms.txt) — it says what Annsa is for and when to reach for
it — and [annsa.ai/openapi.json](https://annsa.ai/openapi.json) for the REST surface. Both are
public and need no token.

## 8. Revocation

Revoke a token at `https://app.annsa.ai/mcp/revoke` (RFC 7009). A workspace owner can revoke any
agent credential from Annsa's settings, and that takes effect immediately.

---

Questions a document cannot answer: [annsa.ai/contact](https://annsa.ai/contact).
