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

# Authentication

> OAuth and bearer tokens for MCP client connections

## OAuth (automatic)

For HTTP servers without a bearer token, the client provisions an OAuth provider
automatically. A server that protects the whole MCP endpoint starts OAuth during
connection:

```typescript theme={null}
import { MCPClient } from "@mcp-use/client";

const client = new MCPClient({
  mcpServers: {
    demo: { url: "https://api.example.com/mcp" },
  },
});

// Node: blocks until authorized (loopback). Browser: popup or redirect.
await client.connect("demo");
```

Disable with `oauth: false`. Override options with an `oauth` object on the server config. Pass a custom `authProvider` to skip auto-provisioning.

## Mixed auth

A mixed-auth server allows anonymous MCP connection and public operations, but
requires OAuth for some tools, resources, or prompts. When the server publishes
[RFC 9728 protected-resource metadata](https://www.rfc-editor.org/rfc/rfc9728.html),
the client detects this after the anonymous connection succeeds:

```typescript theme={null}
const connection = await client.connect("demo");
const authorization = await connection.discoverAuthorization();

if (authorization?.mode === "mixed" && !authorization.authenticated) {
  console.log("Public operations are available without signing in.");

  // Optional: authenticate now instead of waiting for a protected operation.
  await connection.authenticate();
}
```

After discovery, `connection.authorization` and `connection.info.authorization`
expose the same state, including the canonical
resource and advertised scopes when the metadata provides them. Detection is
best-effort and defaults to enabled for HTTP servers with an OAuth provider.
Call `discoverAuthorization()` when using `MCPClient` directly; React performs
the same discovery after publishing the ready connection. Set `detectMixedAuth:
false` on the server configuration to skip it.

If you stay anonymous, a later wire-level OAuth challenge from a protected
operation starts the official SDK flow. Automatic flows retry the operation once
after authorization. Explicit browser flows surface the auth action so the host
can authenticate and retry. A tool result with `isError: true` or auth-like text
is not treated as an OAuth challenge.

### React

```tsx theme={null}
const mcp = useMcp({ url: "https://api.example.com/mcp" });

if (mcp.state === "pending_auth") {
  return <button onClick={mcp.authenticate}>Sign in</button>;
}

if (mcp.authorization?.mode === "mixed" && !mcp.authorization.authenticated) {
  return (
    <>
      <p>Public tools are available. Sign in to use protected tools.</p>
      <button onClick={mcp.authenticate}>Authenticate</button>
    </>
  );
}
```

OAuth callback: import `onMcpAuthorization` from `@mcp-use/client/react` on your callback route. See [React integration](/typescript/client/usemcp#oauth-callback).

### Flow modes

| Mode            | Option                  | When                   |
| --------------- | ----------------------- | ---------------------- |
| Popup (default) | —                       | Desktop web            |
| Redirect        | `useRedirectFlow: true` | Mobile, popup blockers |

### Manual browser authorization

Set `preventAutoAuth: true` on a `BrowserOAuthClientProvider` to prepare an
authorization URL without opening it automatically. Read that URL with
`getLastAttemptedAuthUrl()` and present it to the user in the same page
lifetime. The fallback URL is intentionally kept in memory only and is not
available after the provider or page is recreated; start a new authorization
attempt after a reload.

### Pre-registered client

```typescript theme={null}
const client = new MCPClient({
  mcpServers: {
    slack: {
      url: "https://mcp.example.com/mcp",
      oauth: {
        clientId: "my-client-id",
        clientMetadataUrl:
          "https://app.example.com/.well-known/oauth-client-metadata.json",
        scope: "openid profile",
      },
    },
  },
});
```

Browser clients are public PKCE clients — no client secrets in the browser.

### OAuth proxy (browser)

When upstream OAuth endpoints lack CORS:

```typescript theme={null}
useMcp({
  url: "https://mcp.example.com/mcp",
  oauthProxyUrl: "https://app.example.com/api/mcp-oauth",
});
```

## Bearer token

```typescript theme={null}
const client = new MCPClient({
  mcpServers: {
    api: {
      url: "https://api.example.com/mcp",
      authToken: process.env.API_KEY,
    },
  },
});
```

Or use headers (also disables auto-OAuth):

```typescript theme={null}
headers: { Authorization: "Bearer sk-..." }
```

## Server config fields

| Field             | Description                                                                  |
| ----------------- | ---------------------------------------------------------------------------- |
| `authToken`       | Bearer token                                                                 |
| `headers`         | Custom HTTP headers                                                          |
| `oauth`           | OAuth options, or `false` to disable                                         |
| `authProvider`    | Custom SDK-compatible provider                                               |
| `detectMixedAuth` | Discover optional mixed OAuth after anonymous connection; defaults to `true` |

## Node OAuth helpers

```typescript theme={null}
import {
  createOAuthProvider,
  NodeOAuthClientProvider,
  completeOAuthFlow,
  isUnauthorized,
  FileKVStore,
} from "@mcp-use/client";
```

Use these for headless scripts or custom storage. Browser OAuth uses `localStorage` automatically.
