> ## Documentation Index
> Fetch the complete documentation index at: https://rapidreview.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Authentication

> How clients sign in to the hosted brain, what a grant reaches, how long it lasts, and the few cases that still need a project key.

Browser OAuth for every native client. Project keys only for machines without a browser.

## OAuth

```mermaid theme={"theme":{"light":"github-light","dark":"dark-plus"}}
flowchart TB
    A[Client calls POST /mcp with no credential] --> B[401 + discovery metadata]
    B --> C[Dynamic client registration]
    C --> D[Browser: sign in with your RapidReview account, choose scope]
    D --> E[PKCE code exchange → access token 1 h, refresh 30 d]
    E --> F[Client stores and refreshes; you never see a key]
```

The manifests ship a URL and nothing else. Accounts are RapidReview accounts (email/password or Google).

| Fact               | Value                                                                                                                                         |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------- |
| Access token       | 1 hour, audience-confined to `/mcp` — anywhere else answers `403 credential_audience_forbidden`                                               |
| Refresh token      | 30 days, rolling                                                                                                                              |
| Authorization code | 60 seconds                                                                                                                                    |
| OAuth scopes       | Not supported — a client that registers one gets `invalid_client_metadata`; the **grant scope** below is chosen on the consent screen instead |

### What the grant reaches

| Grant                         | Reach                                                                                   |
| ----------------------------- | --------------------------------------------------------------------------------------- |
| **All my projects** (default) | Every project you're a member of; the agent discovers ids with `project(action="list")` |
| **One project**               | Exactly that project; any other `project_id` is rejected                                |

Every rotation inherits the grant. Membership is the authorization boundary — you only ever see projects you're a member of. Members: [Configure auth → Project members](/docs/merv/self-host/configure-auth#what-a-verified-credential-can-do).

### Remote machines over SSH

Consent redirects to a loopback URL on the machine running the client — Kilo Code and OpenCode listen on `127.0.0.1:19876` during `mcp auth merv`. If that machine is a VM and the browser is your laptop, the redirect lands on the laptop and the client times out after five minutes.

<Note>
  On a remote machine over SSH, connect with `ssh -L 19876:127.0.0.1:19876 user@host` first. The browser sign-in callback goes to `127.0.0.1:19876`, and the forward is what lets it reach the client running on the remote host.
</Note>

Sign in inside that SSH session and approve in the laptop's browser; refresh needs no tunnel. If `ssh` can't bind 19876, another sign-in on the laptop holds it. Same technique for any client with a loopback redirect.

## Project keys

Mint one only when there is no browser and no way to forward the callback port: scripted [Auto-run](/docs/merv/guides/auto-run) installs and CI, containers, a client without MCP OAuth (OpenHands headless), direct `curl`.

**Settings → MCP keys** in the project → create → choose **All my projects** unless you want confinement → expose as `MERV_MCP_KEY`. Treat it as a password; never in shell history, logs, or committed files — native clients don't need one, and the manifests are URL-only on purpose. `merv-client env` prints the header-based MCP snippet for a headless client.

## Local brain

Auth-free: every request is the implicit local principal and the UI skips sign-in. [Self-host](/docs/merv/self-host/overview)
