> ## 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.

# React Integration (useMcp & Provider)

> React hooks and providers for MCP client connections

mcp-use provides comprehensive React integration through `McpClientProvider` and the `useMcp` hook. The provider-based approach is recommended for managing multiple MCP server connections in your application.

## Features

* **Multi-server management**: Connect to multiple MCP servers simultaneously
* **Automatic proxy fallback**: Smart fallback to proxy when direct connection fails (FastMCP/CORS)
* **OAuth support**: Complete OAuth flow with token management
* **Notification management**: Track and handle server notifications per server
* **Sampling/Elicitation**: Built-in handling for interactive server requests
* **Type safety**: Full TypeScript support with automatic type inference

<Tip>
  **Recommended Approach**: Use `McpClientProvider` to manage multiple servers
  with automatic proxy fallback, notification management, and persistence
  support. It provides a superior developer experience compared to standalone
  `useMcp()`.
</Tip>

## Quick Start with Provider

```typescript theme={null}
import { McpClientProvider, useMcpClient, useMcpServer } from "mcp-use/react";

// 1. Wrap your app with the provider
function App() {
  return (
    <McpClientProvider
      defaultAutoProxyFallback={true} // Enable automatic proxy fallback
    >
      <MyComponent />
    </McpClientProvider>
  );
}

// 2. Add servers dynamically
function MyComponent() {
  const { addServer, servers } = useMcpClient();

  useEffect(() => {
    addServer("linear", {
      url: "https://mcp.linear.app/mcp",
      name: "Linear",
    });

    addServer("my-server", {
      url: "http://localhost:3000/mcp",
      name: "My Server",
      headers: { Authorization: "Bearer YOUR_API_KEY" },
    });
  }, [addServer]);

  return (
    <div>
      <h2>Connected Servers ({servers.length})</h2>
      {servers.map((server) => (
        <ServerCard key={server.id} server={server} />
      ))}
    </div>
  );
}

// 3. Use individual servers
function ServerCard({ server }) {
  if (server.state !== "ready") {
    return (
      <div>
        {server.name}: {server.state}...
      </div>
    );
  }

  return (
    <div>
      <h3>{server.serverInfo?.name || server.name}</h3>
      <p>Tools: {server.tools.length}</p>
      <button onClick={() => server.callTool("my-tool", {})}>Call Tool</button>
    </div>
  );
}
```

## Automatic Proxy Fallback

The provider includes intelligent automatic proxy fallback for FastMCP and CORS-restricted servers:

```typescript theme={null}
<McpClientProvider
  defaultAutoProxyFallback={true} // Enabled by default
  // Uses https://inspector.mcp-use.com/inspector/api/proxy by default
>
  <MyApp />
</McpClientProvider>
```

**How it works:**

1. **Tries direct connection** first
2. **Detects FastMCP or CORS errors** automatically
3. **Retries with proxy** seamlessly
4. **Success!** Connection established through proxy

**Custom proxy configuration:**

```typescript theme={null}
<McpClientProvider
  defaultAutoProxyFallback={{
    enabled: true,
    proxyAddress: "http://localhost:3005/inspector/api/proxy",
  }}
>
  <MyApp />
</McpClientProvider>
```

**Per-server override:**

```typescript theme={null}
// Disable automatic fallback for a specific server
addServer("my-server", {
  url: "http://localhost:3000/mcp",
  autoProxyFallback: false, // Override provider default
});

// Or use a different proxy for one server
addServer("special-server", {
  url: "https://api.example.com/mcp",
  proxyConfig: {
    proxyAddress: "https://my-custom-proxy.com/api/proxy",
  },
});
```

## Connection States

Each server manages its connection state:

```typescript theme={null}
function ServerStatus({ serverId }) {
  const server = useMcpServer(serverId);

  if (!server) return null;

  switch (server.state) {
    case "discovering":
      return <Spinner>Connecting...</Spinner>;

    case "authenticating":
      return <div>Authenticating... Check for popup window</div>;

    case "pending_auth":
      return (
        <button onClick={server.authenticate}>Click to Authenticate</button>
      );

    case "ready":
      return <div>✅ Connected ({server.tools.length} tools available)</div>;

    case "failed":
      return (
        <div>
          ❌ Connection failed: {server.error}
          <button onClick={server.retry}>Retry</button>
        </div>
      );
  }
}
```

## Provider Configuration

### McpClientProvider Props

```typescript theme={null}
interface McpClientProviderProps {
  // Default OAuth callback URL for all servers (can be overridden per-server via callbackUrl)
  // Useful when your app is mounted at a sub-path  -  e.g. set to "/myapp/oauth/callback"
  // so the OAuth redirect lands on the correct route.
  // Defaults to /oauth/callback on the current origin.
  defaultCallbackUrl?: string;

  // Default proxy configuration for all servers (can be overridden per-server)
  defaultProxyConfig?: {
    proxyAddress?: string;
    headers?: Record<string, string>;
  };

  // Enable automatic proxy fallback (default: true)
  // When a server fails with FastMCP or CORS errors, automatically retries with proxy
  defaultAutoProxyFallback?:
    | boolean
    | {
        enabled?: boolean;
        proxyAddress?: string; // Default: https://inspector.mcp-use.com/inspector/api/proxy
      };

  // Initial servers (auto-connected on mount)
  mcpServers?: Record<string, McpServerOptions>;

  // Persistence
  storageProvider?: StorageProvider;

  // Debugging
  enableRpcLogging?: boolean;

  // Callbacks
  onServerAdded?: (id: string, server: McpServer) => void;
  onServerRemoved?: (id: string) => void;
  onServerStateChange?: (id: string, state: string) => void;
  onSamplingRequest?: (request, serverId, serverName, approve, reject) => void;
  onElicitationRequest?: (
    request,
    serverId,
    serverName,
    approve,
    reject
  ) => void;
}
```

### Server Options

```typescript theme={null}
interface McpServerOptions {
  // Connection
  url?: string; // MCP server URL
  name?: string; // Display name for the server
  enabled?: boolean; // Enable/disable connection (default: true)
  headers?: Record<string, string>; // Auth headers
  transportType?: "auto" | "http" | "sse"; // Transport preference (default: 'auto')
  timeout?: number; // Connection timeout (ms, default: 30000)

  // Proxy (overrides provider defaults)
  proxyConfig?: {
    proxyAddress?: string;
    headers?: Record<string, string>;
  };
  autoProxyFallback?: boolean | { enabled?: boolean; proxyAddress?: string };

  // OAuth
  preventAutoAuth?: boolean; // Prevent automatic OAuth popup (default: true)
  useRedirectFlow?: boolean; // Use redirect instead of popup (default: false)
  callbackUrl?: string; // OAuth callback URL
  authProvider?: OAuthClientProvider; // Optional external OAuth provider (headless/custom runtimes)
  oauth?: {
    clientId?: string;     // Pre-registered OAuth client ID (skips Dynamic Client Registration)
    clientSecret?: string; // Pre-registered client secret for confidential clients without PKCE
    scope?: string;        // OAuth scopes string included in the authorize request
  };
  clientInfo?: {
    name: string;
    version: string;
    description?: string;
    icons?: Array<{ src: string }>;
    websiteUrl?: string;
  };

  // Reconnection & Health Checks
  autoRetry?: boolean | number; // Auto-retry on initial failure
  autoReconnect?: boolean | number | {  // Auto-reconnect on drop (default: 3000ms)
    enabled?: boolean;                  // Enable/disable (default: true)
    initialDelay?: number;              // Delay before reconnect in ms (default: 3000)
    healthCheckInterval?: number | false; // Health check polling in ms, or false to disable (default: 10000)
    healthCheckTimeout?: number;        // Time before connection considered dead in ms (default: 30000)
  };
  reconnectionOptions?: ReconnectionOptions; // SDK-level transport reconnection

  // Advanced
  wrapTransport?: (transport: any, serverId: string) => any;
  onNotification?: (notification: Notification) => void;
  onSampling?: (params) => Promise<CreateMessageResult>;
  onElicitation?: (params) => Promise<ElicitResult>;
}
```

## Authentication

### Bearer Token Authentication

```typescript theme={null}
function MyApp() {
  const { addServer } = useMcpClient();

  useEffect(() => {
    addServer("authenticated-server", {
      url: "http://localhost:3000/mcp",
      name: "My Server",
      headers: {
        Authorization: "Bearer YOUR_API_KEY",
      },
    });
  }, [addServer]);

  return <ServerList />;
}
```

### OAuth Authentication

**Manual OAuth Trigger (Default)**

By default, you need to explicitly trigger OAuth when a server requires authentication:

```typescript theme={null}
function ServerCard({ serverId }) {
  const server = useMcpServer(serverId);

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

  if (server.state === "authenticating") {
    return <div>Authenticating...</div>;
  }

  // ... rest of component
}
```

**Automatic OAuth (Legacy)**

To enable automatic OAuth popup when authentication is required, set `preventAutoAuth: false`:

```typescript theme={null}
function MyApp() {
  const { addServer } = useMcpClient();

  useEffect(() => {
    addServer("linear", {
      url: "https://mcp.linear.app/mcp",
      name: "Linear",
      preventAutoAuth: false, // Auto-trigger OAuth popup
    });
  }, [addServer]);

  return <ServerList />;
}
```

**Redirect Flow** (for mobile or popup-blocked environments)

```typescript theme={null}
addServer("linear", {
  url: "https://mcp.linear.app/mcp",
  name: "Linear",
  useRedirectFlow: true, // Use redirect instead of popup
  // preventAutoAuth: true is the default
});
```

**Pre-registered OAuth Client** (for servers without Dynamic Client Registration)

Some MCP servers strip the `registration_endpoint` from their auth-server metadata, so Dynamic Client Registration is unavailable. Pre-register a client with the upstream provider and pass the credentials via `oauth`:

```typescript theme={null}
addServer("slack", {
  url: "https://mcp.slack.com/slack",
  name: "Slack",
  oauth: {
    clientId: "my-preregistered-client-id",
    clientSecret: "my-preregistered-client-secret", // optional  -  for confidential clients without PKCE
    scope: "openid profile email",
  },
});
```

When `clientSecret` is set alongside `clientId`, the SDK switches token-endpoint authentication from `none` to `client_secret_basic` or `client_secret_post`, depending on what the auth server advertises in `token_endpoint_auth_methods_supported`. See [Authentication](/typescript/client/authentication#pre-registered-client-credentials) for details.

### OAuth Callback Page

Create an OAuth callback route to handle OAuth redirects.

By default, `McpClientProvider` expects the callback at `/oauth/callback` on the current origin. If your app is mounted at a sub-path, set `defaultCallbackUrl` to match your actual route:

```typescript theme={null}
// App mounted at /myapp  -  callback route is /myapp/oauth/callback
<McpClientProvider
  defaultCallbackUrl={`${window.location.origin}/myapp/oauth/callback`}
>
  <MyApp />
</McpClientProvider>
```

Per-server `callbackUrl` in `addServer()` takes precedence over the provider default.

```typescript theme={null}
// app/oauth/callback/page.tsx (Next.js App Router)
// or pages/oauth/callback.tsx (Next.js Pages Router)
import { onMcpAuthorization } from "mcp-use/auth";
// Also available from: import { onMcpAuthorization } from 'mcp-use/react'
import { useEffect } from "react";

export default function OAuthCallback() {
  useEffect(() => {
    // The function handles everything internally:
    // - Displays success/error UI directly in this callback window
    // - Posts message to opener window for popup flow
    // - Automatically redirects for redirect flow
    // - No need for error handling - it's handled internally
    onMcpAuthorization();
  }, []);

  // Simple loading state while processing
  return <div>Processing authentication...</div>;
}
```

<Note>
  The `onMcpAuthorization()` function handles all success and error cases
  internally. For popup flow, it posts a message to the opener window (which
  `useMcp` listens for automatically). For redirect flow, it handles the
  navigation. You don't need custom error handling in your callback component.
</Note>

## Calling Tools

```typescript theme={null}
function ToolExecutor({ serverId }: { serverId: string }) {
  const server = useMcpServer(serverId);
  const [result, setResult] = useState(null);

  if (!server || server.state !== "ready") {
    return <div>Server not ready...</div>;
  }

  const handleSendEmail = async () => {
    try {
      const result = await server.callTool("send-email", {
        to: "user@example.com",
        subject: "Hello",
        body: "Test message",
      });
      setResult(result);
    } catch (error) {
      console.error("Tool call failed:", error);
    }
  };

  return (
    <div>
      <h3>{server.serverInfo?.name} Tools</h3>
      <button onClick={handleSendEmail}>Send Email</button>
      {result && <pre>{JSON.stringify(result, null, 2)}</pre>}

      <h4>Available Tools:</h4>
      <ul>
        {server.tools.map((tool) => (
          <li key={tool.name}>
            {tool.name}: {tool.description}
          </li>
        ))}
      </ul>
    </div>
  );
}
```

## Reading Resources

```typescript theme={null}
function ResourceViewer({ serverId, uri }: { serverId: string; uri: string }) {
  const server = useMcpServer(serverId);
  const [content, setContent] = useState("");

  useEffect(() => {
    if (server?.state === "ready") {
      server.readResource(uri).then((resource) => {
        setContent(resource.contents[0].text || "");
      });
    }
  }, [server?.state, uri]);

  if (!server) return null;

  return (
    <div>
      <h3>
        {server.name} - Resource: {uri}
      </h3>
      <pre>{content}</pre>
    </div>
  );
}
```

## Managing Multiple Servers

```typescript theme={null}
function ServerManager() {
  const { servers, addServer, removeServer } = useMcpClient();

  const handleAddLinear = () => {
    addServer("linear", {
      url: "https://mcp.linear.app/mcp",
      name: "Linear",
    });
  };

  const handleAddLocal = () => {
    addServer("local", {
      url: "http://localhost:3000/mcp",
      name: "Local Server",
      headers: { Authorization: "Bearer key" },
    });
  };

  return (
    <div>
      <button onClick={handleAddLinear}>Add Linear</button>
      <button onClick={handleAddLocal}>Add Local Server</button>

      <h3>Connected Servers ({servers.length})</h3>
      {servers.map((server) => (
        <div key={server.id}>
          <h4>{server.serverInfo?.name || server.name}</h4>
          <p>State: {server.state}</p>
          <p>Tools: {server.tools.length}</p>
          <p>Resources: {server.resources.length}</p>
          <p>Notifications: {server.unreadNotificationCount} unread</p>
          <button onClick={() => removeServer(server.id)}>Remove</button>
        </div>
      ))}
    </div>
  );
}
```

## Persistence

Save server configurations to localStorage:

```typescript theme={null}
import { McpClientProvider, LocalStorageProvider } from "mcp-use/react";

function App() {
  return (
    <McpClientProvider
      storageProvider={new LocalStorageProvider("my-app-servers")}
      defaultAutoProxyFallback={true}
    >
      <MyApp />
    </McpClientProvider>
  );
}
```

Servers added via `addServer()` are automatically saved and restored on page reload.

**Custom Storage Provider:**

```typescript theme={null}
class CustomStorageProvider implements StorageProvider {
  async getServers(): Promise<Record<string, McpServerOptions>> {
    // Load from your backend, IndexedDB, etc.
    return {};
  }

  async setServers(servers: Record<string, McpServerOptions>): Promise<void> {
    // Save to your backend, IndexedDB, etc.
  }
}
```

## Notification Management

Each server maintains its own notification history:

```typescript theme={null}
function NotificationPanel({ serverId }: { serverId: string }) {
  const server = useMcpServer(serverId);

  if (!server) return null;

  return (
    <div>
      <h3>Notifications ({server.unreadNotificationCount} unread)</h3>
      <button onClick={server.markAllNotificationsRead}>Mark All Read</button>
      <button onClick={server.clearNotifications}>Clear All</button>

      <ul>
        {server.notifications.map((notification) => (
          <li
            key={notification.id}
            style={{ fontWeight: notification.read ? "normal" : "bold" }}
            onClick={() => server.markNotificationRead(notification.id)}
          >
            {notification.method}
            <pre>{JSON.stringify(notification.params, null, 2)}</pre>
          </li>
        ))}
      </ul>
    </div>
  );
}
```

## Sampling & Elicitation

Handle interactive server requests (AI sampling, form elicitation). For elicitation, you can use helpers from `mcp-use` (e.g. `acceptWithDefaults`, `validate`) inside your callback; see [Elicitation](/typescript/client/elicitation).

```typescript theme={null}
function SamplingHandler() {
  const { servers } = useMcpClient();

  return (
    <div>
      {servers.map((server) => (
        <div key={server.id}>
          {server.pendingSamplingRequests.map((request) => (
            <div key={request.id}>
              <h4>{server.name} needs AI assistance</h4>
              <pre>{JSON.stringify(request.request.params, null, 2)}</pre>
              <button
                onClick={() =>
                  server.approveSampling(request.id, {
                    content: [{ type: "text", text: "AI response here" }],
                    model: "gpt-4",
                    role: "assistant",
                  })
                }
              >
                Approve
              </button>
              <button onClick={() => server.rejectSampling(request.id)}>
                Reject
              </button>
            </div>
          ))}
        </div>
      ))}
    </div>
  );
}
```

## Error Handling

```typescript theme={null}
function ServerMonitor() {
  const { servers } = useMcpClient();

  return (
    <div>
      {servers.map((server) => (
        <div key={server.id}>
          <h3>{server.name}</h3>

          {server.state === "failed" && (
            <div className="error">
              <p>❌ {server.error}</p>
              <button onClick={server.retry}>Retry Connection</button>

              {/* Common error guidance */}
              {server.error?.includes("401") && (
                <p>💡 Add Authorization header in server configuration</p>
              )}
              {server.error?.includes("CORS") && (
                <p>💡 CORS error - proxy fallback will retry automatically</p>
              )}
              {server.error?.includes("FastMCP") && (
                <p>
                  💡 FastMCP error - proxy fallback will retry automatically
                </p>
              )}
            </div>
          )}

          {server.state === "ready" && (
            <div className="success">
              ✅ Connected - {server.tools.length} tools available
            </div>
          )}
        </div>
      ))}
    </div>
  );
}

// Provider-level error handling
<McpClientProvider
  defaultAutoProxyFallback={true}
  onServerStateChange={(id, state) => {
    console.log(`Server ${id} state changed to: ${state}`);
  }}
  onServerAdded={(id, server) => {
    console.log(`Server ${id} added:`, server);
  }}
>
  <MyApp />
</McpClientProvider>;
```

## Reconnection & Health Checks

When `autoReconnect` is enabled (the default), the hook monitors connection health by sending periodic HEAD requests to the server. If the server becomes unreachable, it automatically reconnects.

### How it works

1. After a successful connection, a health check timer starts
2. Every **10 seconds** (default), a HEAD request is sent to the server URL
3. If no successful response is received for **30 seconds** (default), the connection is considered broken
4. The hook transitions to `"discovering"` state and reconnects after a configurable delay

### Configuration

`autoReconnect` accepts three forms:

```typescript theme={null}
// Boolean: enable with defaults (3s reconnect delay, 10s health check interval)
useMcp({ url: '...', autoReconnect: true })

// Number: custom reconnect delay in ms
useMcp({ url: '...', autoReconnect: 5000 })

// Object: full control over reconnection and health checks
useMcp({
  url: '...',
  autoReconnect: {
    enabled: true,
    initialDelay: 5000,         // Wait 5s before reconnecting
    healthCheckInterval: 30000, // Poll every 30s instead of 10s
    healthCheckTimeout: 60000,  // Wait 60s before declaring dead
  },
})
```

### Disabling health checks

You can disable health check polling entirely while still reconnecting on transport-level failures:

```typescript theme={null}
useMcp({
  url: '...',
  autoReconnect: {
    healthCheckInterval: false, // No HEAD request polling
  },
})
```

### SDK-level reconnection options

The `reconnectionOptions` prop controls the underlying `StreamableHTTPClientTransport` retry behavior, separate from the health check system:

```typescript theme={null}
import type { ReconnectionOptions } from 'mcp-use/react'

useMcp({
  url: '...',
  reconnectionOptions: {
    initialReconnectionDelay: 2000,        // Start with 2s delay (default: 1000)
    maxReconnectionDelay: 60000,           // Cap at 60s (default: 30000)
    reconnectionDelayGrowFactor: 2,        // Double each retry (default: 1.5)
    maxRetries: 5,                         // Retry up to 5 times (default: 2)
  },
})
```

<Note>
  `autoReconnect` controls the **application-level** health monitoring (HEAD request polling and reconnect triggers).
  `reconnectionOptions` controls the **transport-level** retry behavior within the MCP SDK when the SSE stream drops.
  Both can be used together for robust connection handling.
</Note>

## API Reference

### Provider Hooks

#### `useMcpClient()`

Access the multi-server client context:

```typescript theme={null}
const {
  servers,
  addServer,
  removeServer,
  updateServer,
  updateServerMetadata,
  getServer,
  storageLoaded,
} = useMcpClient();

// Add a server
addServer("my-server", {
  url: "http://localhost:3000/mcp",
  name: "My Server",
  headers: { Authorization: "Bearer key" },
});

// Update a server's display name without reconnecting
await updateServerMetadata("my-server", { name: "Production API" });

// Update connection-affecting configuration (disconnects and reconnects)
await updateServer("my-server", {
  headers: { Authorization: "Bearer new-key" },
});

// Remove a server
removeServer("my-server");

// Get a specific server
const server = getServer("my-server");
```

#### `useMcpServer(id)`

Access a specific server's state and methods:

```typescript theme={null}
const server = useMcpServer("my-server");

// Server properties
server.id; // "my-server"
server.name; // "My Server"
server.state; // "ready" | "discovering" | "failed" | ...
server.tools; // Tool[]
server.resources; // Resource[]
server.prompts; // Prompt[]
server.serverInfo; // { name, version, ... }
server.error; // Error message if failed
server.notifications; // McpNotification[]
server.unreadNotificationCount; // number

// Server methods
await server.callTool("tool-name", { args });
await server.readResource("uri");
await server.listResources();
await server.listPrompts();
await server.getPrompt("prompt-name", { args });
server.retry();
server.disconnect();
server.authenticate();
server.clearStorage();
server.markNotificationRead(notificationId);
server.markAllNotificationsRead();
server.clearNotifications();
```

### Server Methods

#### `callTool(name, args, options?)`

```typescript theme={null}
const result = await server.callTool("send-email", {
  to: "user@example.com",
  subject: "Hello",
  body: "Test",
});

// With timeout
const result = await server.callTool(
  "long-task",
  { data: "..." },
  {
    timeout: 300000, // 5 minutes
    resetTimeoutOnProgress: true,
  }
);
```

#### `readResource(uri)`, `listResources()`, `listPrompts()`, `getPrompt()`

Same API as standalone `useMcp`, but accessed per-server.

#### `complete(params)`

Request autocomplete suggestions for prompt arguments or resource template URIs:

```typescript theme={null}
// Complete a prompt argument
const result = await server.complete({
  ref: { type: 'ref/prompt', name: 'code-review' },
  argument: { name: 'language', value: 'py' }
});

console.log('Suggestions:', result.completion.values);
// Output: ['python', 'pytorch', ...]

// Complete a resource template URI variable
const result = await server.complete({
  ref: { type: 'ref/resource', uri: 'file:///{path}' },
  argument: { name: 'path', value: '/home' }
});
```

See [Completions](/typescript/client/completion) for detailed usage and examples.

#### `refreshResourceTemplates()`

Manually refresh the resource templates list from the server:

```typescript theme={null}
await server.refreshResourceTemplates();
console.log('Updated templates:', server.resourceTemplates);
```

The `resourceTemplates` state is automatically populated on connection and updated when notifications are received. Use this method to force a refresh when needed.

## Standalone useMcp Hook

For simple single-server applications, you can use `useMcp` directly without the provider:

```typescript theme={null}
import { useMcp } from "mcp-use/react";

function SimpleApp() {
  const mcp = useMcp({
    url: "http://localhost:3000/mcp",
    headers: { Authorization: "Bearer key" },
    autoProxyFallback: true, // Enable automatic proxy fallback
  });

  if (mcp.state !== "ready") return <div>Connecting...</div>;

  return (
    <div>
      <h2>Tools ({mcp.tools.length})</h2>
      {mcp.tools.map((tool) => (
        <div key={tool.name}>{tool.name}</div>
      ))}
    </div>
  );
}
```

With elicitation (same pattern as the Node client):

```typescript theme={null}
import { useMcp } from "mcp-use/react";
import { acceptWithDefaults } from "mcp-use";

const mcp = useMcp({
  url: "http://localhost:3000/mcp",
  onElicitation: async (params) => acceptWithDefaults(params),
});
```

<Note>
  **For most applications**, use `McpClientProvider` instead of standalone
  `useMcp`. The provider offers better multi-server support, automatic proxy
  fallback, and notification management.
</Note>

## Next Steps

* [Authentication](/typescript/client/authentication) - OAuth and custom auth setup
* [MCPClient](/typescript/client/client-configuration) - Multi-server class-based client
* [Building Agents](/typescript/agent) - AI agents with MCP tools
* [Client Configuration](/typescript/client/client-configuration) - HTTP, SSE, stdio connection types
