Authentication

use-mcp includes a robust implementation for handling OAuth flows required by secured MCP servers. It uses a browser-compatible OAuth client provider that handles PKCE (Proof Key for Code Exchange) flows.

How it Works

  1. Discovery: When connecting, if the server responds with a 401/Unauthorized, use-mcp initiates the auth flow.
  2. Popup: It opens a popup window pointing to the authorization URL.
  3. Callback: The user logs in within the popup. The provider redirects to your application's callback route.
  4. Handshake: The callback route communicates the authorization code back to the main window.
  5. Token Exchange: The main window exchanges the code for tokens and retries the connection.

Setting up the Callback Route

To support OAuth, your application must have a route dedicated to handling the OAuth callback. This route simply needs to run the onMcpAuthorization function.

React Router Example

// App.tsx
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { onMcpAuthorization } from 'use-mcp';
import { useEffect } from 'react';

// 1. Create the callback component
function OAuthCallback() {
  useEffect(() => {
    // This function handles parsing the URL code/state and notifying the opener window
    onMcpAuthorization();
  }, []);

  return <div>Authenticating...</div>;
}

// 2. Register the route
function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/oauth/callback" element={<OAuthCallback />} />
        <Route path="/" element={<MainApp />} />
      </Routes>
    </BrowserRouter>
  );
}

Configuring the Hook

When using the hook, ensure the callbackUrl matches the route you defined above.

const mcp = useMcp({
  url: 'https://secure-mcp-server.com/sse',
  // Defaults to current origin + '/oauth/callback'
  callbackUrl: `${window.location.origin}/oauth/callback`,
});

Manual Authentication

Browsers often block popups triggered automatically. use-mcp attempts to handle this by entering a pending_auth state if auto-auth fails or is disabled via preventAutoAuth: true.

You can trigger the auth flow manually using the authenticate() function returned by the hook, which should be called from a user interaction event (like a button click) to bypass popup blockers.