> For the complete documentation index, see [llms.txt](https://docs.flowcp.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.flowcp.ai/guides/agent-auth-discovery.md).

# Agent authentication discovery (auth.md)

Any MCP server you publish on FlowCP can advertise how an AI agent can authenticate to it using [**auth.md**](https://github.com/workos/auth.md) — an open protocol that lets agents discover a service's authentication flows on behalf of a user. Discovery is built entirely on the OAuth standards FlowCP already implements.

Agent auth is **opt-in per server** and off by default, in keeping with FlowCP's default-deny model. Turn it on from the server's **Publish** page with the **Agent Auth (auth.md)** toggle. While it is off, FlowCP publishes no auth.md document and emits no `agent_auth` block — discovery stays silent.

***

## Enabling agent auth

1. Publish the server (the toggle appears once the server is live).
2. On the **Publish** page, switch on **Agent Auth (auth.md)**.
3. FlowCP shows the server's `auth.md` URL to copy and immediately begins advertising the discovery artifacts below. Toggle it off at any time to stop.

***

## What gets published

When agent auth is enabled for a server at `https://<runtime>/mcp/<serverId>`, FlowCP serves:

| Artifact                                 | URL                                                                     |
| ---------------------------------------- | ----------------------------------------------------------------------- |
| auth.md file                             | `https://<runtime>/mcp/<serverId>/auth.md`                              |
| Protected Resource Metadata (RFC 9728)   | `https://<runtime>/.well-known/oauth-protected-resource/mcp/<serverId>` |
| Authorization Server Metadata (RFC 8414) | `https://<api>/.well-known/oauth-authorization-server/mcp/<serverId>`   |

The **auth.md file** is a short Markdown document that doubles as human documentation and a machine-readable runtime artifact. It lists the server's resource URL, OAuth endpoints, requested scopes, and enabled tools.

The machine source of truth is the `agent_auth` block carried in the Protected Resource Metadata (and mirrored into the Authorization Server Metadata). It advertises `skill` (the auth.md URL), the registration endpoints (`register_uri`, `claim_uri`, `revocation_uri`), and the supported identity, assertion, and credential types.

***

## The discovery chain

An agent reaches a server's auth.md the same way any MCP client discovers auth:

1. The agent calls `/mcp/<serverId>` and receives `401` with a `WWW-Authenticate: Bearer resource_metadata="…"` header.
2. It fetches the **Protected Resource Metadata**, which names the authorization server and carries the `agent_auth` block.
3. It follows `agent_auth.skill` to read `/mcp/<serverId>/auth.md`.

From there the agent authenticates with the standard OAuth 2.0 authorization-code flow (with PKCE) — exactly the [user-context OAuth](/security/user-context-oauth.md) FlowCP enforces on every call. See [Configure OAuth](/guides/configure-oauth.md) to set up the provider.

***

## Registration flows

Beyond discovery, FlowCP implements both auth.md agent-registration flows. The `agent_auth` block advertises only the flows that are actually live for a server, so an agent is never pointed at a flow that would fail:

| Identity type        | Flow                                                  | Advertised when                                                   |
| -------------------- | ----------------------------------------------------- | ----------------------------------------------------------------- |
| `anonymous`          | **User claimed** — device-style claim ceremony        | The server uses `user_oauth` mode with an OAuth config assigned   |
| `identity_assertion` | **Agent verified** — ID-JAG signed identity assertion | The workspace has at least one [trusted issuer](#trusted-issuers) |

### User claimed (`anonymous`)

A device-authorization-style ceremony for agents that have no registration of their own:

1. The agent `POST`s to `agent_auth.claim_uri` (`/oauth/agent/claim`) with a PKCE `code_challenge` and the server's `resource` URL. It receives a `device_code`, a human-readable `user_code` (`XXXX-XXXX`), a `verification_uri`, and a polling `interval`.
2. The agent shows the code to its user, who signs in to the FlowCP dashboard, opens the **Claim** page, enters the code, and reviews the consent card (which agent, which server). See [Claim an agent](/guides/claim-an-agent.md).
3. Approving routes the user through the app's **standard OAuth sign-in** — the same [user-context OAuth](/security/user-context-oauth.md) as every other flow — so the agent only ever acts in that user's authorization context.
4. The agent polls the token endpoint with `grant_type=urn:ietf:params:oauth:grant-type:device_code` (receiving `authorization_pending` / `slow_down` until the user finishes) and redeems the result with its PKCE `code_verifier`. The tokens it receives are exactly what the standard authorization-code flow would have produced.

### Agent verified (`identity_assertion`)

Agents that hold a signed JWT identity assertion (an **ID-JAG**, `urn:ietf:params:oauth:token-type:id-jag`) from an identity provider you trust can register directly:

1. The agent `POST`s to `agent_auth.register_uri` (`/oauth/agent/register`) with `identity_type=identity_assertion`, the assertion, and the server's `resource` URL.
2. FlowCP verifies the assertion strictly — signature against the issuer's JWKS, exact issuer and audience, expiry, single-use `jti`, and an optional per-issuer subject allowlist — and returns an RFC 7591-style client registration carrying the verified identity.
3. Registration establishes **identity, never access**: the registered client still obtains credentials through the standard authorization-code flow or the user-claimed ceremony above.

Every verification failure returns one generic `invalid_assertion` error, so the endpoint cannot be used to probe configuration.

### Trusted issuers

Configure trusted issuers per workspace under **Settings → Workspace → Trusted agent issuers**: a display name, the issuer URL (exact `iss` match), and its JWKS URL (both must be `https`). Optionally restrict which `sub` values may register. While the list is empty, `identity_assertion` is not advertised and agent-verified registration is refused.
