MCP clients discover your authorization server through OAuth 2.1 metadata and RFC 9728 protected-resource documents. Authdog hosts the issuer per environment so you can protect MCP tool servers without building login UI.

## Flow

1. The MCP client calls your resource without a token.
2. The resource responds with **401** and `WWW-Authenticate` pointing at protected-resource metadata.
3. The client loads metadata, starts authorize with **PKCE (S256)**, and optionally sends a **resource** indicator (RFC 8707).
4. After consent, the client exchanges the code at the token endpoint and calls tools with the access token.

```text
Client --(no token)--> MCP resource
MCP resource --401 + resource_metadata--> Client
Client --authorize + PKCE--> Authdog (hosted consent)
Client --token--> Authdog
Client --Bearer token--> MCP resource
```

## Environment settings

In the console, open **MCP Auth → Settings** for your MCP project environment:

- **Enable MCP Auth** turns on default-resource and strict-resource behavior for that issuer.
- **Default resource** is applied when clients omit the `resource` parameter.
- **Strict resource mode** rejects authorize and token requests that omit `resource` when no default is configured.

Dynamic client registration and client-ID metadata (CIMD) toggles are stored per environment. When **MCP Auth** is enabled, the issuer registration endpoint honors **DCR** and **CIMD** toggles; CIMD clients use an `https` metadata URL as `client_id`.

## Resource server integration

Use `@authdog/mcp-sdk` from the Authdog monorepo (`packages/mcp-sdk`). The `AuthdogMcpAuthProvider` class wraps token validation for Workers or Node MCP servers:

```typescript
import { AuthdogMcpAuthProvider } from "@authdog/mcp-sdk"

const auth = new AuthdogMcpAuthProvider({
  env: {
    AUTHDOG_OIDC_ISSUER: process.env.AUTHDOG_OIDC_ISSUER!,
    MCP_PROTECTED_RESOURCE: process.env.MCP_PROTECTED_RESOURCE!,
    MCP_REQUIRED_SCOPES: "mcp:invoke",
  },
})

const result = await auth.validateAccessToken(request.headers.get("authorization"))
```

See [MCP security](/guides/mcp-security) and the [console MCP module](/docs/console/mcp).

## Enterprise SSO and MCP OAuth

MCP OAuth uses the **same environment issuer** as hosted sign-in and enterprise
connections. There is no separate MCP-only SAML or OIDC stack: when **Enterprise
SSO** is enabled for an environment, users signing in to MCP clients through
Authdog follow the same IdP routing, MFA, and session policies as the account
portal.

SCIM or HRIS **deprovisioning** (or deactivating a user in the console) revokes
Connected Apps consents and invalidates outstanding OIDC access and refresh
tokens for that user in the environment, so MCP clients cannot refresh after
directory removal.

## Audit and SIEM

Enable **`MCP_TELEMETRY=true`** on your MCP server (or hosted gateway) with an
environment API secret (`adenv_`). The SDK sends runtime events to
`POST https://api.authdog.com/v1/mcp/events`. They appear in **Audit** under category
`mcp_runtime` and in **Agents → Activity** for MCP projects.

When AuthZEN or the trust store denies a tool, the runtime records
**`MCP_TOOL_DENIED`** with `decision: deny` and a reason code (for example
`tool_not_allowed`). Subscribe to `MCP_TOOL_DENIED` and related types in
**Notifications → Channels** after you confirm them in **Audit → Event Types**.

Authdog indexes events for console search; **long-term retention is your SIEM or
webhook destination**. See [Audit logs](/guides/audit-logs) and
[SIEM security events](/guides/siem-security-events). Payload fields use snake_case
inside `event_payload` (`tool_name`, `decision`, `reason`, `server_id`, …); raw tool
arguments are never stored.

For how OAuth-only MCP compares to trust store, AuthZEN, and audit, see
[MCP OAuth vs platform stack](/docs/mcp-oauth-vs-platform).

## Related

- [Machine identity](/docs/machine-identity)
- [Agent sign-in](/docs/agent-sign-in)
- [Authentication](/docs/authentication)
