#!/usr/bin/env node
import {
  Client,
  ListResourcesResultSchema,
  ListToolsResultSchema,
  NodeOAuthClientProvider,
  connectToRemoteServer,
  createLazyAuthCoordinator,
  debugLog,
  discoverOAuthServerInfo,
  hasUsableTokens,
  log,
  parseCommandLineArgs,
  serverIssuesAuthChallenge,
  setupSignalHandlers,
  version
} from "./chunk-MSHFUYEB.js";

// src/client.ts
import { EventEmitter } from "events";

// src/lib/client-diagnostics.ts
function attachClientDiagnostics(client, transport, onClose) {
  const dispatch = transport.onmessage;
  transport.onmessage = (message, extra) => {
    log("Received message:", JSON.stringify(message, null, 2));
    dispatch?.(message, extra);
  };
  client.onerror = (error) => {
    log("Transport error:", error);
  };
  client.onclose = () => {
    log("Connection closed.");
    onClose();
  };
}

// src/client.ts
async function runClient(serverUrl, callbackPath, callbackPort, specifiedPort, headers, transportStrategy = "http-first", host, staticOAuthClientMetadata, staticOAuthClientInfo, clientMetadataUrl, useIdToken, useDeviceCode, authorizeResource, skipResourceParameter, authorizeParams, authTimeoutMs, serverUrlHash) {
  const events = new EventEmitter();
  const strictPort = !!specifiedPort || !!staticOAuthClientInfo || !!clientMetadataUrl;
  const authCoordinator = createLazyAuthCoordinator(serverUrlHash, callbackPath, callbackPort, events, authTimeoutMs, strictPort);
  log("Discovering OAuth server configuration...");
  const discoveryResult = await discoverOAuthServerInfo(serverUrl, headers);
  if (discoveryResult.protectedResourceMetadata) {
    log(`Discovered authorization server: ${discoveryResult.authorizationServerUrl}`);
    if (discoveryResult.protectedResourceMetadata.scopes_supported) {
      debugLog("Protected Resource Metadata scopes", {
        scopes_supported: discoveryResult.protectedResourceMetadata.scopes_supported
      });
    }
  } else {
    debugLog("No Protected Resource Metadata found, using server URL as authorization server");
  }
  const authProvider = new NodeOAuthClientProvider({
    serverUrl: discoveryResult.authorizationServerUrl,
    callbackPath,
    callbackPort,
    host,
    clientName: "MCP CLI Client",
    staticOAuthClientMetadata,
    staticOAuthClientInfo,
    clientMetadataUrl,
    useIdToken,
    useDeviceCode,
    authorizeResource,
    skipResourceParameter,
    authorizeParams,
    serverUrlHash,
    authorizationServerMetadata: discoveryResult.authorizationServerMetadata,
    protectedResourceMetadata: discoveryResult.protectedResourceMetadata,
    wwwAuthenticateScope: discoveryResult.wwwAuthenticateScope
  });
  const client = new Client(
    {
      name: "mcp-remote",
      version
    },
    {
      capabilities: {}
    }
  );
  let server = null;
  const authInitializer = async () => {
    const authState = await authCoordinator.initializeAuth();
    server = authState.server;
    if (authState.actualPort !== callbackPort) {
      log(`Using callback port ${authState.actualPort}`);
      authProvider.setCallbackPort(authState.actualPort);
    }
    return {
      waitForAuthCode: authState.waitForAuthCode,
      skipBrowserAuth: authState.skipBrowserAuth
    };
  };
  if (!useDeviceCode && !await hasUsableTokens(serverUrlHash) && await serverIssuesAuthChallenge(serverUrl, headers)) {
    await authInitializer();
  }
  try {
    const transport = await connectToRemoteServer(client, serverUrl, authProvider, headers, authInitializer, transportStrategy);
    attachClientDiagnostics(client, transport, () => process.exit(0));
    const cleanup = async () => {
      log("\nClosing connection...");
      await client.close();
      if (server) {
        server.close();
      }
    };
    setupSignalHandlers(cleanup);
    log("Connected successfully!");
    try {
      log("Requesting tools list...");
      const tools = await client.request({ method: "tools/list" }, ListToolsResultSchema);
      log("Tools:", JSON.stringify(tools, null, 2));
    } catch (e) {
      log("Error requesting tools list:", e);
    }
    try {
      log("Requesting resource list...");
      const resources = await client.request({ method: "resources/list" }, ListResourcesResultSchema);
      log("Resources:", JSON.stringify(resources, null, 2));
    } catch (e) {
      log("Error requesting resources list:", e);
    }
    log("Exiting OK...");
    if (server) {
      server.close();
    }
    process.exit(0);
  } catch (error) {
    log("Fatal error:", error);
    if (server) {
      server.close();
    }
    process.exit(1);
  }
}
parseCommandLineArgs(process.argv.slice(2), "Usage: mcp-remote-client <https://server-url> [callback-port] [--debug]").then(
  ({
    serverUrl,
    callbackPath,
    callbackPort,
    specifiedPort,
    headers,
    transportStrategy,
    host,
    staticOAuthClientMetadata,
    staticOAuthClientInfo,
    clientMetadataUrl,
    useIdToken,
    useDeviceCode,
    authorizeResource,
    skipResourceParameter,
    authorizeParams,
    authTimeoutMs,
    serverUrlHash
  }) => {
    return runClient(
      serverUrl,
      callbackPath,
      callbackPort,
      specifiedPort,
      headers,
      transportStrategy,
      host,
      staticOAuthClientMetadata,
      staticOAuthClientInfo,
      clientMetadataUrl,
      useIdToken,
      useDeviceCode,
      authorizeResource,
      skipResourceParameter,
      authorizeParams,
      authTimeoutMs,
      serverUrlHash
    );
  }
).catch((error) => {
  console.error("Fatal error:", error);
  process.exit(1);
});
