# Authentication & permissions

The two ways to connect (delegated OAuth and named tokens), what each scope grants, how project reach works, and how to revoke — with least privilege throughout.

Semel has exactly **two** authentication modes and no third. Interactive, OAuth-capable harnesses use delegated OAuth with PKCE; unattended or OAuth-incapable agents use an owner-created **named token**. Both resolve to an accountable agent principal tied to a human — and authentication **never** approves a human gate.

## Two ways to connect
<a id="two-modes"></a>

**Delegated OAuth (authorization code + PKCE)** — for interactive harnesses such as Claude Code and Codex. The client registers dynamically, opens the Semel browser consent screen, and owns rotating-token storage and refresh. The model never sees the token.

**Named token** — for unattended or OAuth-incapable agents. A workspace owner creates a show-once token scoped to specific permissions and project reach. Supply it through an environment variable, OS credential store, or native secret reference — never in chat, source control, logs, checkpoints, or documentation. There is no password, API-key paste, or third authentication mode.

**Named token — env var only**

```bash
# Provide a named token to an unattended agent via the environment.
# Never paste a token into chat, commit it, or log it.
export SEMEL_MCP_TOKEN="$(op read op://vault/semel/token)"   # from a credential store
```

## Interactive client commands
<a id="interactive-commands"></a>

**Claude Code**

```bash
claude mcp add --transport http --scope user semel https://mcp.semel.ai/mcp
claude mcp login semel
claude mcp get semel
```

**Codex**

```bash
codex mcp add semel --url https://mcp.semel.ai/mcp --oauth-resource https://mcp.semel.ai/mcp
codex mcp login semel --scopes brief:read,brief:write
codex mcp get semel
```

These forms match the current client CLIs. After login, reload the model session and verify live `initialize`, Semel `serverInfo`, and non-empty `tools/list`. A stored configuration or an OAuth label does not establish readiness.

## Scopes
<a id="scopes"></a>

`brief:read` is the floor every tool requires and is implied by every other scope. Grant only what an agent needs:

| Scope | What it grants |
| --- | --- |
| `brief:read` | Read briefs, projects, and review state. The floor every tool requires. |
| `brief:write` | Create and edit brief and project content. |
| `review:run` | Start and observe hosted AI review passes (the review lifecycle). |
| `review:configure` | Configure how the AI reviewer cascade runs for a project. |
| `review:execute` | Execute an external review session: claim it, submit checkpoints, answer durable questions, and submit a result. Deliberately narrow — never implies brief:write, review:configure, or gate approval. |

Scopes compose; they do not imply one another except that every MCP operation also requires `brief:read`. `review:execute` drives an already-originated local session but does not imply `review:run`, `brief:write`, or human authority. `review:configure` is reserved and no current registry tool requires it. Request the smallest journey set: read-only uses `brief:read`; brief/project authoring adds `brief:write`; review origination adds `review:run`; local driving adds `review:execute`.

## Actions a scope can never grant
<a id="human-actions"></a>

No agent scope can approve or reject a gate; decide, commit, rebase, or revert a proposal; mint or approve an execution grant; clear or destructively restart a review; administer workspace membership or credentials; change billing or spend; connect Slack, GitHub, or a tracker; accept BYOK or model-provider consent; create public share links; write to Brain; perform Done Check; or invoke `/runs/:id/continue`. Delegated consent and named-token creation/revocation are human actions. `project_codebase_link` only links a repository already connected by a human.

## The MCP endpoint
<a id="endpoint"></a>

Point your harness at the stable production MCP endpoint. The same URL is the OAuth resource identifier and token audience:

**Production MCP endpoint:** `https://mcp.semel.ai/mcp`

## Workspace & project reach
<a id="reach"></a>

Every request is scoped to one workspace. Within it, a principal reaches **all** projects (current and future) or an explicit **allowlist**. An allowlisted principal is pinned to its set and can never widen its own reach — including by creating a project. A request for a project outside its reach fails with `PROJECT_ACCESS_DENIED` and no cross-project expansion.

## Revocation & reauthorization
<a id="revocation"></a>

A workspace owner can revoke a named token or connected-app grant at any time; Semel’s local authorization ledger blocks the next request even if provider revocation lags. On terminal OAuth states such as `invalid_grant`, stop concurrent clients sharing the credential, perform one harness-native login, reload the session, and recheck live tools. Preserve credentials through timeouts, rate limits, network errors, and 5xx responses. A named token is rotated by a human: mint the replacement, move the secret reference, verify it, then revoke the old token.

## Authentication never approves a human gate
<a id="never-a-gate"></a>

> **Caution:** Connecting an agent establishes an accountable principal and a human who answers for it. It does **not** approve a human gate, substitute for a review-execution grant, or permit deletion of data. Those remain explicit, separate human actions.

Canonical page: https://docs.semel.ai/authentication
