mastra-ai/mastra · error · Error

Cannot authenticate MCP server ${serverName}: the provider's

Error message

Cannot authenticate MCP server ${serverName}: the provider's redirect URL must be a loopback address, got ${redirectUrl.origin}.

What it means

Error thrown during runAuthorizationFlow when the provider's redirect URL is not an http:// loopback address. The local OAuth callback server only binds loopback hostnames (localhost/127.0.0.1/etc.) over plain HTTP, so non-loopback or https redirect URLs are rejected before binding.

Source

Thrown at packages/mcp/src/client/configuration.ts:899

    let provider: MCPOAuthClientProvider | undefined;
    let sessionStarted = false;
    let callbackServer: OAuthCallbackServer | undefined;

    // Installed before the first fallible step so the abort-controller entry,
    // provider session, and callback server never leak on an early throw.
    try {
      const config = this.getServerConfig(serverName);
      const candidateProvider = config.authProvider;
      if (!(candidateProvider instanceof MCPOAuthClientProvider)) {
        throw new Error(
          `Cannot authenticate MCP server ${serverName}: it is not configured with an MCPOAuthClientProvider.`,
        );
      }
      provider = candidateProvider;

      const redirectUrl = new URL(provider.redirectUrl.toString());
      if (redirectUrl.protocol !== 'http:' || !isLoopbackHostname(redirectUrl.hostname)) {
        throw new Error(
          `Cannot authenticate MCP server ${serverName}: the provider's redirect URL must be a loopback address, got ${redirectUrl.origin}.`,
        );
      }

      const state = await provider.beginAuthorizationSession();
      sessionStarted = true;
      // A cancel that arrived during beginAuthorizationSession() has no callback
      // server to close yet, so bail here before binding a port and parking.
      throwIfAborted();

      callbackServer = await createOAuthCallbackServer({ redirectUrl, state });
      // A cancel during port binding: bail before we ever wait for a code that
      // will never arrive. The outer finally closes the freshly-bound server.
      throwIfAborted();
      this.authCallbackServersByServer.set(serverName, callbackServer);

      // Point the authorization request at the callback URL that actually
      // bound, and register every fallback candidate during dynamic client

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Change the provider redirectUrl to a loopback http URL, e.g. http://localhost:<port>/callback.
  2. Pick a port (or port range) that is free on the local machine.
  3. Register the loopback redirect URL with the OAuth authorization server if it validates exact redirects.
  4. For remote/web deployments, do not use the local callback flow; use a flow appropriate for server-to-server auth.

Example fix

// before
new MCPOAuthClientProvider({ redirectUrl: 'https://myapp.example.com/callback' })
// after
new MCPOAuthClientProvider({ redirectUrl: 'http://localhost:3456/callback' })
Defensive patterns

Strategy: validation

Validate before calling

const redirectUrl = new URL(provider.redirectUrl.toString());
const isLoopback = ['localhost', '127.0.0.1', '[::1]'].includes(redirectUrl.hostname) || /^127\./.test(redirectUrl.hostname);
if (redirectUrl.protocol !== 'http:' || !isLoopback) {
  throw new Error(`redirectUrl must be http loopback, got ${redirectUrl.origin}`);
}

Type guard

function isLoopbackHttpRedirect(url: URL): boolean {
  return url.protocol === 'http:' && (url.hostname === 'localhost' || /^127\./.test(url.hostname) || url.hostname === '::1');
}

Prevention

When it happens

Trigger: Configuring MCPOAuthClientProvider with redirectUrl such as https://myapp.example.com/callback or http://10.0.0.5:3000/callback, then invoking the authorization flow.

Common situations: Copying a production web-app redirect URL into a local CLI/desktop flow; using https for the local callback; using a LAN hostname or container name instead of localhost.

Understand the failure class

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/a1913f0c25e5ebc1. Report an issue: GitHub.