> 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>`   |

`<serverId>` is whichever identifier the agent connected with — the server's friendly slug or its internal id. Each artifact is served under both, and the URLs inside it echo the one that was used, so an agent that validates the advertised resource against the URL it connected to sees a consistent chain either way.

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.
